使用 Object.assign 和 class/extends 有啥区别?

Posted

技术标签:

【中文标题】使用 Object.assign 和 class/extends 有啥区别?【英文标题】:What are the differences between using Object.assign and class/extends?使用 Object.assign 和 class/extends 有什么区别? 【发布时间】:2016-04-06 07:21:28 【问题描述】:

我试图通过查看他们的flux chat example 的源代码来了解 Facebook Flux 的工作原理。

在那里,我看到了this code:

var MessageStore = assign(, EventEmitter.prototype, 

  emitChange: function() 
    this.emit(CHANGE_EVENT);
  ,

  /**
   * @param function callback
   */
  addChangeListener: function(callback) 
    this.on(CHANGE_EVENT, callback);
  ,
  ...


...

module.exports = MessageStore;

...assign 只是 ES6 规范中的 polyfill Object.assign。

嗯。这个代码,使用类和扩展,会工作吗?会是同一个意思吗?这种方法有什么区别和优点/缺点?

class MessageStore extends EventEmitter 
    emitChange() 
        this.emit(CHANGE_EVENT);
    

    addChangeListener(callback) 
        this.on(CHANGE_EVENT, callback);
    

    ...


module.exports = new MessageStore();

我问,因为来自其他语言,我直观地理解类/扩展,而基于原型的继承对我来说总是有点不清楚。

【问题讨论】:

Object.assign 只复制属性,没有继承。 但是我写的代码应该是等价的,不是吗?也许除了一个只创建和使用一次的类。 相似,但相同,问题 - ***.com/questions/29548562/… 那要看EventEmitter.prototype是否会被修改。如果你想要继承,也可以考虑使用Object.assign(Object.create(EventEmitter.prototype), ...) 嗯。如果修改了EventEmitter.prototype,这两个代码都会做同样的事情,不是吗? 【参考方案1】:

以下是您可以根据 ES6 语法和您的情况使用的工作代码:

import EventEmitter from 'events';
const CHANGE_EVENT = 'change';

class MessageStore extends EventEmitter 

  constructor() 
    super();
  

  addChangeListener = (callback) => 
    this.on(CHANGE_EVENT, callback);
  

  removeChangeListener = (callback) => 
    this.removeListener(CHANGE_EVENT, callback);
  

  emitChange = () => 
    this.emit(CHANGE_EVENT);
  


注意,我更喜欢 ES6 函数字面量语法,因为它确保“this”始终绑定到封闭对象上下文。

如需完整的 ES6 商店示例,请随时查看stores code in my Babel React Starter App

这也是ES6 classes 上的有用参考,它直观地解释了类定义主体内部发生的情况。

【讨论】:

我没有得到函数文字语法。没有它会有什么不同? this 将引用该对象,即使它是一个普通函数,就像我的问题一样,不是吗? @KarelBílek - 你就在这里。然而,更一般地说,其他时候也被咬过,例如从 React.Component 扩展的“辅助函数”。 - 您看到的一个常见模式是需要显式绑定到您使用的函数,例如“onPress=this.onLoginPressed.bind(this)”但是,如果您使用上述语法声明您的 onLoginPressed 函数,例如。 onLoginPressed = () => console.log('尝试使用用户名登录' + this.state.username); 那么你不再需要显式地绑定。例如。只需使用“onPress=this.onLoginPressed”作为结果,更喜欢这种语法,所以毫无疑问。【参考方案2】:

类扩展:* 您正在扩展一个泛型类,这有时正是您想要的,例如button 扩展了 domElement,但 button 不应扩展 EventEmitter,因为它们没有任何共同点。

Object.assign: 使用 Object.assign 您可以将新功能“混合”到目标对象中,例如Store 可以混入 EventEmitter。在 Java 中,您可以使用 Store implements EventEmitter,这更能自我解释。

【讨论】:

以上是关于使用 Object.assign 和 class/extends 有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章

使用 TypeScript 和 Object.assign 给我一个错误“属性 'assign' 在类型 'ObjectConstructor' 上不存在”

Object.assign 的奇怪行为

Object.assign()的使用

Object.assign()合并对象

ES6中Object.assign()和Object.create()

对象传播与 Object.assign