关于this
this即不指向函数自身也不指向函数的词法作用域
不要妄图使用this来引用一个词法作用域内部的东西。也就是说无法实现this与词法作用域的查找混合使用。
function foo() {
var a = 2;
this.bar();
}
function bar() {
console.log( this.a );
}
foo(); // ReferenceError: a is not defined
this到底是什么?
this的绑定与声明和函数声明的位置没有任何关系,只取决于函数的调用方式。当一个函数被调用时,会创建一个活动记录(有时候也称为执行上下文)。这个记录会包 含函数在哪里被调用(调用栈)、函数的调用方法、传入的参数等信息。this 就是记录的其中一个属性,会在函数执行的过程中用到。
this的绑定规则
- 默认绑定
非严格模式下且未使用其他绑定规则this绑定到全局对象,严格模式下为undefined - 隐式绑定
当函数引用有上下文对象时,隐式绑定会把函数调用中的this绑定到这个上下文对象。
隐式丢失:隐式赋值是造成this绑定丢失的常见原因
function foo() {
console.log( this.a );
}
var obj = {
a: 2,
foo: foo
};
var bar = obj.foo; // 函数别名!引用的是foo函数本身
var a = "oops, global"; // a 是全局对象的属性 bar(); // "oops, global"
- 显式绑定
使用bind或者apply强制绑定this
当传入的原始值为字符串,布尔或数字类型来做this的绑定对象时,原始值会被自动转换为他的对象形式(new String(…)、new Boolean(…)、new Number(…)
显式绑定仍然无法解决绑定丢失问题
可以使用硬绑定的方式来解决显式绑定this丢失问题
function foo(something) {
console.log( this.a, something );
return this.a + something;
}
var obj = { a:2 };
var bar = foo.bind( obj );
var b = bar( 3 ); // 2 3 console.log( b ); // 5
- new绑定
使用new来调用函数会自动执行以下操作- 创建(或者说构造)一个全新的对象。
- 这个新对象会被执行[[ 原型 ]]连接。
- 这个新对象会被绑定到函数调用的this。
- 如果函数没有返回其他对象,那么new表达式中的函数调用会自动返回这个新对象。
- 优先级
new绑定>显示绑定>隐式绑定>默认绑定 - 判断this
- 函数是否在 new 中调用(new 绑定)?如果是的话 this 绑定的是新创建的对象。 var bar = new foo()
- 函数是否通过 call、apply(显式绑定)或者硬绑定调用?如果是的话,this 绑定的是 指定的对象。 var bar = foo.call(obj2)
- 函数是否在某个上下文对象中调用(隐式绑定)?如果是的话,this 绑定的是那个上 下文对象。 var bar = obj1.foo()
- 如果都不是的话,使用默认绑定。如果在严格模式下,就绑定到 undefined,否则绑定到 全局对象。 var bar = foo()
- 特例:
将null或者undefined作为this的绑定对象传入call、apply或者bind时,在调用的时候会被忽略,此时应用默认绑定规则。