commonjs在导出过程中如何制作两份副本并需要处理?

时间:2016-08-16 10:16:20

标签: javascript module commonjs

我正在从blog了解CommonJS,并且在代码方面遇到以下问题:

  

在这个例子中,我们基本上制作了两个模块副本:一个是   我们出口它,当我们需要它时。而且,副本中   main.js现在与原始模块断开连接。这就是原因   当我们递增计数器时它仍然返回1 - 因为计数器   我们导入的变量是计数器的断开连接的副本   来自模块的变量。

// lib/counter.js

var counter = 1;

function increment() {
  counter++;
}

function decrement() {
  counter--;
}

module.exports = {
  counter: counter,
  increment: increment,
  decrement: decrement
};


// src/main.js

var counter = require('../../lib/counter');

counter.increment();
console.log(counter.counter); // 1

因此,如果创建了2个副本,那么每个副本都不会有自己的counterincrement版本吗?因此,每一个都将连接到他们自己的increment函数?作者说,{。1}}中有counterincrementdecrement的副本,而var counter = require('../../lib/counter')中有另一个副本,所以不应该{ {1}}调用require副本中的counter.increment函数,increment返回require副本中的连接计数器?

1 个答案:

答案 0 :(得分:1)

我认为该声明是为了实现ES6模块与nodejs CommonJS模块之间的对比。它并不完全正确。

当您需要模块时,您需要了解一些事项。

require如何在幕后工作?

简而言之,调用require所需的模块代码将被执行并缓存。     在执行模块代码之前,Node.js将使用函数包装器(module wrapping)来包装它。这可以确保顶级变量(如计数器)的范围限定为模块而不是全局对象。这意味着如果你正在导出一个要在另一个模块中使用的函数,它对于模块中声明的变量可以表现为closure。最后返回module.exports的内容。

关于原始对象类型和对象类型如何进行值赋值?

让我们看看module.exports的{​​{1}} 您将看到它正在导出原始值(lib/counter.js)加上两个函数(counterincrement)。作为原始值的decrement被其值复制,即数字1被设置为counter的值,而增量和减量(都是第一类对象)被其引用复制。实际上,module.exports.countermodule.exports.increment都是关闭的在其正文中使用的module.exports.decrement变量。 您可以在this帖子中阅读有关原始与对象分配的更多信息。

最后在countermain.js变量(从计数器分配了module.exports的内容)是一个具有以下键的对象。

  1. counter - 这是类型编号的原始值。
  2. increment - 指向闭包的指针。
  3. 减量 - 这也是一个闭包的指针。
  4. 因此,您可以看到函数内部的计数器变量是指计数器模块中定义的那个。由于counter值仅通过其值导出,因此对它的任何操作都不会影响原始模块变量