CommonJS 模块模式

Nem*_*mus 2 javascript module-pattern commonjs node.js

我把这个取自

\n\n

通量架构

\n\n
var AppDispatcher = require(\'../dispatcher/AppDispatcher\');\nvar EventEmitter = require(\'events\').EventEmitter;\nvar TodoConstants = require(\'../constants/TodoConstants\');\nvar assign = require(\'object-assign\');\n\nvar CHANGE_EVENT = \'change\';\n\nvar _todos = {}; // collection of todo items\n\n/**\n * Create a TODO item.\n * @param {string} text The content of the TODO\n */\nfunction create(text) {\n  // Using the current timestamp in place of a real id.\n  var id = Date.now();\n  _todos[id] = {\n    id: id,\n    complete: false,\n    text: text\n  };\n}\n\n/**\n * Delete a TODO item.\n * @param {string} id\n */\nfunction destroy(id) {\n  delete _todos[id];\n}\n\nvar TodoStore = assign({}, EventEmitter.prototype, {\n\n  /**\n   * Get the entire collection of TODOs.\n   * @return {object}\n   */\n  getAll: function() {\n    return _todos;\n  },\n\n  emitChange: function() {\n    this.emit(CHANGE_EVENT);\n  },\n\n  /**\n   * @param {function} callback\n   */\n  addChangeListener: function(callback) {\n    this.on(CHANGE_EVENT, callback);\n  },\n\n  /**\n   * @param {function} callback\n   */\n  removeChangeListener: function(callback) {\n    this.removeListener(CHANGE_EVENT, callback);\n  },\n\n  dispatcherIndex: AppDispatcher.register(function(payload) {\n    var action = payload.action;\n    var text;\n\n    switch(action.actionType) {\n      case TodoConstants.TODO_CREATE:\n        text = action.text.trim();\n        if (text !== \'\') {\n          create(text);\n          TodoStore.emitChange();\n        }\n        break;\n\n      case TodoConstants.TODO_DESTROY:\n        destroy(action.id);\n        TodoStore.emitChange();\n        break;\n\n      // add more cases for other actionTypes, like TODO_UPDATE, etc.\n    }\n\n    return true; // No errors. Needed by promise in Dispatcher.\n  })\n\n});\n
Run Code Online (Sandbox Code Playgroud)\n\n

它说的地方

\n\n
\n

上面的代码中有一些重要的事情需要注意。首先,我们维护一个名为 _todos 的私有数据结构。该对象包含所有单独的待办事项。因为该变量位于类之外,但在模块的闭包内,所以它仍然是私有的\xe2\x80\x94,因此不能从模块外部直接更改。这有助于我们为数据流保留独特的输入/输出接口,使得不使用操作就无法更新存储。

\n
\n\n

粗体部分我不清楚。js 解释器如何知道所有这些代码都在模块闭包内而不是在全局范围内?\n模块闭包从哪里开始到哪里结束?

\n\n

据我所知

\n\n
\n

用 var 声明的变量的范围是其当前执行上下文,它可以是封闭函数,或者对于在任何函数外部声明的变量,可以是 global

\n
\n\n

有什么解释吗?

\n

Art*_*hur 5

您实际上缺少引用的摘录中的最后一行:

module.exports = TodoStore;
Run Code Online (Sandbox Code Playgroud)

CommonJS 是一个 API,用于定义使用以下约定的模块:

  • 每个文件定义一个模块并在隔离的环境中执行;也就是说,它定义的变量不能从模块外部获得
  • 为了允许导入其他模块,require为模块提供了一个全局变量,允许它导入其他模块
  • 以同样的方式,该变量module可供模块使用,以便它可以设置其exports属性来定义模块应导出的内容;module.exports您在模块a.js中设置的值正是require('./a')将返回的值。

每个实现 CommonJS 的 JS 环境都必须了解这些规则。当然,这包括 Node.js,还包括 Browserify 和 Webpack 等打包程序,它们将打包您的代码,以便遵守这些约定。

这样,您可以控制将导出模块的哪一部分。

PS:请注意,您还可以使用exportsvar 来定义导出,并且其用法与module.exports. 有关详细信息,请参阅此 StackOverflow 问题和答案