簡介及資料
通過Node.js的官方API可以看到Node.js本身提供了很多核心模塊 http://nodejs.org/api/ 苔悦,這些核心模塊被編譯成二進(jìn)制文件,可以require('模塊名')去獲让槐觥;核心模塊具有最高的加載優(yōu)先級(有模塊與核心模塊同名時(shí)會體現(xiàn))
(本次主要說自定義模塊)
Node.js還有一類模塊為文件模塊沸柔,可以是JavaScript代碼文件(.js作為文件后綴)循衰、也可以是JSON格式文本文件(.json作為文件后綴)、還可以是編輯過的C/C++文件(.node作為文件后綴)褐澎;
文件模塊訪問方式通過require('/文件名.后綴') require('./文件名.后綴') requrie('../文件名.后綴') 去訪問会钝,文件后綴可以省略;以"/"開頭是以絕對路徑去加載工三,以"./"開頭和以"../"開頭表示以相對路徑加載迁酸,而以"./"開頭表示同級目錄下文件,
前面提到文件后綴可以省略俭正,Nodejs嘗試加載的優(yōu)先級 js文件 > json文件 > node文件
官方解釋
Nodejs基于CommonJS,所以直接看的Node的官方文檔解釋
Module.exports
The module.exports object is created by the Module system. Sometimes this is not acceptable; many want their module to be an instance of some class. To do this, assign the desired export object to module.exports. Note that assigning the desired object to exports will simply rebind the local exports variable, which is probably not what you want to do.
譯文:module.exports對象是由模塊系統(tǒng)創(chuàng)建的奸鬓。 有時(shí)這是難以接受的;許多人希望他們的模塊成為某個(gè)類的實(shí)例掸读。 為了實(shí)現(xiàn)這個(gè)串远,需要將期望導(dǎo)出的對象賦值給module.exports。 注意儿惫,將期望的對象賦值給exports會簡單地重新綁定到本地exports變量上澡罚,這可能不是你想要的。
exports
The exports variable is available within a module's file-level scope, and is assigned the value of module.exports before the module is evaluated. It allows a shortcut, so that module.exports.f = ... can be written more succinctly as exports.f = .... However, be aware that like any variable, if a new value is assigned to exports, it is no longer bound to module.exports:
譯文:exports變量是在模塊的文件級別作用域內(nèi)有效的肾请,它在模塊被執(zhí)行前被賦于 module.exports 的值留搔。它有一個(gè)快捷方式,以便 module.exports.f = ... 可以被更簡潔地寫成exports.f = ...隔显。 注意却妨,就像任何變量,如果一個(gè)新的值被賦值給exports荣月,它就不再綁定到module.exports(其實(shí)是exports.屬性會自動掛載到?jīng)]有命名沖突的module.exports.屬性)
module.exports是真正的接口梳毙,exports只不過是它的輔助工具生年。推薦使用exports導(dǎo)出,除非你打算從原來的“實(shí)例化對象”改變成一個(gè)類型患亿。如果你想你的模塊是一個(gè)特定的類型就用Module.exports咙冗。如果你想的模塊是一個(gè)典型的“實(shí)例化對象”就用exports显歧。
require
從require導(dǎo)入方式去理解到旦,關(guān)鍵有兩個(gè)變量(全局變量module.exports采呐,局部變量exports)、一個(gè)返回值(module.exports)
Demo
主要探索 Module.exports 和 exports 區(qū)別
1.js
console.log(exports); // {}
console.log(module.exports); // {}
console.log(exports === module.exports); // true
console.log(exports == module.exports); // true
/**
Module {
id: '.',
exports: {},
parent: null,
filename: '/1.js',
loaded: false,
children: [],
paths:
[
'/node_modules' ]
}
*/
console.log(module);
1.每個(gè)js文件一創(chuàng)建昼捍,都有一個(gè)var exports = module.exports = {};郊闯,使exports和module.exports都指向一個(gè)空對象笋粟。
2.module是全局內(nèi)置對象绿淋,exports是被var創(chuàng)建的局部對象绞幌。
3.module.exports和exports所指向的內(nèi)存地址相同
2.js仪吧、3.js
// 2.js
exports.id = 'exports的id';
exports.id2 = 'exports的id2';
exports.func = function(){
console.log('exports的函數(shù)');
};
exports.func2 = function() {
console.log('exports的函數(shù)2');
};
module.exports = {
id: 'module.exports的id',
func:function(){
console.log('module.exports的函數(shù)');
}
};
// 3.js
var a = require('./2.js');
// 當(dāng)屬性和函數(shù)在module.exports都有定義時(shí):
console.log(a.id); // module.exports的id
console.log("~~~~~~~~~~~~~~~~~~");
console.log(a.func()); // module.exports的函數(shù)
console.log("~~~~~~~~~~~~~~~~~~");
// 當(dāng)屬性在module.exports沒有定義唯咬,函數(shù)在module.exports有定義
console.log(a.id2); // undefined
console.log("~~~~~~~~~~~~~~~~~~");
console.log(a.func()); // module.exports的函數(shù)
console.log("~~~~~~~~~~~~~~~~~~");
// 當(dāng)函數(shù)在module.exports沒有定義蜀涨,屬性在module.exports有定義
console.log(a.id); // module.exports的id
console.log("~~~~~~~~~~~~~~~~~~");
console.log(a.func2()); // 報(bào)錯(cuò)了 TypeError: a.func2 is not a function
console.log("~~~~~~~~~~~~~~~~~~");
1.module.exports像是exports的大哥瞎嬉,當(dāng)module.exports以{}整體導(dǎo)出時(shí)會覆蓋exports的屬性和方法,
2.注意厚柳,若只是將屬性/方法掛載在module.exports./exports.上時(shí)氧枣,exports.id=1和module.exports.id=100,module.exports.id=function(){}和exports.id=function(){}别垮,最后id的值取決于exports.id和module.exports.id的順序便监,誰在后,就是最后的值
3.若exports和module.exports同時(shí)賦值時(shí)宰闰,exports所使用的屬性和方法必須出現(xiàn)在module.exports茬贵,若屬性沒有在module.exports中定義的話簿透,出現(xiàn)undefined,若方法沒有在module.exports中定義解藻,會拋出TypeError錯(cuò)誤老充。
4.js、5.js
module.exports的對象螟左、prototype啡浊、構(gòu)造函數(shù)使用
// 4.js
var a = require('./5.js');
// 若傳的是類,new一個(gè)對象
var person = new a('Kylin',20);
console.log(person.speak()); // my name is Kylin ,my age is 20
// 若不需要在構(gòu)造函數(shù)時(shí)初始化參數(shù)胶背,直接調(diào)用方法/屬性
// a.speak(); // my name is kylin ,my age is 20
// 5.js
// Person類
function Person(name,age){
this.name = name;
this.age = age;
}
// 為類添加方法
Person.prototype.speak = function(){
console.log('my name is '+this.name+' ,my age is '+this.age);
};
// 返回類
module.exports = Person;
// 若構(gòu)造函數(shù)沒有傳入?yún)?shù)(name,age)巷嚣,直接傳入對象
// module.exports = new Person('kylin',20);
如果只是單一屬性或方法的話,就使用exports.屬性/方法钳吟。要是導(dǎo)出多個(gè)屬性或方法或使用對象構(gòu)造方法廷粒,結(jié)合prototype等,就建議使用module.exports = {}红且。
旨在學(xué)習(xí)記錄坝茎,其中描述可能不是很準(zhǔn)確,若是存在問題暇番,還望大神指正建議嗤放。