[英]arrow function and this
我正在浏览Twitter,发现了以下推文:
https://twitter.com/_ericelliott/status/855598297939144704
这是推文中的代码:
const double = () => this.x * 2;
const numDouble = double.bind({ x: 5 });
numDouble();
当您在控制台中运行此代码段时,它将生成NaN。 怎么样? 作者显式绑定x的值,但仍显示NaN。
作者还指定了箭头功能不能绑定此功能。 据我所知,箭头功能在词法上绑定了这种形式的范围周围的值。 那为什么作者这么宣称呢?
请澄清我的疑问,并在此先感谢您的帮助。
箭头功能不结合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)
要记住的关键是:
this
关闭, this
恰好是函数在变量上关闭的方式。 (事实上,这是相同的机制。)不管this
是在其中创建箭头的功能是什么this
将是该箭头函数的调用过程。 再也没有其他了。 箭函数忽略了this
他们称之为有。 如果您还记得这一点,那么您再也不会在箭头功能中this
感到困惑。
当您在控制台中运行此代码段时,它将生成NaN。 怎么样? 作者显式绑定x的值,但仍显示NaN。
numDouble = double.bind({ x: 5 })
创建一个新的功能( numDouble
),调用它时,将调用原始功能( double
)与this
设定为您提供作为值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
不是const
,则可以更改其持有的值 ,但不能thisWhereFunctionWasCreated
变量 t
使用的值。但是在该示例中它是一个常量,因为this
是一个常量。)
由于箭头功能完全忽略了this
,它被称为用,它不会不管你用什么机制来试图告诉箭头的功能是什么this
来使用,它不会工作。 是否指定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; }
当在箭头函数上调用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
(它还将结果函数的名称设置为"bound x"
[其中x
是原始函数的名称。因此,上面的arrowWith2.name
是"bound arrow"
。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.