【问题标题】:ES6 arrow functions not working on the prototype?ES6 箭头函数不适用于原型?
【发布时间】:2023-02-10 05:04:21
【问题描述】:

当 ES6 箭头函数似乎无法将函数分配给具有 prototype.object 的对象时。考虑以下示例:

function Animal(name, type){
 this.name = name;
  this.type = type;
  this.toString = () => `${this.name} is a ${this.type}`;

}
var myDog = new Animal('Max', 'Dog');
console.log(myDog.toString()); //Max is a Dog

在对象定义中显式使用箭头函数是可行的,但使用带有 Object.prototype 语法的箭头函数则不行:

function Animal2(name, type){
  this.name = name;
  this.type = type;
}
Animal2.prototype.toString = () => `${this.name} is a ${this.type}`;

var myPet2 = new Animal2('Noah', 'cat');
console.log(myPet2.toString()); //is a undefined

作为概念证明,将模板字符串语法与 Object.prototype 语法一起使用确实有效:

function Animal3(name, type){
  this.name = name;
  this.type = type;
}
Animal3.prototype.toString = function(){ return `${this.name} is a ${this.type}`;}

var myPet3 = new Animal3('Joey', 'Kangaroo');
console.log(myPet3.toString()); //Joey is a Kangaroo

我错过了一些明显的东西吗?我觉得示例 2 应该符合逻辑,但我对输出感到困惑。我猜这是一个范围界定问题,但我对输出“未定义”感到困惑。

ES6 Fiddle

【问题讨论】:

  • @Bergi 我的问题是 10 个月前发布的,有 0 个赞成票。它怎么可能与 5 个月前发布的问题重复,为什么现在决定这个问题很重要?
  • 这里没有指责(注意我也没有关闭问题,只是发表了评论)。唯一重要的是未来的读者会被引导到关于这个主题的非常有用的规范帖子,这就是我链接它的原因。

标签: javascript prototype ecmascript-6 arrow-functions


【解决方案1】:

箭头函数提供词法 this。它使用在计算函数时可用的 this

它在逻辑上等同于(以下不是有效代码,因为您不能拥有名为this 的变量):

(function(this){
   // code that uses "this"
 })(this)

在您的第一个示例中,箭头函数位于构造函数中,this 指向新生成的实例。

在您的第三个示例中,未使用箭头函数并且标准 this 行为一如既往地工作(函数范围内的 this )。

在你的第二个例子中,你使用了一个箭头函数,但在它被评估的范围内,this 是全局的/未定义的。

【讨论】:

  • 那么是不是不可能在构造函数之外将它与箭头函数一起使用(示例 2)?
  • 您可以在this 是您想要的this 的任何地方使用它。例如,假设您的对象有一个 setup() 函数,它向自身添加多个函数,您可以这样称呼它:myObj.setup()。该函数可以使用箭头函数来添加所需的函数。另一个更典型的用例是使用需要访问初始上下文的 this 的回调函数。
  • “箭头函数提供了一个词法 this”更准确的说法是箭头函数不提供 this,因此它不是来自其自身的词法范围,而是来自外部词法范围。
  • 我认为它更等同于function(){}.bind(this)。它预先绑定到创建它的范围的this。这在例如事件监听器,我们经常想在监听器内部使用周围范围的东西。在 es5 代码中,它意味着在附加侦听器或使用 bind 之前执行 var me = this
  • “它使用在评估函数时可用的 this。”具有误导性。建议:“它使用存在于创建函数的上下文中的 this。”或者更好:“箭头函数根本没有自己的this。它们关闭创建它们的上下文的this,就像关闭创建它们的变量一样。(它们也关闭arguments以及相关的super。)”
【解决方案2】:

常规函数返回对当前 JavaScript 对象的引用,但箭头函数返回对全局窗口对象的引用。

常规函数可以很好地处理使用 new 关键字的对象。他们有构造函数可以在对象创建期间初始化值的函数。它可以使用原型链接但是箭头函数没有构造函数,原型链接.他们不能很好地处理对象。它们不能与用于分配内存的 new 关键字一起使用。

在您的第一个示例中,您在常规函数中编写箭头键函数,然后您将获得输出。

function Animal2(name, type){
    this.name = name;
    this.type = type;
}
Animal2.prototype.toString = function(){
    return () => `${this.name} is a ${this.type}`;
}

var myPet2 = new Animal2('Noah', 'cat');
console.log(myPet2.toString()()); //Noah is a cat

参考:Difference between regular function and arrow key function

【讨论】:

    【解决方案3】:

    箭头函数没有自己的 this ,它解析为最近函数的 this

    • 您的第一个示例:this 解析为 Animal() 函数的 this
    • 你的第二个例子:this解析为全局对象window(因为它不在任何函数内)
    • 您的第三个示例:this 一直按预期工作,因为没有使用箭头函数。

    【讨论】:

      【解决方案4】:

      应该注意的是,箭头函数本身没有 this 并且每个箭头函数中的 this 关键字始终指的是词法范围,因此在您的第一个示例中, this 关键字指的是 Animal 类。在您的第二个示例中,this 关键字指的是全局范围。在第三个例子中,由于toString方法属于Animal类原型,因此它可以访问Animal类作用域,换句话说,原型方法中的this关键字是指原型所有者。

      这里有一些有用的链接:

      https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this

      https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain

      【讨论】:

      • 正如目前所写,您的答案尚不清楚。请edit 添加更多详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写出好的答案的信息in the help center
      猜你喜欢
      • 2015-10-23
      • 2019-01-06
      • 1970-01-01
      • 2018-01-29
      • 1970-01-01
      • 2016-09-07
      • 2022-01-21
      • 2016-03-25
      相关资源
      最近更新 更多