箭头函数和这个 [英] arrow function and this
问题描述
我在浏览推特时发现了这条推文:
I'm browsing twitter and found this tweet:
https://twitter.com/_ericelliott/status/855598297939144704
这是推文中的代码:
const double = () => this.x * 2;
const numDouble = double.bind({ x: 5 });
numDouble();
当您在控制台中运行此代码段时,它会生成 NaN.如何?作者明确绑定了 x 的值,但仍然显示 NaN.
When you run this snippet in console it'll produce NaN. How? Author is explicitly binding the value of x, but still it's showing NaN.
作者还指定箭头函数不能绑定 this.据我所知,箭头函数在词法上绑定了围绕作用域的这种形式的值.那作者为什么这么说呢?
Author is also specifying that arrow function can't bind this. As i know that arrow function lexically bind the value of this form surrounding scope. Then why author is claiming so?
请澄清我的疑问,并在此先感谢您的帮助.
Please clarify my doubts and Thanks in advance for the help.
推荐答案
要记住的关键是:
- 箭头函数关闭
this
,正是函数关闭变量的方式. (实际上,这是相同的机制.) 无论this
是在何处创建箭头函数,在调用该箭头函数期间this
都会是什么.它永远不会是其他任何东西.箭头函数会忽略调用它们的this
.
- Arrow functions close over
this
, exactly the way that functions close over variables. (In fact, it's the same mechanism.) Whateverthis
is where the arrow function is created is whatthis
will be during a call to that arrow function. It will never be anything else. Arrow functions ignore thethis
they're called with.
如果你记住这一点,你就再也不会被箭头函数中的this
弄糊涂了.
If you remember that, you'll never be confused by this
in an arrow function again.
当您在控制台中运行此代码段时,它会生成 NaN.如何?作者明确绑定了 x 的值,但仍然显示 NaN.
When you run this snippet in console it'll produce NaN. How? Author is explicitly binding the value of x, but still it's showing NaN.
numDouble = double.bind({ x: 5 })
创建一个新函数 (numDouble
),当被调用时,它将调用原始函数 (double
) 并将 this
设置为您提供的值作为 bind
的第一个参数 ({ x: 5 }
).但是由于箭头函数会忽略它们调用时使用的 this
,bind
无法控制它们使用的 this
.
numDouble = double.bind({ x: 5 })
creates a new function (numDouble
) that, when called, will call the original function (double
) with this
set to the value you provide as bind
's first argument ({ x: 5 }
). But since arrow functions ignore the this
they're called with, bind
can't control what this
they use.
作者还指定箭头函数不能绑定 this.据我所知,箭头函数在词法上绑定了围绕作用域的这种形式的值.
Author is also specifying that arrow function can't bind this. As i know that arrow function lexically bind the value of this form surrounding scope.
是的,这意味着您无法更改它.词法绑定是闭包的工作方式.这个箭头函数:
Right, which means you can't change it. Lexical binding is the way closures work. This arrow function:
const a = () => {
console.log(typeof this);
};
对待this
的方式与这个传统函数对待thisWhereFunctionWasCreated
的方式完全一样:
treats this
exactly the way this traditional function treats thisWhereFunctionWasCreated
:
const thisWhereFunctionWasCreated = this;
const t = function() {
console.log(typeof thisWhereFunctionWasCreated);
};
就像你不能改变thisWhereFunctionWasCreated
变量t
在你调用它时使用的内容一样,你也不能改变this
的内容a
在您调用它时使用.(如果 thisWhereFunctionWasCreated
不是 const
,你可以改变它持有的值,但不能thisWhereFunctionWasCreated
变量 t
使用哪个.但在那个例子中它是一个常量,因为 this
是一个常量.)
Just like you can't change what thisWhereFunctionWasCreated
variable t
uses when you call it, you can't change what this
a
uses when you call it. (If thisWhereFunctionWasCreated
weren't a const
, you could change the value it holds, but not which thisWhereFunctionWasCreated
variable t
uses. But it's a constant in that example because this
is a constant.)
因为箭头函数完全忽略了它被调用的this
,所以你用什么机制来告诉箭头函数使用什么this
并不重要,它不会工作.是通过调用函数作为方法 (obj.arrow()
) 或通过 call
或 apply<隐式指定
this
/code> (arrow.call(obj)
),或通过 bind
(const boundArrow = arrow.bind(obj); boundArrow();
>),它仍然会使用它关闭的 this
代替:
Since an arrow function completely ignores the this
it was called with, it doesn't matter what mechanism you use to try to tell the arrow function what this
to use, it won't work. Whether you specify this
implicitly by calling the function as a method (obj.arrow()
), or via call
or apply
(arrow.call(obj)
), or via bind
(const boundArrow = arrow.bind(obj); boundArrow();
), it will still use the this
it closes over instead:
"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
唯一能做的就是将参数绑定到它:
The only thing bind
can do when called on an arrow function is bind arguments to it:
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"
[其中 x
是原始函数的名称.所以 arrowWith2.name
上面是绑定箭头"
.)
(It also sets the name of the resulting function to "bound x"
[where x
is the name of the original function. So arrowWith2.name
in the above is "bound arrow"
.)
这篇关于箭头函数和这个的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!