Meteor:为什么我在将function(){} 切换为 () => {} 后丢失了数据上下文?

8

我正在尝试使用ES6,安装了grigio:babel包,并开始逐步更新我的es5代码以使用一些新的ES6语法,但是我遇到了一个问题。

最初我的模板助手看起来像这样:

Template.exampleTemplateName.helpers({
   exampleHelper: function() {
      //returns an array from Mongo Collection
   }
});

这段代码用于在Blaze each循环中使用:

{{#each exampleHelper}}
{{/each}}

如你所料,在这个事件循环中,所有元素的事件处理程序通过exampleHelper返回的Mongo Collection字段可以通过this关键字访问。 this.exampleField会返回我期望的内容。

现在我开始升级到ES6,但某些原因导致以下语法破坏了数据上下文,因此this不再返回预期的结果,而是返回Window

Template.exampleTemplateName.helpers({
    exampleHelper() {
        //returns an array from Mongo Collection
    }
});

上述是我的第一次尝试,然后我尝试了:
Template.exampleTemplateName.helpers({
    exampleHelper: () => {
        //returns an array from Mongo Collection
    }
});

所以我将上述ES6代码通过Babeljs的在线翻译器运行,得到了以下结果,显然是不正确的,因为我不想要一个命名函数:

Template.exampleTemplateName.helpers({
     exampleHelper: function exampleHelper() {}
});

有人能告诉我正确的语法应该是什么样子的吗?

2
据我所知,这实际上是一个特点:箭头函数没有自己的this,它们像任何其他来自父上下文的变量一样闭合this - zwol
那么这种情况下箭头函数就不应该被使用了吗? - Kris
是的,我相信如此。我没有将其发布为答案,因为我不确定,不过。 - zwol
为什么你需要在从Mongo返回一组数据的exampleHelper中引用this?由于你有{{#each exampleHelper}},所以this不会指向该数组中的项。 - CaptSaltyJack
我在exampleHelper中没有引用this,而是在所有绑定到{{#each}}生成的元素的事件处理程序中引用this。这非常方便。 - Kris
2个回答

4

有人能告诉我正确的语法应该是什么样子的吗?

你原来的代码完全没问题。不需要滥用特性,只为了少按几个键等等。在这种情况下,应该使用普通的匿名函数。

你混淆this指向全局对象的原因是因为箭头函数的工作方式:它们具有词法 this,而不是动态的。这意味着this引用在函数创建时就静态地绑定到函数上下文(在你的情况下是window),而不是在运行时动态解析。


事实上,箭头函数甚至不能节省按键次数,方法定义更短(而且正确工作)。 - Bergi

2

这段代码不会起作用(它会显示窗口对象):

Template.homePage.helpers({
  exampleHelper: function () {
    return [
      {text: 'this'}, {text: 'that'}, {text: 'the other thing'}
    ];
  },

  process: () => {
    console.log(this);
  }
});

因为当你使用=>语法时,它想要做如下操作:
var self = this;

process(function () {
  doSomethingWith(self);
});

所以在这种情况下,this确实等于window。解决方法是在这种情况下不使用=>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接