简体   繁体   English

箭头功能和这个

[英]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: 要记住的关键是:

  • Arrow functions close over 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. 就像你不能改变什么thisWhereFunctionWasCreatedt的用途时,你怎么称呼它,你不能改变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()或通孔) callapplyarrow.call(obj)或通过bindconst 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM