简体   繁体   English

JS 类与普通对象中的箭头函数有何不同

[英]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.

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