【问题标题】:Explain effect of ES6 class constructor and arrow functions解释 ES6 类构造函数和箭头函数的作用
【发布时间】:2015-03-31 19:09:59
【问题描述】:

我目前正在特别学习 JS 和 ES6。我无法理解为什么我的带有类构造函数和箭头函数的代码如果不进行一些更改就无法工作。

这是我开始的地方,一个 ES6 模块导出这个类似通量的调度程序对象。

// RiotControl dispatcher formatted as ES6 module.
// https://github.com/jimsparkman/RiotControl

var dispatcher = {
  stores: [],
  addStore: function(store) {
    this.stores.push(store);
  }
};

['on','one','off','trigger'].forEach(function(api){
  dispatcher[api] = function() {
    var args = [].slice.call(arguments);
    this.stores.forEach(function(el){
      el[api].apply(null, args);
    });
  };
});

export default dispatcher

我想用这段代码创建一个类,结果是:

// RiotControl dispatcher formatted as ES6 class module.
// https://github.com/jimsparkman/RiotControl

export default class {
  constructor() {        
    this.stores = []    
    this.addStore = store => {
      this.stores.push(store);
    }

    ['on','one','off','trigger'].forEach(fn => {
      this[fn] = () => {
        var args = [].slice.call(arguments)
        this.stores.forEach(function(el){
          el[fn].apply(null, args)
        })
      }
    })
  }
}

由于我不知道的原因,这不起作用。

  1. 第一个.forEach(...) 结果为Uncaught TypeError: Cannot read property 'forEach' of undefined,就好像数组没有定义一样。
  2. var args = [].slice.call(arguments) 导致 args 是一个零长度数组,而不是实际上,嗯,有参数。

为了使代码正常工作,我将其更改为:

// RiotControl dispatcher formatted as ES6 class module.
// https://github.com/jimsparkman/RiotControl

export default class {
  constructor() {        
    this.stores = []    
    this.addStore = store => {
      this.stores.push(store);
    }

    var api = ['on','one','off','trigger']
    api.forEach(fn => {
      this[fn] = function() {
        var args = [].slice.call(arguments)
        this.stores.forEach(function(el){
          el[fn].apply(null, args)
        })
      }
    })
  }
}

因此,错误已由

修复
  1. 声明一个数组并在上面调用.forEach,然后
  2. 使用常规回调函数而不是箭头函数。

请解释为什么带有内联数组的forEach 会失败,以及为什么从箭头函数内部切片参数列表会失败。

另外,额外的问题,为什么'this.stores.foreach'中的this绑定到我的对象实例而不是例如导致函数被调用的事件?

【问题讨论】:

  • 如果使用分隔符;,是否还会出现错误?你好像对它们过敏
  • 正确,缺少分号是错误 #1 的原因。我不过敏,但我看过的几个库似乎省略了分隔符。我只需要学习规则并采用约定来使用或不使用它们。不过,使用它们似乎更安全。

标签: javascript arrays class module ecmascript-6


【解决方案1】:

请解释为什么带有内联数组的forEach 会失败,以及为什么从箭头函数内部切片参数列表会失败。

代码解释如下:

this.addStore = store => { ... }['on','one','off','trigger'].forEach(...)
// which becomes
this.addStore = store => { ... }['trigger'].forEach(...)

即您正在尝试访问函数的 trigger 属性,该属性当然不存在。在函数定义后使用分号显式终止赋值表达式:

this.addStore = store => {
  this.stores.push(store);
};
['on','one','off','trigger'].forEach(...);

另外,额外的问题,为什么 this.stores.foreach 中的 this 绑定到我的对象实例而不是例如导致函数被调用的事件?

this 未在此处绑定。 this 所指的内容取决于函数的调用方式,您不应该显示。


var args = [].slice.call(arguments) 导致 args 是一个零长度数组,而不是实际上,嗯,有参数。

在箭头函数中,thisarguments 都是词法范围的。 IE。箭头函数没有自己的 arguments 对象。

【讨论】:

  • 谢谢,很好的回答!既然你解释了它就很有意义了。
  • 如果可以,请在您的回答中编辑这个错字:this 所指的内容取决于函数的调用方式,您不应该 [=> 不要] 显示。跨度>
猜你喜欢
  • 2017-11-21
  • 2018-08-01
  • 2020-08-24
  • 1970-01-01
  • 1970-01-01
  • 2019-02-19
  • 2019-01-06
  • 1970-01-01
相关资源
最近更新 更多