当循环调用 require() 时,一个模块可能在未完成执行时被返回。
例如如下状况:
a.js:node
exports.done = false; const b = require('./b.js'); console.log('在 a 中,b.done = %j', b.done); exports.done = true; console.log('a 结束');
b.js:app
console.log('b 开始'); exports.done = false; const a = require('./a.js'); console.log('在 b 中,a.done = %j', a.done); exports.done = true; console.log('b 结束');
main.js:函数
console.log('main 开始'); const a = require('./a.js'); const b = require('./b.js'); console.log('在 main 中,a.done=%j,b.done=%j', a.done, b.done);
当 main.js 加载 a.js 时,a.js 又加载 b.js。 此时,b.js 会尝试去加载 a.js。 为了防止无限的循环,会返回一个 a.js 的 exports 对象的 未完成的副本 给 b.js 模块。 而后 b.js 完成加载,并将 exports 对象提供给 a.js 模块。
当 main.js 加载这两个模块时,它们都已经完成加载。 所以,该程序的输出会是:
$ node main.jsui
main 开始 a 开始 b 开始 在 b 中,a.done = false b 结束 在 a 中,b.done = true a 结束 在 main 中,a.done=true,b.done=true
须要仔细的规划, 以容许循环模块依赖在应用程序内正常工做.this
须要注意的是call、apply、bind方法都只能继承对象的方法,却不能对它们的原型进行拷贝或继承,为此咱们通常使用混合的写法,使用原型链和(apply或者call)方法进行继承。
而在nodeJS中,util包提供了一个方法util.inherits(constructor, superConstructor)
因此就得以下,经过结合使用call和inherits才能将其彻底拷贝:prototype
function Girl(name){ this.name = name; EventEmitter.call(this); } util.inherits(Girl,EventEmitter); var girl = new Girl();
注意,不建议使用 util.inherits()。 请使用 ES6 的 class 和 extends 关键词得到语言层面的继承支持。 注意,这两种方式是语义上不兼容的。
constructor <Function>
superConstructor <Function>
从一个构造函数中继承原型方法到另外一个。 constructor 的原型会被设置到一个从 superConstructor 建立的新对象上。code
superConstructor 可经过 constructor.super_ 属性访问。对象
const util = require('util'); const EventEmitter = require('events'); function MyStream() { EventEmitter.call(this); } util.inherits(MyStream, EventEmitter); MyStream.prototype.write = function(data) { this.emit('data', data); }; const stream = new MyStream(); console.log(stream instanceof EventEmitter); // true console.log(MyStream.super_ === EventEmitter); // true stream.on('data', (data) => { console.log(`接收的数据:"${data}"`); }); stream.write('运做良好!'); // 接收的数据:"运做良好!"
例子:使用 ES6 的 class 和 extends:继承
const EventEmitter = require('events'); class MyStream extends EventEmitter { write(data) { this.emit('data', data); } } const stream = new MyStream(); stream.on('data', (data) => { console.log(`接收的数据:"${data}"`); }); stream.write('使用 ES6');