javascript 全局使用一个模块实例的最佳实践

javascript best practice to use one instance of a module globally

我有 javascript 模块 Nodeuser.

节点是一个class:

define(["underscore", "user"], function(_, User) {

class Node {
   // one of the Node attributes needs to access user.prefs in order to figure out what style to output its output in.  user should already be initialized at that point, and it is this initialized version of user that Node must access.
}

return Node

}) // end of define

用户不是一个class:

define(['underscore'], function(_) {

user = {}
function init({username, password}) {
        user.username = username
        // open oauth stuff with username and password
        user.prefs = _.defaults(this._initPrefs(), {
            display_name_capitalization: "title", // bla
            underline_definitions: false, // blablabla
            show_description_on_hover: false, // blabla
        })
}

return user

}) // end of define

然后我 运行 main 中的所有内容,它通过 RequireJS 获取依赖项,初始化用户,然后创建一些节点,然后调用依赖于的节点属性用户:

require(["node", "user"], function(Node, user) {

user.init({
  username: 'Tim',
  password: 'TinyButMighty!',
})
for (n of retrieved_nodes) {
  n = new Node(n)
  doSomethingWith(n.attribute_that_depends_on_user)
}

}) // end of require

由此产生了一些非常具体的问题。

  1. 即使只有一个用户实例,是否有充分的理由使其成为 class? (这是一个不太重要的问题,主要取决于它与以下问题的联系...)

  2. 节点和主要导入用户。这是否意味着将有两个用户副本?如果我在 main 中初始化用户,然后尝试从 Node 访问它,我会访问同一个初始化用户吗?

  3. 在只有一个用户对象在多个模块(主模块、Node 和可能的其他模块)之间共享的情况下,获得此行为的 "best practice" 是什么?我正在考虑使用 window.user = user 而不是使用 return user,但我想确保我以正确的方式做事。 (同样重要的是要考虑到我目前正在使用 RequireJS,但很快就会切换到 Browserify。针对任何一种工具的特定解决方案都可能是一件坏事。我愿意使用 Babel 支持的 ES6 功能,因此今天和将来都会工作。)

问题 2 的答案是 user 只会存在一个实例。 AMD 加载器(以及类似的 CommonJS 环境)加载并执行每个模块一次,然后缓存其 return 值。

由此可见,问题 3 的答案是您不需要做任何特别的事情。公开全局会适得其反(模块的一个收获是您不需要污染全局命名空间)。

至于问题 1,没有理由将某些东西设为 class,如果它不需要是一个,尤其是如果它本来应该代表一个实例的话。既然您只能 return 一个对象,为什么还要创建一个带有单例模式的 class?您已经可以通过在模块工厂函数的闭包中定义函数来实现 "private" 函数,这些函数不会暴露在 return 值上。