避免在es6中导出单例

Luc*_*non 3 javascript ecmascript-6 reactjs es6-modules

如我所见,ES6导出对象文字的单例:

// module A
export const singleton = {
  user: 'a',
  asd: 'b'
}

setTimeout(() => console.log(singleton.user), 5000) // 'asd'

// module B
import { singleton } from './A'
singleton.user = 'asd'
Run Code Online (Sandbox Code Playgroud)

即:如果我更改了B中的A导出,也更改了A中以及所有导入A的模块,那么,我希望A导出对象的新实例而不是单例,我做到了:

// module A
export const getObject = () => ({ user: 'asd', asd: 'b' })
Run Code Online (Sandbox Code Playgroud)

那行得通,但是我在想,是否有一种更干净的方法来导出新实例?还是唯一的方法是导出应在B中调用的函数以获取新实例?

我想我也可以这样做,但是不能说服我:

// module A
export const getObject = (() => ({ user: 'asd', asd: 'b' }))()
Run Code Online (Sandbox Code Playgroud)

谢谢

Est*_*ask 5

ES模块在首次导入时仅评估一次,这使模块导出单例有效。

export const getObject = () => ({ user: 'asd', asd: 'b' })
Run Code Online (Sandbox Code Playgroud)

是工厂函数,在这种情况下完全有效,对于没有继承和方法的纯数据对象比较可取。

类是一个合适的替代方法(效率比工厂函数低一些,但是如果有方法的话,则是更好的选择):

export class A {
  constructor() {
    this.user =  'asd';
    this.asd = 'b';
  }
}
Run Code Online (Sandbox Code Playgroud)

由于使用了React,因此可以安全地假定代码是使用Babel进行编译的,因此可以使用类字段提案。它们在ES6中不可用,并且为上面列出的构造函数代码提供语法糖:

export class A {
  user = 'asd';
  asd = 'b';
}
Run Code Online (Sandbox Code Playgroud)