记住的关键是:
箭头函数与函数闭合变量的方式相同,可以关闭“this”。实际上,这是相同的机制。在创建箭头函数的位置,无论“this”是什么,在调用该箭头函数时,“this”都将是什么。“this”永远不会是其他任何东西。箭头函数忽略了它们被调用时的“this”。
如果您记得这一点,您将再也不会困惑于箭头函数中的“this”了。
当您在控制台中运行此片段时,它将产生NaN。如何?作者明确地绑定了x的值,但仍然显示NaN。
numDouble = double.bind({ x: 5 })
创建一个新函数(
numDouble
),当调用它时,它将使用提供为
bind
第一个参数的值(
{ x: 5 }
)调用原始函数(
double
)。但由于箭头函数忽略了它们调用时的“this”,因此
bind
无法控制它们使用的“this”。
作者还指定箭头函数无法绑定“this”。正如我所知道的那样,箭头函数从周围作用域词法地绑定“this”的值。
没错,这意味着您无法更改它。词法绑定是闭包的工作方式。这个箭头函数:
const a = () => {
console.log(typeof this);
};
它正好像传统函数对 thisWhereFunctionWasCreated
所采取的方式一样处理 this
:
最初的回答:
const thisWhereFunctionWasCreated = this;
const t = function() {
console.log(typeof thisWhereFunctionWasCreated);
};
就像在调用函数时无法更改
thisWhereFunctionWasCreated
变量使用的内容一样,当您调用时也无法更改
this
a
使用的内容。 (如果
thisWhereFunctionWasCreated
不是一个
const
,则可以更改它所持有的
值,但不能更改
哪个thisWhereFunctionWasCreated
变量使用。 但是,在该示例中,它是常量,因为
this
是常量。)
由于箭头函数完全忽略了调用它时使用的
this
,因此使用任何机制尝试告诉箭头函数使用哪个
this
都是无效的。无论您是通过将函数作为方法隐式指定
this
(
obj.arrow()
),还是通过
call
或
apply
(
arrow.call(obj)
)指定
this
,还是通过
bind
(
const boundArrow = arrow.bind(obj); boundArrow();
)指定
this
,它仍然会使用它关闭的
this
:
"use strict";
function Ctor() {
this.name = "outerThis";
const outerThis = this;
function traditional(testNum) {
console.log(testNum, "traditional:", getName(this));
}
const arrow = testNum => {
console.log(testNum, "arrow: ", getName(this));
};
console.log("Direct call (default `this`):");
traditional(1);
arrow(1);
console.log("`obj.xyz()`:");
const obj = {
name: "obj",
arrow,
traditional
};
obj.traditional(2);
obj.arrow(2);
console.log("Using `call`:");
traditional.call(obj, 3);
arrow.call(obj, 3);
console.log("Using `bind` and calling result:");
const boundTraditional = traditional.bind(obj);
const boundArrow = arrow.bind(obj);
boundTraditional(4);
boundArrow(4);
}
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));
const arrowWith2 = arrow.bind(null, 2);
console.log(arrowWith2(3));
const arrowWith2And3 = arrow.bind(null, 2, 3);
console.log(arrowWith2And3());
这还将结果函数的名称设置为"bound x"
(其中x
是原始函数的名称。因此,上面的arrowWith2.name
是"bound arrow"
)。
prototype
属性和相关对象,它们没有自己的arguments
绑定,它们没有自己的super
绑定(如果相关的话)...... - T.J. Crowder