箭头函数和这个 [英] arrow function and this

查看:23
本文介绍了箭头函数和这个的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在浏览推特时发现了这条推文:

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.) Whatever this is where the arrow function is created is what this will be during a call to that arrow function. 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.

当您在控制台中运行此代码段时,它会生成 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 }).但是由于箭头函数会忽略它们调用时使用的 thisbind 无法控制它们使用的 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()) 或通过 callapply<隐式指定 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆