express簡談
express對(duì)于node.js是一種什么樣的存在?就像mvc對(duì)于.net,就像spring.mvc對(duì)于java,是一個(gè)裝機(jī)量特別多的開源,web框架。github地址
推薦使用visual studio code 進(jìn)行代碼下載,查看,微軟開發(fā)的專門進(jìn)行web開發(fā)的輕量級(jí)工具。
express結(jié)構(gòu)

源代碼
visual studio code下載代碼,主要源碼有兩個(gè),一個(gè)lib文件夾和index.js。index.js算是express的入口文件。
express使用
var express = require('express');
var app = express();
第一行引用express模塊,引用的文件在package.json配置。
"main": "xxxx.js",
express中沒有main這個(gè)屬性,因?yàn)閑xpress默認(rèn)使用根目錄下的index.js
//默認(rèn)會(huì)查找express根目錄下的index.js
var express = require('express');
index.js
module.exports = require('./lib/express');
index.js對(duì)外導(dǎo)出函數(shù)createApplication
./lib/express
'use strict';
/**
* 依賴的模塊
*/
var EventEmitter = require('events').EventEmitter;
var mixin = require('merge-descriptors');
var proto = require('./application');
var Route = require('./router/route');
var Router = require('./router');
var req = require('./request');
var res = require('./response');
/**
* express對(duì)外導(dǎo)出了一個(gè)函數(shù),createApplication,所以在創(chuàng)建app的時(shí)候需要express();
*/
exports = module.exports = createApplication;
function createApplication() {
//創(chuàng)建一個(gè)app的函數(shù)
var app = function(req, res, next) {
//app調(diào)用了一個(gè)handle函數(shù),處理請(qǐng)求
app.handle(req, res, next);
};
//mixin在這里的作用,對(duì)象屬性復(fù)制的手段,另類的繼承
mixin(app, EventEmitter.prototype, false);
mixin(app, proto, false);
//繼承的手段
/*創(chuàng)建request對(duì)象,request的原型為req,也就是request繼承req;并在request對(duì)象上添加了一個(gè)app屬性;
*/
app.request = Object.create(req, {
app: { configurable: true, enumerable: true, writable: true, value: app }
})
// 創(chuàng)建response對(duì)象,同上
app.response = Object.create(res, {
app: { configurable: true, enumerable: true, writable: true, value: app }
})
//調(diào)用初始化
app.init();
//返回
return app;
}
propertiesObject
merge-descriptors
merge-descriptors 源碼復(fù)制源對(duì)象的自有屬性到目標(biāo)對(duì)象上面,默認(rèn)重寫目標(biāo)對(duì)象上的同名屬性
'use strict'
/**
* Module exports.
* @public
*/
module.exports = merge
/**
* Module variables.
* @private
*/
var hasOwnProperty = Object.prototype.hasOwnProperty
function merge(dest, src, redefine) {
//判斷,拋出異常
if (!dest) {
throw new TypeError('argument dest is required')
}
//判斷,拋出異常
if (!src) {
throw new TypeError('argument src is required')
}
//默認(rèn)重新定義未True
if (redefine === undefined) {
// Default to true
redefine = true
}
//獲取所有src對(duì)象中的自身屬性的屬性名稱集合并循環(huán)處理(不包括原型鏈上的)
Object.getOwnPropertyNames(src).forEach(function forEachOwnPropertyName(name) {
//判斷如果redefine=false并且目標(biāo)對(duì)象中含有名稱為name的屬性,則跳過
if (!redefine && hasOwnProperty.call(dest, name)) {
// Skip desriptor
return
}
// 獲取src對(duì)象中name屬性的propertiesObject
var descriptor = Object.getOwnPropertyDescriptor(src, name)
//在目標(biāo)對(duì)象中創(chuàng)建屬性名稱=name,propertiesObject=descriptor
Object.defineProperty(dest, name, descriptor)
})
//結(jié)束
return dest
}
結(jié)語
createApplication函數(shù)中采用了兩種'繼承'方式,來完成對(duì)象的創(chuàng)建,擴(kuò)展,所以在app對(duì)象上面那些我們不知道的函數(shù),屬性其實(shí)都是其他模塊依賴過來的對(duì)象中的函數(shù),屬性。