丢失 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 的值 调用将是对 windowundefined 的引用,如果代码恰好在"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);