← Back Home

JS 中的 this 详解

  1. JavaScript

本文记录对 JS 中 this 的详解

this的绑定方式

默认绑定

没调用对象指向全局


function foo() {
    console.log(this.a);
}
var a = 1;
foo();//1

隐式绑定


var a = 1;
function foo() {
    console.log(this.a);        
}
var obj = {
    a: 2,
    foo: foo
}
obj.foo();//2
var bar = obj.foo;
bar();//1

显式绑定


function foo() {
    console.log(this.a);        
}
var a = 1;
var obj = {
    a: 2
}

foo.call(obj);//2
foo.apply(obj);//2
var bar = foo.bind(obj);
bar();//2

new绑定

function foo(a) {
    this.a = a;
}

var a = 1;

var bar = new foo(3);
console.log(bar.a);//3

各绑定方式的优先级

显示与隐式的比较


function foo() {
    console.log(this.a);
}

var obj1 = {
    a: 1,
    foo: foo
}
var obj2 = {
    a: 2
}

obj1.foo();//1
obj1.foo.call(obj2);//2

所以显式优先级高于隐式

new与隐式的比较


function foo(a) {
    this.a = a;
}
var obj = {
    a: 1,
    foo: foo
}

obj.foo(2);
console.log(obj.a);//2

var bar = new obj.foo(3);
console.log(obj.a);//2此时obj.foo(3)未起作用,new优先级大于隐式
console.log(bar.a);//3

显式与new的比较


function foo(a) {
    this.a = a;
}

var obj = {};

var bar = foo.bind(obj);
bar(2);
console.log(obj.a);//2

var baz = new bar(3);
console.log(obj.a);//2使用new未将obj.a改变为3,显式优先级高于new
console.log(baz.a);//3this绑定新创建的对象baz

bind的用法

一般情况下在使用对象调用函数是会使用以下方式书写,将对象赋值给函数内部的局部变量,调用函数时能从局部变量中获取

var x = 10;
var myObj = {
    x: 0,
    deal: function() {
        var that = this;
        return function() {
            return ++that.x;
        }
    }
};

var aaa = myObj.deal();
console.log(aaa());//1

不将对象赋值到函数内部的局部变量,函数调用时从全局中去获取

var aaa = myObj.deal();
console.log(aaa());//1

var x = 10;
var myObj = {
    x: 0,
    deal: function() {
        return function() {
            return ++this.x;
        }
    }
};

var aaa = myObj.deal();
console.log(aaa());//11

bind相当于将myObj(上下文)传入到函数中

var x = 10;
var myObj = {
    x: 0,
    deal: function() {
        return (function() {
            return ++this.x;
        }).bind(this);
    }
};

var aaa = myObj.deal();
console.log(aaa());//1

bind使用参数的形式传入时

function foo(p1) {
    this.val = p1;
}

var baz = foo.bind(null, 'p1');
var bar = new baz('p2');
console.log(bar.val);//p1
function foo(p1, p2) {
    this.val = p1 + p2;
}

var baz = foo.bind(null, 'p1');
var bar = new baz('p2');
console.log(bar.val);//p1p2
function foo(p1) {
    this.val = p1;
}

var baz = foo.bind('p1');
var bar = new baz('p2');
console.log(bar.val);//p2

使用new新建对象时即被忽略

null、undefined作为this绑定对象传入call、apply和bind时,实际应用的是默认绑定规则


function foo() {
    console.log(this.a);
}
var a = 1;
foo.call(null);//1

绑定到全局的this改为局部,使用空集合符号


var Ø = Object.create(null);
function foo() {
    console.log(this.a);
}
foo.call(Ø);//undefined

ES6箭头函数中的this(与self=this的机制一样)

以下例子需要ES6环境下使用,可参考https://github.com/PLDaily/ES6


var Person = function() {
    this.name = 'pcd';
    this.hello = () => {
        console.log(this.name);//this在定义是已经被锁死
    }
}

var bb = new Person();
bb.hello.bind({"name": "dcp"});
bb.hello();//pcd

注意事项

var a;
a++;
console.log(a);//NaN
comments powered by Disqus