避免在es6中导出单例

时间:2018-07-04 19:35:23

标签: javascript reactjs ecmascript-6 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'

ie:如果我更改了B中的A导出,那么在A和所有导入A的模块中也都进行了更改 因此,我希望A导出对象的新实例而不是单例,然后执行此操作:

// module A
export const getObject = () => ({ user: 'asd', asd: 'b' })

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

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

// module A
export const getObject = (() => ({ user: 'asd', asd: 'b' }))()

谢谢

2 个答案:

答案 0 :(得分:3)

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

export const getObject = () => ({ user: 'asd', asd: 'b' })

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

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

export class A {
  constructor() {
    this.user =  'asd';
    this.asd = 'b';
  }
}

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

export class A {
  user = 'asd';
  asd = 'b';
}

答案 1 :(得分:1)

加载模块时,将对其进行缓存。因此,当其他人再次加载它时,不会运行任何新代码。以前的出口刚刚返回。

  

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

如果每次都需要一个新实例,则必须导出一个可以调用以获取新实例的函数。没有其他方法,因为加载先前加载的模块不会运行任何其他代码-它仅返回先前缓存的导出。

您可以导出工厂功能(例如您的示例):

export const myFactory = function() {
   return { user: 'asd', asd: 'b' };
}

或者您可以导出构造函数(调用者将使用new进行调用以获取新对象)。

export class myObj {
   constructor() {
       this.user = 'asd';
       this.asd = 'b';
   }
   checkUser() {
       // some code here that operates on instance data
   }
}

工厂函数或构造函数都可以正常工作。如果没有方法,而只需要一个普通对象,则工厂函数会更简单。如果有方法,则该类可能更有意义。