箭头功能和

时间:2017-04-22 11:34:29

标签: javascript ecmascript-6

我正在浏览推特并发现此推文:

https://twitter.com/_ericelliott/status/855598297939144704

以下是推文中的代码:

const double = () => this.x * 2;
const numDouble = double.bind({ x: 5 });
numDouble();

当您在控制台中运行此代码段时,它将生成NaN。 怎么样? 作者明确地绑定了x的值,但它仍然显示了NaN。

作者还指定箭头函数不能绑定它。据我所知,箭头函数在词法上绑定了这个形式围绕范围的值。那么为什么作者声称呢?

请澄清我的疑虑,并提前感谢您的帮助。

2 个答案:

答案 0 :(得分:5)

Arrow functions不要绑定this。根据MDN:

  

没有绑定

     

在箭头函数之前,每个新函数都定义了自己的this值   (构造函数中的新对象,在严格模式下未定义)   函数调用,如果函数被调用为上下文对象   "对象方法"等)。事实证明这很烦人   面向对象的编程风格。

因此,您的示例中的this将是全局对象window,它显然没有名为x的属性。

示例:



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)




答案 1 :(得分:2)

要记住的关键是:

  • 箭头函数关闭 this,正是函数关闭变量的方式。 (实际上,它是相同的机制。)< / em>创建箭头函数的地方this就是调用该箭头函数期间this的东西。再也没有其他了。箭头函数会忽略调用它们的this

如果您还记得这一点,那么您再也不会在箭头功能中被this所迷惑了。

  

在控制台中运行此代码段时,它将生成NaN。怎么样?作者已明确绑定x的值,但仍显示NaN。

numDouble = double.bind({ x: 5 })创建一个新函数(numDouble),该函数在被调用时将调用原始函数(double),其中this设置为您提供的值为{ {1}}的第一个参数(bind)。但是由于箭头函数会忽略调用它们的{ x: 5 },因此this无法控制它们使用的bind

  

作者还指定了箭头功能不能绑定此功能。据我所知,箭头功能在词法上绑定了这种形式的范围值。

对,这意味着您无法更改它。词汇绑定是闭包的工作方式。此箭头功能:

this

处理const a = () => { console.log(typeof this); }; 正是此传统函数对待this的方式:

thisWhereFunctionWasCreated

就像您无法更改const thisWhereFunctionWasCreated = this; const t = function() { console.log(typeof thisWhereFunctionWasCreated); }; 变量thisWhereFunctionWasCreated在调用时使用的内容一样,您也无法更改t this在调用它时使用的内容。 (如果a不是thisWhereFunctionWasCreated,您可以可以更改其保存的,但不能更改{{1}变量 const使用。但是在该示例中它是常量,因为thisWhereFunctionWasCreated是常量。)

由于箭头函数完全忽略了调用它的t,因此使用哪种机制尝试告诉箭头函数使用什么this都没有关系,它将不起作用。通过调用函数作为方法(this或通过thisthisobj.arrow())或通过{{1 }}(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; }是原始函数的名称。因此上面的bindconst 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。 )