CommonJS 模块模式

CommonJS module pattern

我从

Flux architecture

var AppDispatcher = require('../dispatcher/AppDispatcher');
var EventEmitter = require('events').EventEmitter;
var TodoConstants = require('../constants/TodoConstants');
var assign = require('object-assign');

var CHANGE_EVENT = 'change';

var _todos = {}; // collection of todo items

/**
 * Create a TODO item.
 * @param {string} text The content of the TODO
 */
function create(text) {
  // Using the current timestamp in place of a real id.
  var id = Date.now();
  _todos[id] = {
    id: id,
    complete: false,
    text: text
  };
}

/**
 * Delete a TODO item.
 * @param {string} id
 */
function destroy(id) {
  delete _todos[id];
}

var TodoStore = assign({}, EventEmitter.prototype, {

  /**
   * Get the entire collection of TODOs.
   * @return {object}
   */
  getAll: function() {
    return _todos;
  },

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

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

  /**
   * @param {function} callback
   */
  removeChangeListener: function(callback) {
    this.removeListener(CHANGE_EVENT, callback);
  },

  dispatcherIndex: AppDispatcher.register(function(payload) {
    var action = payload.action;
    var text;

    switch(action.actionType) {
      case TodoConstants.TODO_CREATE:
        text = action.text.trim();
        if (text !== '') {
          create(text);
          TodoStore.emitChange();
        }
        break;

      case TodoConstants.TODO_DESTROY:
        destroy(action.id);
        TodoStore.emitChange();
        break;

      // add more cases for other actionTypes, like TODO_UPDATE, etc.
    }

    return true; // No errors. Needed by promise in Dispatcher.
  })

});

上面写着

There are a few important things to note in the above code. To start, we are maintaining a private data structure called _todos. This object contains all the individual to-do items. Because this variable lives outside the class, but within the closure of the module, it remains private — it cannot be directly changed from outside of the module. This helps us preserve a distinct input/output interface for the flow of data by making it impossible to update the store without using an action.

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

据我所知

The scope of a variable declared with var is its current execution context, which is either the enclosing function or, for variables declared outside any function, global.

有什么解释吗?

您实际上漏掉了您引用的摘录中的最后一行:

module.exports = TodoStore;

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

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

每个实现 CommonJS 的 JS 环境都必须知道这些规则。当然,这包括 Node.js,但也包括 Browserify 和 Webpack 等捆绑器,它们将打包您的代码,以便遵守这些约定。

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

P.S。 : 请注意,您还可以使用 exports var 来定义您的导出,并且它的使用与 module.exports 略有不同。详情见this Whosebug question and answer

常见的 JS 模式使用构造函数来定义您的实用程序。

定义为class。

var moduleName = function() {

  // private variables

  // public functions
  this.method1 = function() {
    // logic1 goes here
  };

  this.method2 = function() {
    // logic2 goes here
  };

};

所以我们要使用

将class导出到其他模块
    module.exports = moduleName;

以便其他模块可以导入它、实例化它然后使用该功能。

如何使用?

    var module = require('moduleName');  //importing the module created above

此处获取、执行模块定义,然后在 'module' 变量中可用。

这个变量名可以是任何东西

    var objectOfModule = new module(); //instance is created

    objectOfModule .method1(); //use1

    console.log(objectOfModule .method2()); //use2

谢谢。