this实际上是在函数被调用时发生的绑定,它指向什么完全取决于函数在哪里被调用
- 对象属性引用链只在引用链的最后一层生效
示例
function foo() {
console.log(this.a)
}
var obj2 = {
a: 42,
foo: foo
}
var obj1 = {
a: 2,
obj2: obj2
}
obj1.obj2.foo() //42
安全的this
function foo(a, b) {
console.log("a:" + a + ",b:" + b)
}
//我们的DMZ空对象
var ø = Object.create(null)
//把数组展开成参数
foo.apply(ø, [2, 3]) //a:2, b:3
//使用bind(...)进行柯里化
var bar = foo.bind(ø, 2)
bar(3) //a:2, b:3
总结如果要判断一个运行中函数的this绑定,就需要找到这个函数的直接调用位置。找到之后就可以顺序应用下面四条规则判断this的绑定对象
- 由new调用?绑定到新创建的对象
- 由call或者apply(或者bind)调用?绑定到指定对象
- 由上下文对象调用?绑定到那个上下文对象
- 默认: 在严格模式下绑定到undefined,否则绑定到全局对象。
注意: 有些调用可能在无意中使用默认绑定规则,如果想要更安全的忽略this绑定,可以使用一个DMZ对象,比如ø = Object.create(null),以保护全局对象
ES6的箭头函数并不会使用四条标准的绑定规则,而是根据当时的词法作用域来决定this,具体来说,箭头函数会继承外层函数调用的this绑定(无论this绑定到什么)。这其实和ES6之前代码中的self = this机制一样