推断this
函数是不是在new中挪用(new绑定)?假如是的话this绑定的是新建立的对象。
bar = new foo()
函数是不是经由过程call、apply(显式绑定)或许硬绑定挪用?假如是的话,this绑定的是指定的对象。
bar = foo.call(obj2)
函数是不是在某个上下文对象中挪用(隐式绑定)?假如是的话,this绑定的是谁人上下文对象。
bar = obj1.foo()
假如都不是的话,运用默许绑定。假如在严厉形式下,就绑定到undefined,不然绑定到全局对象。
bar = foo();
绑定破例
被疏忽的this
假如把null或许undefined作为this的绑定对象传入call、apply或许bind,这些值在挪用时会被疏忽,现实运用的是默许绑定划定规矩。
function foo() {
console.log(this.a);
}
var a = 2;
foo.call(null); //2
然则,老是运用null来疏忽this绑定能够发作一些副作用。假如某个函数确切运用了this,那默许绑定划定规矩会把this绑定到全局对象(在浏览器中全局对象为window),这将致使不可估计的效果(比方修正全局对象)。
不言而喻,这类体式格局能够会致使很多难以剖析和追踪的bug。
更平安的this
一种“更平安”的做法是传入一个特别的对象、把this绑定到这个对象不会对你的递次发作副作用。
在JavaScript中建立一个空对象最简朴的要领都是Object.create(null),然则并不会建立Object.prototype这个托付。
function foo(a, b) {
console.log("a:" + a + ", b:" + b);
}
//建立一个新对象
var emptyObj = Object.create(null);
foo.apply(emptyObj, [2, 3])
var bar = foo.bind(emptyObj, 2);
bar(3);
间接援用
间接援用最轻易在赋值时发作。
function foo() {
console.log(this.a);
}
var a = 2;
var o = {
a: 3,
foo: foo
};
var p = {
a: 4
};
o.foo(); //3
(p.foo = o.foo)() //2
赋值表达式p.foo= o.foo的返回值是目的函数的援用,因而挪用位置是foo()而不是p.foo()或许o.foo(),所以绑定的是全局对象。
小结
假如要推断一个运转中函数的this绑定,就需要找到这个函数的直接挪用位置。找到以后就能够递次运用下面这四条划定规矩来推断this的绑定对象。
由new挪用?绑定到新建立的对象。
由call或许apply(或许bind)挪用?绑定到指定的对象。
由上下文对象挪用?绑定到谁人上下文对象。
默许:在严厉形式下绑定到undefined,不然绑定到全局对象。