要记住的关键是:
- 箭头函数close over
this,正是函数关闭变量的方式。 (实际上,这是相同的机制。)无论this在何处创建箭头函数,this在调用该箭头函数期间都会发生什么。它永远不会是其他任何东西。箭头函数忽略this它们被调用的。
如果您记住了这一点,您就再也不会被this箭头函数所迷惑了。
当您在控制台中运行此代码段时,它会生成 NaN。如何?作者明确绑定了 x 的值,但它仍然显示 NaN。
numDouble = double.bind({ x: 5 })创建一个新函数 ( numDouble),当调用该函数时,它将调用原始函数 ( double) 并this设置为您作为bind第一个参数 ( { x: 5 })提供的值。但是由于箭头函数忽略了this它们的调用方式,bind因此无法控制this它们使用的内容。
作者还指定箭头函数不能绑定 this。据我所知,箭头函数在词法上绑定了围绕作用域的这种形式的值。
是的,这意味着你不能改变它。词法绑定是闭包的工作方式。这个箭头函数:
const a = () => {
console.log(typeof this);
};
治疗this完全相同的方式这种传统的功能对待thisWhereFunctionWasCreated:
const thisWhereFunctionWasCreated = this;
const t = function() {
console.log(typeof thisWhereFunctionWasCreated);
};
就像调用thisWhereFunctionWasCreated变量t时无法更改其this a用途一样,调用它时也无法更改其用途。(如果thisWhereFunctionWasCreated不是 a const,您可以更改它所持有的值,但不能更改使用哪个thisWhereFunctionWasCreated变量 t。但在该示例中它是一个常量,因为this是一个常量。)
由于箭头函数完全忽略了this调用它的方法,因此无论您使用什么机制来尝试告诉箭头函数this使用什么,它都不会起作用。无论您是this通过将函数调用为方法 ( obj.arrow()) 还是通过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
(它还将结果函数的名称设置为"bound x"[wherex是原始函数的名称。所以arrowWith2.name在上面的是"bound arrow"。)