我正在浏览推特并发现此推文:
https://twitter.com/_ericelliott/status/855598297939144704
以下是推文中的代码:
const double = () => this.x * 2;
const numDouble = double.bind({ x: 5 });
numDouble();
当您在控制台中运行此代码段时,它将生成NaN。 怎么样? 作者明确地绑定了x的值,但它仍然显示了NaN。
作者还指定箭头函数不能绑定它。据我所知,箭头函数在词法上绑定了这个形式围绕范围的值。那么为什么作者声称呢?
请澄清我的疑虑,并提前感谢您的帮助。
答案 0 :(得分:5)
Arrow functions不要绑定this
。根据MDN:
没有绑定
在箭头函数之前,每个新函数都定义了自己的
this
值 (构造函数中的新对象,在严格模式下未定义) 函数调用,如果函数被调用为上下文对象 "对象方法"等)。事实证明这很烦人 面向对象的编程风格。
因此,您的示例中的this
将是全局对象window
,它显然没有名为x
的属性。
示例:强>
function foo() {
let arrow = () => {
console.log(this); // will use foo's this as arrow will never have its own this
}
arrow.call({"x": "x"}); // ... even if we specify it using bind, call, or apply
}
foo.call({"y": "y"}); // specifying the this for foo (this value will eventually be used by arrow because it will be availbale in its scope)

答案 1 :(得分:2)
要记住的关键是:
this
,正是函数关闭变量的方式。 (实际上,它是相同的机制。)< / em>创建箭头函数的地方this
就是调用该箭头函数期间this
的东西。再也没有其他了。箭头函数会忽略调用它们的this
。如果您还记得这一点,那么您再也不会在箭头功能中被this
所迷惑了。
在控制台中运行此代码段时,它将生成NaN。怎么样?作者已明确绑定x的值,但仍显示NaN。
numDouble = double.bind({ x: 5 })
创建一个新函数(numDouble
),该函数在被调用时将调用原始函数(double
),其中this
设置为您提供的值为{ {1}}的第一个参数(bind
)。但是由于箭头函数会忽略调用它们的{ x: 5 }
,因此this
无法控制它们使用的bind
。
作者还指定了箭头功能不能绑定此功能。据我所知,箭头功能在词法上绑定了这种形式的范围值。
对,这意味着您无法更改它。词汇绑定是闭包的工作方式。此箭头功能:
this
处理const a = () => {
console.log(typeof this);
};
正是此传统函数对待this
的方式:
thisWhereFunctionWasCreated
就像您无法更改const thisWhereFunctionWasCreated = this;
const t = function() {
console.log(typeof thisWhereFunctionWasCreated);
};
变量thisWhereFunctionWasCreated
在调用时使用的内容一样,您也无法更改t
this
在调用它时使用的内容。 (如果a
不是thisWhereFunctionWasCreated
,您可以可以更改其保存的值,但不能更改{{1}变量 const
使用。但是在该示例中它是常量,因为thisWhereFunctionWasCreated
是常量。)
由于箭头函数完全忽略了调用它的t
,因此使用哪种机制尝试告诉箭头函数使用什么this
都没有关系,它将不起作用。通过调用函数作为方法(this
或通过this
或this
(obj.arrow()
)或通过{{1 }}(call
),它仍将使用关闭的apply
来代替:
arrow.call(obj)
bind
const boundArrow = arrow.bind(obj); boundArrow();
只能在将箭头绑定参数时对它进行绑定:
this
(它还将结果函数的名称设置为"use strict";
function Ctor() {
// `this` will be the object created by `new Ctor`; grab it
this.name = "outerThis";
const outerThis = this;
// `traditional` doesn't close over `this`, so you CAN change
// what `this` it uses when you call it, in various ways
function traditional(testNum) {
console.log(testNum, "traditional:", getName(this));
}
// `arrow` closes over `this`, so you CAN'T change
// what `this` it uses when you call it
const arrow = testNum => {
console.log(testNum, "arrow: ", getName(this));
};
// Remember that the `this` in a direct call is the global
// object in loose mode, `undefined` in strict mode; this
// code is in strict mode
console.log("Direct call (default `this`):");
traditional(1); // 1 traditional: window
arrow(1); // 1 arrow: outerThis
console.log("`obj.xyz()`:");
const obj = {
name: "obj",
arrow,
traditional
};
obj.traditional(2); // 2 traditional: obj
obj.arrow(2); // 2 arrow: outerThis
console.log("Using `call`:");
traditional.call(obj, 3); // 3 traditional: obj
arrow.call(obj, 3); // 3 arrow: outerThis
console.log("Using `bind` and calling result:");
const boundTraditional = traditional.bind(obj);
const boundArrow = arrow.bind(obj);
boundTraditional(4); // 4 traditional: obj
boundArrow(4); // 4 arrow: outerThis
}
function getName(t) {
switch (t) {
case undefined:
return "undefined";
case window:
return "window";
default:
return t.name;
}
}
new Ctor();
[其中.as-console-wrapper {
max-height: 100% !important;
}
是原始函数的名称。因此上面的bind
是const arrow = (x, y) => x + y;
console.log(arrow(2, 3)); // 5
const arrowWith2 = arrow.bind(null, 2);
console.log(arrowWith2(3)); // 5
const arrowWith2And3 = arrow.bind(null, 2, 3);
console.log(arrowWith2And3()); // 5
。 )