本篇文章給大家分享的是有關(guān)Node中exports有哪些設(shè)計(jì)模式,小編覺(jué)得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話(huà)不多說(shuō),跟著小編一起來(lái)看看吧。
上栗網(wǎng)站制作公司哪家好,找成都創(chuàng)新互聯(lián)公司!從網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)站建設(shè)、微信開(kāi)發(fā)、APP開(kāi)發(fā)、自適應(yīng)網(wǎng)站建設(shè)等網(wǎng)站項(xiàng)目制作,到程序開(kāi)發(fā),運(yùn)營(yíng)維護(hù)。成都創(chuàng)新互聯(lián)公司于2013年成立到現(xiàn)在10年的時(shí)間,我們擁有了豐富的建站經(jīng)驗(yàn)和運(yùn)維經(jīng)驗(yàn),來(lái)保證我們的工作的順利進(jìn)行。專(zhuān)注于網(wǎng)站建設(shè)就選成都創(chuàng)新互聯(lián)公司。
首先我們需要先聊點(diǎn)基礎(chǔ)的知識(shí)
在Node官方文件中定義了匯入一個(gè)檔案就是匯入一個(gè)模塊。
In Node.js,files and modules are in one-to-one correspondence.- Node文件
也就是所有的模塊會(huì)參考指向(Reference)一個(gè)隱式模塊物件的module.exports。當(dāng)我們使用require()時(shí)會(huì)取得的東西。同時(shí)我們也取得exports。
這個(gè)exports就是指向module.exports的參考。exports會(huì)收集該其屬性,如果module.exports沒(méi)有任何屬性就把這些數(shù)據(jù)交給module.exports,但如果module.exports已經(jīng)具備屬性的話(huà),那么exports的所有數(shù)據(jù)都會(huì)被忽略。
為了讓您更好理解關(guān)于exports與module.exports下面的示例提供了較詳細(xì)的說(shuō)明
var a = { id: 1 } var b = a console.log(a)// {id: 1} console.log(b)// {id: 1} // b參考指向a,意味著修改b的屬性a會(huì)跟著變動(dòng) b.id = 2 console.log(a)// {id: 2} console.log(b)// {id: 2} //但如果將一個(gè)全新的物件賦予b那么參考的關(guān)系將會(huì)中斷 b = { id: 3 } console.log(a)// {id: 2} console.log(b)// {id: 3}
另外比較具體的示例
/* person.js */ exports.name = function(){ console.log('My name is andyyou.') } … /* main.js */ var person = require('./person.js') person.name() /* person.js */ module.exports = 'Hey,andyyou' exports.name = function(){ console.log('My name is andyyou') } /* main.js */ var person = require('./person.js') // exports的屬性被忽略了 person.name()// TypeError: Object Hey,andyyou has no method 'name'
exports只是指向module.exports的參考(Reference)
module.exports初始值為{}空物件,于是exports也會(huì)取得該空物件
require()回傳的是module.exports而不是exports
所以您可以使用exports.property_name = something而不會(huì)使用exports = something
一旦使用exports = something參考關(guān)系便會(huì)停止,也就是exports的數(shù)據(jù)都會(huì)被忽略。
本質(zhì)上我們可以理解為所有模塊都隱含實(shí)作了下面這行代碼
var exports = module.exports = {}
現(xiàn)在我們知道了,當(dāng)我們要導(dǎo)出一個(gè)function時(shí)我們得使用module.exports。
如果使用exports那個(gè)exports的內(nèi)存位置(Reference/參考)將會(huì)被修改而module.exports就不會(huì)得到其內(nèi)容。
另外,我們?cè)谠S多項(xiàng)目看到下面的這行代碼
exports = module.exports = something
這行代碼作用就是確保exports在module.exports被我們復(fù)寫(xiě)之后,仍可以指向相同的參考。
接著我們就可以透過(guò)module.exports來(lái)定義并導(dǎo)出一個(gè)function
/* function.js */ module.exports = function(){ return { name: 'andyyou' } }
使用的方式則是
var func = require('./function')
關(guān)于require一個(gè)很重要的行為就是它會(huì)緩存(Cache)module.exports的值,未來(lái)每一次require被調(diào)用時(shí)都會(huì)回傳相同的值。
它會(huì)根據(jù)匯入檔案的絕對(duì)路徑來(lái)緩存,所以當(dāng)我們想要模塊能夠回傳不同得值時(shí),我們就需要導(dǎo)出function,如此一來(lái)每次執(zhí)行函式時(shí)就會(huì)回傳一個(gè)新值。
下面在Node REPL中簡(jiǎn)易的示范
$ node > f1 = require('/Users/andyyou/Projects/export_this/function') [Function] > f2 = require('./function')//相同路徑 [Function] > f1 === f2 true > f1()=== f2() false
您可以觀(guān)察到require回傳了同樣的函式物件實(shí)例,但每一次調(diào)用函式回傳的物件是不同的。
更詳細(xì)的介紹可以參考官方文件,值得一讀。
現(xiàn)在,我們可以開(kāi)始探討界面的設(shè)計(jì)模式(pattern)了。
導(dǎo)出命名空間
一個(gè)簡(jiǎn)單且常用的設(shè)計(jì)模式就是導(dǎo)出一個(gè)包含數(shù)個(gè)屬性的物件,這些屬性具體的內(nèi)容主要是函式,但并不限于函式。
如此,我們就能夠透過(guò)匯入該模塊來(lái)取得這個(gè)命名空間下一系列相關(guān)的功能。
當(dāng)您匯入一個(gè)命名空間類(lèi)型的模塊時(shí),我們通常會(huì)將模塊指定到某一個(gè)變數(shù),然后透過(guò)它的成員(物件屬性)來(lái)存取使用這些功能。
甚至我們也可以將這些變數(shù)成員直接指定到區(qū)域變數(shù)。
var fs = require('fs') var readFile = fs.readFile var ReadStream = fs.ReadStream readFile('./file.txt',function(err,data){ console.log('readFile contents: %s',data) })
這便是fs核心模塊的做法
var fs = exports
首先將隱式exports物件設(shè)定一個(gè)區(qū)域變數(shù)(即上面提過(guò)的exports)到fs,然后透過(guò)fs的屬性使用各個(gè)功能,例如:fs.Stats = binding.Stats。
由于fs參考exports并且它是一個(gè)物件,所以當(dāng)我們r(jià)equire('fs')時(shí),我們就能夠透過(guò)屬性使用那些功能。
fs.readFile = function(path,options,callback_){ //… }
其他東西也是一樣的作法,例如導(dǎo)出構(gòu)造函數(shù)
fs.ReadStream = ReadStream function ReadStream(path,options){ //… } ReadStream.prototype.open = function(){ //… }
當(dāng)導(dǎo)出命名空間時(shí),您可以指定屬性到exports,就像fs的作法,又或者可以建立一個(gè)新的物件指派給module.exports
/* exports作法*/ exports.verstion = '1.0' /*或者module.exports作法*/ module.exports = { version: '1.0', doYourTasks: function(){ //… } }
一個(gè)常見(jiàn)的作法就是透過(guò)一個(gè)根模塊(root)來(lái)匯整并導(dǎo)出其他模塊,如此一來(lái)只需要一個(gè)require便可以使用所有的模塊。
原文作者在Good Eggs工作時(shí),會(huì)將數(shù)據(jù)模型(Model)拆分成個(gè)別的模塊,并使用導(dǎo)出構(gòu)造函數(shù)的方式導(dǎo)出(請(qǐng)參考下文介紹),然后透過(guò)一個(gè)index檔案來(lái)集合該目錄下所有的數(shù)據(jù)模型并一起導(dǎo)出,如此一來(lái)在models命名空間下的所有數(shù)據(jù)模型都可以使用
var models = require('./models') var User = models.User var Product = models.Product
在ES2015和CoffeeScript中我們甚至還可以使用解構(gòu)指派來(lái)匯入我們需要的功能
/* CoffeeScript */ {User,Product} = require './models' /* ES2015 */ import {User,Product} from './models'
而剛剛提到的index.js大概就如下
exports.User = require('./User') exports.Person = require('./person')
實(shí)際上這樣分開(kāi)的寫(xiě)法還有更精簡(jiǎn)的寫(xiě)法,我們可以透過(guò)一個(gè)小小的函式庫(kù)來(lái)匯入在同一階層中所有檔案并搭配CamelCase的命名規(guī)則導(dǎo)出。
于是在我們的index.js中看起來(lái)就會(huì)如下
module.exports = require('../lib/require_siblings')(__filename)
導(dǎo)出函式
另外一個(gè)設(shè)計(jì)模式是導(dǎo)出函式當(dāng)作該模塊的界面。常見(jiàn)的作法是導(dǎo)出一個(gè)工廠(chǎng)函式(Factory function),然后呼叫并回傳一個(gè)物件。
在使用Express.js的時(shí)候便是這種作法
var express = require('express') var app = express() app.get('/hello',function(req,res,next){ res.send('Hi there!We are using Express v' + express.version) })
Express導(dǎo)出該函式,讓我們可以用來(lái)建立一個(gè)新的express應(yīng)用程序。
在使用這種模式時(shí),通常我們會(huì)使用factory function搭配參數(shù)讓我們可以設(shè)定并回傳初始化后的物件。
想要導(dǎo)出function,我們就一定要使用module.exports,Express便是這么做
exports = module.exports = createApplication … function createApplication(){ … }
上面指派了createApplication函式到module.exports然后再指給exports確保參考一致。
同時(shí)Express也使用下面這種方式將導(dǎo)出函式當(dāng)作命名空間的作法使用。
exports.version = '3.1.1'
這邊要大略解釋一下由于Javascript原生并沒(méi)有支持命名空間的機(jī)制,于是大部分在JS中提到的namespace指的就是透過(guò)物件封裝的方式來(lái)達(dá)到namespace的效果,也就是***種設(shè)計(jì)模式。
注意!并沒(méi)有任何方式可以阻止我們將導(dǎo)出的函式作為命名空間物件使用,我們可以用其來(lái)引用其他的function,構(gòu)造函數(shù),物件。
Express 3.3.2 / 2013-07-03之后已經(jīng)將exports.version移除了
另外在導(dǎo)出函式的時(shí)候***為其命名,如此一來(lái)當(dāng)出錯(cuò)的時(shí)候我們比較容易從錯(cuò)誤堆疊信息中找到問(wèn)題點(diǎn)。
下面是兩個(gè)簡(jiǎn)單的例子:
/* bomb1.js */ module.exports = function(){ throw new Error('boom') } module.exports = function bomb(){ throw new Error('boom') } $ node > bomb = require('./bomb1'); [Function] > bomb() Error: boom at module.exports(/Users/andyyou/Projects/export_this/bomb1.js:2:9) at repl:1:2 … > bomb = require('./bomb2'); [Function: bomb] > bomb() Error: boom at bomb(/Users/andyyou/Projects/export_this/bomb2.js:2:9) at repl:1:2 …
導(dǎo)出函式還有些比較特別的案例,值得用另外的名稱(chēng)以區(qū)分它們的不同。
導(dǎo)出高階函式
一個(gè)高階函式或functor基本上就是一個(gè)函式可以接受一個(gè)或多個(gè)函式為其輸入或輸出。而這邊我們要談?wù)摰暮笳?一個(gè)函式回傳函式
當(dāng)我們想要模塊能夠根據(jù)輸入控制回傳函式的行為時(shí),導(dǎo)出一個(gè)高階函式就是一種非常實(shí)用的設(shè)計(jì)模式。
補(bǔ)充:functor & monad
舉例來(lái)說(shuō)Connect就提供了許多可掛載的功能給網(wǎng)頁(yè)框架。
這里的middleware我們先理解成一個(gè)有三個(gè)參數(shù)(req,res,next)的function。
Express從v4.x版之后不再相依于connect
connect middleware慣例就是導(dǎo)出的function執(zhí)行后,要回傳一個(gè)middleware function。
在處理request的過(guò)程中這個(gè)回傳的middleware function就可以接手使用剛剛提到的三個(gè)參數(shù),用來(lái)在過(guò)程中做一些處理或設(shè)定。
同時(shí)因?yàn)殚]包的特性這些設(shè)定在整個(gè)中間件的處理流程中都是有效的。
舉例來(lái)說(shuō),compression這個(gè)middleware就可以在處理responsive過(guò)程中協(xié)助壓縮
var connect = require('connect') var app = connect() // gzip outgoing responses var compression = require('compression') app.use(compression())
而它的原始碼看起來(lái)就如下
module.exports = compression … function compression(options){ … return function compression(req,res,next){ … next() } }
于是每一個(gè)request都會(huì)經(jīng)過(guò)compression middleware處理,而代入的options也因?yàn)殚]包的關(guān)系會(huì)被保留下來(lái)
這是一種***彈性的模塊作法,也可能在您的開(kāi)發(fā)項(xiàng)目上幫上許多忙。
middleware在這里您可以大略想成串連執(zhí)行一系列的function,自然其Function Signature要一致
導(dǎo)出構(gòu)造函數(shù)
在一般面向?qū)ο笳Z(yǔ)言中,constructor構(gòu)造函數(shù)指的是一小段代碼協(xié)助我們從類(lèi)別Class建立一個(gè)物件。
// C# class Car { // c#構(gòu)造函數(shù) // constructor即class中用來(lái)初始化物件的method。 public Car(name){ name = name; } } var car = new Car('BMW');
由于在ES2015之前Javascript并不支持類(lèi)別,某種程度上在Javascript之中我們可以把任何一個(gè)function當(dāng)作類(lèi)別,或者說(shuō)一個(gè)function可以當(dāng)作function執(zhí)行或者搭配new關(guān)鍵字當(dāng)作constructor來(lái)使用。如果想知道更詳細(xì)的介紹可以閱讀MDN教學(xué)。
欲導(dǎo)出構(gòu)造函數(shù),我們需要透過(guò)構(gòu)造函式來(lái)定義類(lèi)別,然后透過(guò)new來(lái)建立物件實(shí)例。
function Person(name){ this.name = name } Person.prototype.greet = function(){ return 'Hi,I am ' + this.name } var person = new Person('andyyou') console.log(person.greet())// Hi,I am andyyou
在這種設(shè)計(jì)模式底下,我們通常會(huì)將每個(gè)檔案設(shè)計(jì)成一個(gè)類(lèi)別,然后導(dǎo)出構(gòu)造函數(shù)。這使得我們的項(xiàng)目構(gòu)架更加清楚。
var Person = require('./person') var person = new Person()
整個(gè)檔案看起來(lái)會(huì)如下
/* person.js */ function Person(name){ this.name = name } Person.prototype.greet = function(){ return 'Hi,I am ' + this.name } exports = module.exports = Person
導(dǎo)出單一物件實(shí)例Signleton
當(dāng)我們需要所有的模塊使用者共享物件的狀態(tài)與行為時(shí),就需要導(dǎo)出單一物件實(shí)例。
Mongoose是一個(gè)ODM(Object-Document Mapper)函式庫(kù),讓我們可以使用程序中的Model物件去操作MongoDB。
var mongoose = require('mongoose') mongoose.connect('mongodb://localhost/test') var Cat = mongoose.model('Cat',{name: String}) var kitty = new Cat({name: 'Zildjian'}) kitty.save(function(err){ if(err) throw Error('save failed') console.log('meow') })
那我們r(jià)equire取得的mongoose物件是什么東西呢?事實(shí)上mongoose模塊的內(nèi)部是這么處理的
function Mongoose(){ … } module.exports = exports = new Mongoose()
因?yàn)閞equire的緩存了module.exports的值,于是所有reqire('mongoose')將會(huì)回傳相同的物件實(shí)例,之后在整個(gè)應(yīng)用程序之中使用的都會(huì)是同一個(gè)物件。
Mongoose使用面向?qū)ο蟮脑O(shè)計(jì)模式來(lái)封裝,解耦(分離功能之間的相依性),維護(hù)狀態(tài)使整體具備可讀性,同時(shí)透過(guò)導(dǎo)出一個(gè)Mongoose Class的物件給使用者,讓我們可以簡(jiǎn)單的存取使用。
如果我們有需要,它也可以建立其他的物件實(shí)例來(lái)作為命名空間使用。實(shí)際上Mongoose內(nèi)部提供了存取構(gòu)造函數(shù)的方法
Mongoose.prototype.Mongoose = Mongoose
因此我們可以這么做
var mongoose = require('mongoose') var Mongoose = mongoose.Mongoose var anotherMongoose = new Mongoose() anotherMongoose.connect('mongodb://localhost/test')
擴(kuò)展全局物件
一個(gè)被匯入的模塊不只限于單純?nèi)〉闷鋵?dǎo)出的數(shù)據(jù)。它也可以用來(lái)修改全局物件或回傳全局物件,自然也能定義新的全局物件。而在這邊的全局物件(Global objects)或稱(chēng)為標(biāo)準(zhǔn)內(nèi)置物件像是Object,F(xiàn)unction,Array指的是在全局能存取到的物件們,而不是當(dāng)Javascript開(kāi)始執(zhí)行時(shí)所產(chǎn)生代表global scope的global object。
當(dāng)我們需要擴(kuò)增或修改全局物件預(yù)設(shè)行為時(shí)就需要使用這種設(shè)計(jì)模式。當(dāng)然這樣的方式是有爭(zhēng)議,您必須謹(jǐn)慎使用,特別是在開(kāi)放原始碼的項(xiàng)目上。
例如:Should.js是一個(gè)常被用在單元測(cè)試中用來(lái)判斷分析值是否正確的函式庫(kù)。
require('should') var user = { name: 'andyyou' } user.name.should.equal('andyyou')
這樣您是否比較清楚了,should.js增加了底層的Object的功能,加入了一個(gè)非列舉型的屬性 should,讓我們可以用簡(jiǎn)潔的語(yǔ)法來(lái)撰寫(xiě)單元測(cè)試。
而在內(nèi)部should.js做了這樣的事情
var should = function(obj){ return new Assertion(util.isWrapperType(obj)?obj.valueOf():obj) } … exports = module.exports = should Object.defineProperty(Object.prototype,'should',{ set: function(){}, get: function(){ return should(this); }, configurable: true });
就算看到這邊您肯定跟我一樣有滿(mǎn)滿(mǎn)的疑惑,全局物件擴(kuò)展定義跟exprots有啥關(guān)聯(lián)呢?
事實(shí)上
/* whoami.js */ exports = module.exports = { name: 'andyyou' } Object.defineProperty(Object.prototype,'whoami',{ set: function(){}, get: function(){ return 'I am ' + this.name } }) /* app.js */ var whoami = require('whoami') console.log(whoami)// { name: 'andyyou' } var obj = { name: 'lena' } console.log(obj.whoami)// I am lena
現(xiàn)在我們明白了上面說(shuō)的修改全局物件的意思了。should.js導(dǎo)出了一個(gè)should函式但是它主要的使用方式則是把should加到Object屬性上,透過(guò)物件本身來(lái)呼叫。
套用猴子補(bǔ)丁(Monkey Patch)
在這邊所謂的猴子補(bǔ)丁特別指的是在執(zhí)行時(shí)期動(dòng)態(tài)修改一個(gè)類(lèi)別或者模塊,通常會(huì)這么做是希望補(bǔ)強(qiáng)某的第三方套件的bug或功能。
假設(shè)某個(gè)模塊沒(méi)有提供您客制化功能的界面,而您又需要這個(gè)功能的時(shí)候,我們就會(huì)實(shí)作一個(gè)模塊來(lái)補(bǔ)強(qiáng)既有的模塊。
這個(gè)設(shè)計(jì)模式有點(diǎn)類(lèi)似擴(kuò)展全局物件,但并非修改全局物件,而是依靠Node模塊系統(tǒng)的緩存機(jī)制,當(dāng)其他代碼匯入該模塊時(shí)去補(bǔ)強(qiáng)該模塊的實(shí)例物件。
預(yù)設(shè)來(lái)說(shuō)Mongoose會(huì)使用小寫(xiě)以及復(fù)數(shù)的慣例替數(shù)據(jù)模型命名。例如一個(gè)數(shù)據(jù)模型叫做CreditCard最終我們會(huì)得到collection的名稱(chēng)是creditcards。假如我們希望可以換成credit_cards并且其他地方也遵循一樣的用法。
下面是我們?cè)囍褂煤镒友a(bǔ)丁的方式來(lái)替既有的模塊增加功能
var pluralize = require('pluralize')//處理復(fù)數(shù)單字的函式庫(kù) var mongoose = require('mongoose') var Mongoose = mongoose.Mongoose mongoose.Promise = global.Promise // v4.1+ http://mongoosejs.com/docs/promises.html var model = Mongoose.prototype.model //補(bǔ)丁 var fn = function(name,schema,collection,skipInit){ collection = collection || pluralize.plural(name.replace(/([a-z\d])([A-Z])/g,'$1_$2').toLowerCase()) return model.call(this,name,schema,collection,skipInit) } Mongoose.prototype.model = fn /*實(shí)際測(cè)試*/ mongoose.connect('mongodb://localhost/test') var CreditCardSchema = new mongoose.Schema({number: String}) var CreditCardModel = mongoose.model('CreditCard',CreditCardSchema); var card = new CreditCardModel({number: '5555444433332222'}); card.save(function(err){ if(err){ console.log(err) } console.log('success') })
您不該輕易使用上面這種方式補(bǔ)丁,這邊只是為了說(shuō)明猴子補(bǔ)丁這種方式,mongoose已經(jīng)有提供官方的方式設(shè)定名稱(chēng)
var schema = new Schema({..},{ collection: 'your_collection_name' })
當(dāng)這個(gè)模塊***次被匯入的時(shí)候便會(huì)讓mongoose重新定義Mongoose.prototype.model并將其設(shè)回原本的model的實(shí)作。
如此一來(lái)所有Mongoose的實(shí)例物件都具備新的行為了。注意到這邊并沒(méi)有修改exports所以當(dāng)我們r(jià)equire的時(shí)候得到的是預(yù)設(shè)的物件
另外如果您想使用上面這種補(bǔ)丁的方式時(shí),記得閱讀原始碼并注意是否產(chǎn)生沖突。
請(qǐng)善用導(dǎo)出的功能
Node模塊系統(tǒng)提供了一個(gè)簡(jiǎn)單的機(jī)制來(lái)封裝功能,使我們能夠建立了清楚的界面。希望掌握這七種設(shè)計(jì)模式提供不同的優(yōu)缺點(diǎn)能對(duì)您有所幫助。
在這邊作者并沒(méi)有徹底的調(diào)查所有的方式,一定有其他選項(xiàng)可供選擇,這邊只有描述幾個(gè)最常見(jiàn)且不錯(cuò)的方法。
小結(jié)
namespace:導(dǎo)出一個(gè)物件包含需要的功能
root module的方式,使用一個(gè)根模塊導(dǎo)出其他模塊
function:直接將module.exports設(shè)為function
Function物件也可以拿來(lái)當(dāng)作命名空間使用
為其命名方便調(diào)試
exports = module.exports = something的作法是為了確保參考(Reference)一致
high-order function:可以透過(guò)代入?yún)?shù)控制并回傳function。
可協(xié)助實(shí)作middleware的設(shè)計(jì)模式
換句話(huà)說(shuō)middleware即一系列相同signature的function串連。一個(gè)接一個(gè)執(zhí)行
constructor:導(dǎo)出類(lèi)別(function),使用時(shí)再new,具備OOP的優(yōu)點(diǎn)
singleton:導(dǎo)出單一物件實(shí)例,重點(diǎn)在各個(gè)檔案可以共享物件狀態(tài)
global objects:在全局物件作的修改也會(huì)一起被導(dǎo)出
monkey patch:執(zhí)行時(shí)期,利用Node緩存機(jī)制在instance加上補(bǔ)丁
筆記
一個(gè)javascript檔案可視為一個(gè)模塊
解決特定問(wèn)題或需求,功能完整由單一或多個(gè)模塊組合而成的整體稱(chēng)為套件(package)
require匯入的模塊具有自己的scope
exports只是module.exports的參考,exports會(huì)記錄收集屬性如果module.exports沒(méi)有任何屬性就把其數(shù)據(jù)交給module.exports,但如果module.exports已經(jīng)具備屬性的話(huà),那么exports的所有數(shù)據(jù)都會(huì)被忽略。
就算exports置于后方仍會(huì)被忽略
Node初始化的順序
Native Module -> Module
StartNodeInstance()-> CreateEnvironment()-> LoadEnvironment()-> Cached
Native Module加載機(jī)制
檢查是否有緩存
->有;直接回傳this.exports
->沒(méi)有;new一個(gè)模塊物件
cache()
compile()-> NativeModule.wrap()將原始碼包進(jìn)function字串->runInThisContext()建立函式
return NativeModule.exports
Node的require會(huì)cache,也就是說(shuō):如果希望模塊產(chǎn)生不同的instance時(shí)應(yīng)使用function
以上就是Node中exports有哪些設(shè)計(jì)模式,小編相信有部分知識(shí)點(diǎn)可能是我們?nèi)粘9ぷ鲿?huì)見(jiàn)到或用到的。希望你能通過(guò)這篇文章學(xué)到更多知識(shí)。更多詳情敬請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。