[英]arrow function and this
I'm browsing twitter and found this tweet: 我正在浏览Twitter,发现了以下推文:
https://twitter.com/_ericelliott/status/855598297939144704 https://twitter.com/_ericelliott/status/855598297939144704
Here is the code from the tweet: 这是推文中的代码:
const double = () => this.x * 2;
const numDouble = double.bind({ x: 5 });
numDouble();
When you run this snippet in console it'll produce NaN. 当您在控制台中运行此代码段时,它将生成NaN。 How? 怎么样? Author is explicitly binding the value of x, but still it's showing NaN. 作者显式绑定x的值,但仍显示NaN。
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. 请澄清我的疑问,并在此先感谢您的帮助。
Arrow functions don't bind this
. 箭头功能不结合this
。 As per MDN: 根据MDN:
No binding of this 没有约束力
Until arrow functions, every new function defined its own
this
value (a new object in the case of a constructor, undefined in strict mode function calls, the context object if the function is called as an "object method", etc.). 直到箭头的功能,每一个新的函数来定义其自己的this
值(在一个构造的情况下,一个新的对象,在严格模式的函数调用,如果该函数被称为“对象方法”等上下文对象未定义)。 This proved to be annoying with an object-oriented style of programming. 事实证明,这是一种面向对象的编程风格,令人讨厌。
So this
in your example will be the global object window
which apparently don't have a property called x
. 所以, this
在你的榜样将是全局对象window
,这显然没有叫物业x
。
Example: 例:
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)
The key thing to remember is: 要记住的关键是:
this
, exactly the way that functions close over variables. 箭头函数在 this
关闭, this
恰好是函数在变量上关闭的方式。 (In fact, it's the same mechanism.) Whatever this
is where the arrow function is created is what this
will be during a call to that arrow function. (事实上,这是相同的机制。)不管this
是在其中创建箭头的功能是什么this
将是该箭头函数的调用过程。 It will never be anything else. 再也没有其他了。 Arrow functions ignore the this
they're called with. 箭函数忽略了this
他们称之为有。 If you remember that, you'll never be confused by this
in an arrow function again. 如果您还记得这一点,那么您再也不会在箭头功能中this
感到困惑。
When you run this snippet in console it'll produce NaN. 当您在控制台中运行此代码段时,它将生成NaN。 How? 怎么样? Author is explicitly binding the value of x, but still it's showing NaN. 作者显式绑定x的值,但仍显示NaN。
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 }
). numDouble = double.bind({ x: 5 })
创建一个新的功能( numDouble
),调用它时,将调用原始功能( double
)与this
设定为您提供作为值bind
的第一个参数( { x: 5 }
)。 But since arrow functions ignore the this
they're called with, bind
can't control what this
they use. 但是,由于箭头的功能忽略了this
他们称之为有, bind
无法控制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);
};
treats this
exactly the way this traditional function treats thisWhereFunctionWasCreated
: 对待this
正是这种传统的功能对待的方式thisWhereFunctionWasCreated
:
const thisWhereFunctionWasCreated = this;
const t = function() {
console.log(typeof thisWhereFunctionWasCreated);
};
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. 就像你不能改变什么thisWhereFunctionWasCreated
变t
的用途时,你怎么称呼它,你不能改变this
a
,当你调用它的用途。 (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.) (如果thisWhereFunctionWasCreated
不是const
,则可以更改其持有的值 ,但不能thisWhereFunctionWasCreated
变量 t
使用的值。但是在该示例中它是一个常量,因为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. 由于箭头功能完全忽略了this
,它被称为用,它不会不管你用什么机制来试图告诉箭头的功能是什么this
来使用,它不会工作。 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: 是否指定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; }
The only thing bind
can do when called on an arrow function is bind arguments to it: 当在箭头函数上调用bind
时, 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
(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"
.) (它还将结果函数的名称设置为"bound x"
[其中x
是原始函数的名称。因此,上面的arrowWith2.name
是"bound arrow"
。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.