經過Node.js的官方API能夠看到Node.js自己提供了不少核心模塊 http://nodejs.org/api/ ,這些核心模塊被編譯成二進制文件,能夠require('模塊名')去獲取;核心模塊具備最高的加載優先級(有模塊與核心模塊同名時會體現),如:node
var fs=require('fs'); var http=require('http')
文件模塊訪問方式經過require('/文件名.後綴') require('./文件名.後綴') requrie('../文件名.後綴') 去訪問,文件後綴能夠省略;以"/"開頭是以絕對路徑去加載,以"./"開頭和以"../"開頭表示以相對路徑加載,而以"./"開頭表示同級目錄下文件,如:api
var myadd=require('./add'); //本目錄下的add.js
exports和module.exports;提供了外部訪問的接口緩存
(本文講exports和module.exports,是對外暴露文件,再引用,屬於文件模塊。核心模塊由node寫好,直接引用就行)
講講他們的區別
一、模塊導入會緩存,寫了屢次導入,只會導一次。
即便導入的路徑不同。它緩存是指實際文件名,並不會由於傳入的路徑形式不同而認會是不一樣的文件函數
var outputVal = 0; //輸出值 var increment = 1; //增量 /* 設置輸出值 */ function seOutputVal (val) { outputVal = val; } /* 設置增量 */ function setIncrement(incrementVal){ increment = incrementVal; } /* 輸出 */ function printNextCount() { outputVal += increment; console.log(outputVal) ; } function printOutputVal() { console.log(outputVal); } exports.seOutputVal = seOutputVal; exports.setIncrement = setIncrement; module.exports.printNextCount = printNextCount;
一個Node.js文件就是一個模塊,這個文件多是Javascript代碼、JSON或者編譯過的C/C++擴展。重要的兩個對象:require是從外部獲取模塊,exports是把模塊接口公開工具
var counter = require('./1_modules_custom_counter'); console.log('第一次調用模塊[1_modules_custom_counter]'); counter.seOutputVal(10);//設置從10開始計數 counter.setIncrement (10);//設置增量爲10 counter.printNextCount(); counter.printNextCount(); counter.printNextCount(); counter.printNextCount();//require屢次調用同一模塊不會重複加載 var counter = require('./1_modules_custom_counter'); console.log('第二次調用模塊[1_modules_custom_counter]'); counter.printNextCount();
二、經過exports和module.exports對外公開的方法均可以訪問,但有區別ui
module.exports纔是真正的接口,exports只不過是它的一個輔助工具。 最終返回給調用的是module.exports而不是exports。
全部的exports收集到的屬性和方法,都賦值給了Module.exports。固然,這有個前提,就是module.exports自己不具有任何屬性和方法。
若是,module.exports已經具有一些屬性和方法,那麼exports收集來的信息將被忽略。this
我把exports和 module.exports都打印出來看看究竟spa
① (雖然這樣在引入模塊時會報錯,但這一步能說明問題,後面說緣由)3d
var counter = 0; exports.temp = function(){ counter += 10; this.printNextCount = function() { console.log(counter); } } var isEq = (exports === module.exports); console.log(exports); console.log(module.exports); console.log(isEq);
結果:code
經過exports導出的方法,會傳遞給module.exports。兩者沒區別
var counter = 0; module.exports = function(){ counter += 10; this.printNextCount = function() { console.log(counter); } } var isEq = (exports === module.exports); console.log(exports); console.log(module.exports); console.log(isEq);
結果:
直接傳給module.exports,那exports就說明都沒有,兩者不相等了。
③:注意,導入時有點區別。和上面第一大點不同
如這裏的②
var Counter = require('./ '); var counterObj = new Counter(); counterObj.printNextCount();
而第一大點能夠直接這樣:
var counter = require('./1_modules_custom_counter'); console.log('第二次調用模塊[1_modules_custom_counter]'); counter.printNextCount();
就是要new一個對象!
由於導出的文件中的函數變成了成員方法,因此要new一個對象,再調用成員方法。
說明①不可行的緣由:當我在別的文件調用它時,不管是直接調用,仍是new一個對象再調用,都報錯!
因此,要遵循這兩點
1.最好別分別定義module.exports和exports
2.NodeJs開發者建議導出對象用module.exports,導出多個方法和變量用exports
三、exports和module.exports覆蓋
直接上代碼,看誰留下,誰消失
var counter = 0; exports.printNextCount = function() { counter+=2; console.log(counter); } module.exports = function(){ counter+=10; this.printNextCount=function(){ console.log(counter) } } var isEq = (exports === module.exports); console.log(exports); console.log(module.exports); console.log(isEq);
想一想都知道誰厲害。
引用該模塊:
①報錯,說明exports的消失了
var counter = require('./test3'); counter.printNextCount();
②留下了。
var counter = require('./test3'); var counterObj=new counter() counterObj.printNextCount();
結果,輸出了它成功導出的對象函數值;前面兩個是兩個接口收集到的東西,最後exports的被覆蓋了
exports僅僅是module.exports的一個地址引用。nodejs只會導出module.exports的指向,若是exports指向變了,那就僅僅是exports不在指向module.exports,因而不會再被導出
至關於:a和b指向同一塊內存,b是a的地址引用
var a = new Object();//a至關於module.exports var b = a; //b至關於exports
覆蓋,也就是a已經賦值了,但b又被賦了別的值。這時候,b就是叛變了,就指向了一塊新的地址了。而模塊引用是要用module.exports來引用,因此指向新地址的exports不起做用了。