[英]How arrow functions differ in JS Classes vs Normal objects
Why does calling click()
here prints out the value
property.为什么在这里调用click()
会打印出value
属性。
class Button {
constructor(value) {
this.value = value;
}
click = () => {
return this.value;
}
}
let button = new Button("hi")
console.log(button.click()) //hi
And calling click
here prints the value property.调用click
here 会打印 value 属性。
function Button2(value){
this.value = value
this.click = () => {
return this.value
}
}
let button2 = new Button2("hi")
console.log(button2.click()) //hi
However, calling click()
here prints undefined.但是,在这里调用click()
会打印 undefined。 This is what I would expect to happen for both examples, since arrow functions have no this
.这就是我希望这两个示例都会发生的情况,因为箭头函数没有this
。
let button2 = {
value:"hi",
click: () => { return this.value }
}
console.log(button2.click()) //undefined
When printing all 3 objects in devtools, they look identical.在 devtools 中打印所有 3 个对象时,它们看起来相同。
button, button2, and button3 when logged in devtools:登录 devtools 时的按钮、按钮 2 和按钮 3:
{value: "hi", click: ƒ}
click: () => { return this.value }
value: "hi"
__proto__: Object
Why does the first 2 examples print hi
but the third prints undefined
, even though the objects look the same when printed?为什么前两个示例打印hi
但第三个打印undefined
,即使打印时对象看起来相同?
One of the primary concerns of arrow functions is that they inherit the this
keyword from the lexical scope they are defined in. Inside your class, this
refers to the class instance as you would expect, but in your object declaration, this
will refer to the global object window
. One of the primary concerns of arrow functions is that they inherit the this
keyword from the lexical scope they are defined in. Inside your class, this
refers to the class instance as you would expect, but in your object declaration, this
will refer to the全球 object window
。
@trincot makes a good point that the primary distinction is that one of these is callable and one is not - basically, the class
is a function (and you can actually verify this with typeof TestClass === 'function'
) which will form the lexical scope of the arrow method definition, but the object's lexical scope is just the global scope, so this === globalThis === window
. @trincot 提出了一个很好的观点,主要区别是其中一个是可调用的,一个不是 - 基本上, class
是 function (您实际上可以使用typeof TestClass === 'function'
来验证这一点),这将形成lexical scope of the arrow method definition, but the object's lexical scope is just the global scope, so this === globalThis === window
.
You can read the Mozilla docs for more information, and this is basically why it heavily recommends against arrow functions for method definitions.您可以阅读Mozilla 文档以获取更多信息,这基本上就是为什么它强烈建议不要将箭头函数用于方法定义。 (Especially worth noting is that .bind
and .apply
do not work for arrow functions either, and the this
parameter will be ignored.) (特别值得注意的是.bind
和.apply
也不适用于箭头函数,并且this
参数将被忽略。)
class TestClass { // test defined inside TestClass instance scope // returns false test = () => console.log(this === window) } TestObject = { // object defined in global lexical scope // returns true test: () => console.log(this === globalThis && this === window) }; new TestClass().test(); TestObject.test();
The reason is that in the first code block, click
is a public field .原因是在第一个代码块中, click
是一个公共字段。 The documentation on MDN specifies: MDN 上的文档指定:
When initializing fields,
this
refers to the class constructor.初始化字段时,this
指的是 class 构造函数。
By consequence, if that initialisation is an arrow function, then the lexical this
at the time of execution of that function will be the same this
.因此,如果该初始化是箭头 function,那么执行该 function 时的词法this
将与this
相同。 And it is a given that the this
value of the class constructor is the instance .并且给定 class 构造函数的this
值是实例。
This principle is further clarified when we represent that first code block without using class
syntax:当我们在不使用class
语法的情况下表示第一个代码块时,这一原则将得到进一步阐明:
function Button(value) {
this.value = value;
this.click = () => {
return this.value;
}
}
All this
in this code are the same this
(a consequence of "lexical this" ). this
代码中的所有这些都与this
相同( “lexical this”的结果)。
The second code block has a plain old object property click
.第二个代码块有一个普通的旧 object 属性click
。 An object does not define this
for the arrow functions that may be defined for its properties. object 没有为可能为其属性定义的箭头函数定义this
。 Only functions ( function
, possibly constructors) define this
by the way they are called.只有函数( function
,可能是构造函数)通过调用它们的方式来定义this
。 Your object is not called (it is not callable), and the way you call an arrow function has no influence on this
either.您的 object 未被调用(它不可调用),并且您调用箭头 function 的方式this
也没有影响。 So the this
that occurs within the arrow function here, is determined by the larger context, which could be a wrapping function (not represented in your example), and how it is called.所以this
发生在箭头 function 中的 this 由更大的上下文决定,这可能是一个包装 function (在您的示例中未表示),以及它是如何被调用的。 Or, by absence of such a context, this
is the global object (or in strict mode: undefined
).或者,由于没有这样的上下文, this
是全局 object (或在严格模式下: undefined
)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.