ECMAScript this
在 ECMAScript 中,this 提供了一种更优雅的方式来隐式传递一个对象引用,可以将 API 设计得更加简洁并且易于复用。
this 的绑定和函数声明的位置没有任何关系,只取决于函数的调用方式。
按照绑定的优先级排序
new 绑定
如果函数在 new 中调用,则 this 绑定的是新创建的对象。
function foo(a) {
this.a = a;
}
var bar = new foo(1);
console.log(bar.a); // 输出:1
显式绑定
如果函数通过 call、apply 调用,则 this 绑定的是指定的对象。
function foo() {
console.log(this.a);
}
var obj = {
a:1
};
foo.call(obj); // 输出:1
如果你把 null 或者 undefined 作为 this 的绑定对象传入 call、apply、bind,这些值在调用时会被忽略。
function foo() {
console.log(this.a);
}
var a = 1;
foo.call(null); // 输出:1
隐式绑定
如果函数在某个上下文对象中调用,则 this 绑定的是那个上下文的对象。
function foo() {
console.log(this.a);
}
var obj2 = {
a: 2,
foo: foo
};
var obj1 = {
a: 1,
obj2: obj2
};
obj1.obj2.foo(); // 输出:2
如果函数的调用方式发生改变,就会导致隐式丢失(被隐式绑定的函数丢失绑定对象),结果是默认绑定。
function foo() {
console.log( this.a );
}
var obj = {
a: 1,
foo: foo
};
var a = 2;
var bar = obj.foo;
bar(); // 输出:2
setTimeout(obj.foo, 100); // 输出:2
默认绑定
如果都不是,使用默认绑定。只有运行在非严格下时,默认绑定才能绑定到全局对象,否则会绑定到 undefined。
function foo() {
console.log(this.a);
}
var a = 1;
foo(); // 输出:1
规则例外:箭头函数的绑定
箭头函数不使用 this 的四种标准规则,而是根据当前的词法作用域来决定 this 的绑定。
具体来说,箭头函数会继承外层函数调用的 this 绑定,这其实和 ES6 之前代码中的 self = this
机制一样。
var foo = () => {
console.log(this.a);
}
var obj = {
a: 1
};
var a = 2;
foo.call(obj); // 输出:2