丢失 this 关键字的显式绑定
Losing Explicit Binding of the `this` Keyword
什么是 example/scenario this
关键字如何失去其显式绑定并被默认绑定覆盖?下面是一个示例代码片段,它使用 call
方法将 this
关键字显式绑定到一个对象。这段代码的哪些理论上的补充可以改变 this
的值?在硬绑定 this
关键字时,我们要保护我们的代码免受哪些具体问题的影响?
function foo(){
console.log(this.bar); // outputs: 9
}
var obj = {
bar: 9
};
foo.call(obj);
通常 this
没有 "explicit" 绑定。 this
的值是根据调用的性质在调用函数时确定的。与函数"birth".
的情况无关
在通过对象 属性 查找发现其引用后调用函数时,如:
obj.someFunction();
那么所涉及的对象引用(obj
,上面)将是函数特定调用中 this
的值。但是,函数引用可以很容易地复制到另一个对象:
var otherObj = { someFunction: obj.someFunction };
otherObj.someFunction();
现在 this
的值(在那个特定的调用中)将是对 otherObj
的引用,而不是 obj
。
如果对函数的引用被复制到普通变量:
var func = obj.someFunction;
func();
中 this
的值 调用将是对 window
或 undefined
的引用,如果代码恰好在"strict" 上下文。
通过所有这些,请注意函数最初可能在对象文字中被声明为 属性 值这一事实与结束的结果 无关 up 是调用中 this
的值。
创建显式 "binding" 的一种方法是利用每个函数实例可用的内置 .call()
或 .apply()
方法:
function whatever() { /* ... */ }
var objWhatever = function() {
whatever.call(obj);
};
该设置明确强制将对 obj
的引用用作函数 whatever()
调用中 this
的值。您还可以使用内置(在现代环境中).bind()
函数来创建这样的 "bound" 函数:
var objWhatever = whatever.bind(obj);
我个人会犹豫将其称为 "bound" 函数,因为在幕后它只是通过 .call()
的显式调用,但我也不担心术语 很多。 :)
由于 Pointy 提到了 this
的值,或者上下文取决于函数的调用方式,这篇文章 Understanding Scope and Context in Javascript 很好地解释了它的工作原理。
添加此代码会覆盖 "explicit" 绑定,this
关键字现在 returns 8
,由 "implicit" 绑定生成=15=] 对象。该函数在该对象的 space 中调用。
var otherObj = {
foo: foo,
bar: 8
};
otherObj.foo();
进一步添加这段代码,由于函数是在全局space中调用的,没有任何修饰,"implicit"绑定被"default"绑定覆盖,returns 全局 bar
变量,结果为 7
.
var secondObj = otherObj.foo;
var bar = 7;
secondObj();
在使用 call
方法调用函数之前添加此代码,将导致将 this
关键字锁定到 secondObj
对象上 - 并导致输出 6
.
var thirdObj = {
bar: 6
};
var foo = foo.bind(thirdObj);
什么是 example/scenario this
关键字如何失去其显式绑定并被默认绑定覆盖?下面是一个示例代码片段,它使用 call
方法将 this
关键字显式绑定到一个对象。这段代码的哪些理论上的补充可以改变 this
的值?在硬绑定 this
关键字时,我们要保护我们的代码免受哪些具体问题的影响?
function foo(){
console.log(this.bar); // outputs: 9
}
var obj = {
bar: 9
};
foo.call(obj);
通常 this
没有 "explicit" 绑定。 this
的值是根据调用的性质在调用函数时确定的。与函数"birth".
在通过对象 属性 查找发现其引用后调用函数时,如:
obj.someFunction();
那么所涉及的对象引用(obj
,上面)将是函数特定调用中 this
的值。但是,函数引用可以很容易地复制到另一个对象:
var otherObj = { someFunction: obj.someFunction };
otherObj.someFunction();
现在 this
的值(在那个特定的调用中)将是对 otherObj
的引用,而不是 obj
。
如果对函数的引用被复制到普通变量:
var func = obj.someFunction;
func();
中 this
的值 调用将是对 window
或 undefined
的引用,如果代码恰好在"strict" 上下文。
通过所有这些,请注意函数最初可能在对象文字中被声明为 属性 值这一事实与结束的结果 无关 up 是调用中 this
的值。
创建显式 "binding" 的一种方法是利用每个函数实例可用的内置 .call()
或 .apply()
方法:
function whatever() { /* ... */ }
var objWhatever = function() {
whatever.call(obj);
};
该设置明确强制将对 obj
的引用用作函数 whatever()
调用中 this
的值。您还可以使用内置(在现代环境中).bind()
函数来创建这样的 "bound" 函数:
var objWhatever = whatever.bind(obj);
我个人会犹豫将其称为 "bound" 函数,因为在幕后它只是通过 .call()
的显式调用,但我也不担心术语 很多。 :)
由于 Pointy 提到了 this
的值,或者上下文取决于函数的调用方式,这篇文章 Understanding Scope and Context in Javascript 很好地解释了它的工作原理。
添加此代码会覆盖 "explicit" 绑定,this
关键字现在 returns 8
,由 "implicit" 绑定生成=15=] 对象。该函数在该对象的 space 中调用。
var otherObj = {
foo: foo,
bar: 8
};
otherObj.foo();
进一步添加这段代码,由于函数是在全局space中调用的,没有任何修饰,"implicit"绑定被"default"绑定覆盖,returns 全局 bar
变量,结果为 7
.
var secondObj = otherObj.foo;
var bar = 7;
secondObj();
在使用 call
方法调用函数之前添加此代码,将导致将 this
关键字锁定到 secondObj
对象上 - 并导致输出 6
.
var thirdObj = {
bar: 6
};
var foo = foo.bind(thirdObj);