[Transfer] Modularization - Common Specification and Node Module Implementation (2)

Cyclic loading of modules

If a circular loading of modules occurs, i.e. A loads B which in turn loads A, then B will load an incomplete version of A.

// a.js
exports.x = 'a1';
console.log('a.js ', require('./b.js').x);
exports.x = 'a2';

// b.js
exports.x = 'b1';
console.log('b.js ', require('./a.js').x);
exports.x = 'b2';

// main.js
console.log('main.js ', require('./a.js').x);
console.log('main.js ', require('./b.js').x);

The above code is three JavaScript files. Among them, a.js loads b.js, which in turn loads a.js. At this time, Node returns an incomplete version of a.js, so the execution result is as follows.

Modify main.js and load a.js and b.js again.

// main.js
console.log('main.js ', require('./a.js').x);
console.log('main.js ', require('./b.js').x);
console.log('main.js ', require('./a.js').x);
console.log('main.js ', require('./b.js').x);

 

Execute the above code, the result is as follows.


In the above code, when a.js and b.js are loaded for the second time, the exports property will be directly read from the cache, so the console.log statements inside a.js and b.js will not be executed.

require.main

requireThe method has an mainattribute that can be used to determine whether the module executes directly or is called to execute .

When executed directly ( node module.js), the require.mainattribute points to the module itself.

 

When the call is executed (by requireloading the script), the above expression returns false.

Module loading mechanism

The loading mechanism of CommonJS modules is that the input is a copy of the value that is output . That is, once a value is output , changes within the module cannot affect this value . See the example below.

Below is a module file lib.js.

// lib.js
var counter = 3;
function incCounter() {
  counter++;
}
module.exports = {
  counter: counter,
  incCounter: incCounter,
};

The above code outputs the internal variable counterand the internal method that overwrites this variable incCounter.

Then, load the above module.

// main.js
var counter = require('./lib').counter;
var incCounter = require('./lib').incCounter;

console.log(counter);  // 3
incCounter();
console.log(counter); // 3

The above code shows that counterafter output, lib.jschanges inside the module will not be affected counter.

The internal processing flow of require

requireCommands are the commands in the CommonJS specification to load other modules. It's not actually a global command, but a command that points to the current module , which in turn calls Node's internal commands . module.require Module._load

上面的第4步,采用module.compile()执行指定模块的脚本,逻辑如下。

The above steps 1 and 2, requirefunctions and their auxiliary methods are mainly as follows.

Once the requirefunction is ready, the entire script content to be loaded is put into a new function, which can avoid polluting the global environment. The parameters of this function include require, module, exports, and a few others.

(function (exports, require, module, __filename, __dirname) {
  // YOUR CODE INJECTED HERE!
});

Module._compileThe method is executed synchronously , so it will not return the value to the user until Module._loadit finishes executing .module.exports

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324942797&siteId=291194637