看express时写如下代码:
const express = require('../index.js')
const app = express()
app.listen(3000)
module.exports = function createServer() {
const app = function (req, res) {
res.end('Response From Server')
}
mixin(app, proto, false)
console.log(app); // { [Function: app] listen: [Function] }
return app
}
const proto = Object.create(null)
proto.listen = function (port) {
const server = http.createServer(this)
console.log(this); // { [Function: app] listen: [Function] }
return server.listen.apply(server, arguments)
}
此时,listen方法相当于app函数对象的一个属性。
http.createServer([requestListener])中的requestListener是一个函数,会被自动添加到'request'事件。
上面的代码将this赋值给http.createServer(),app将被添加到'request'事件。
此时,访问localhost:3000将会在浏览器上显示Response From Server。
这正是函数对象app的初始内容,app的属性没有参与进去。
let app = function (x) {
console.log(x);
}
app.y = function (y) {
console.log(this);
console.log(y);
}
app.z = function (z) {
console.log(this);
console.log(z);
}
app.y(1); // ƒ (x) { console.log(x); } 1
app.z(2); // ƒ (x) { console.log(x); } 2
console.log(app); // ƒ (x) { console.log(x); }
console.log(app.z); // ƒ (z) { console.log(this); console.log(z); }
function A(app) { app(1); }
A(app); // 1
这说明了,函数对象也可像普通函数一样被调用。函数对象的属性如果和函数本身的内部逻辑无关,该属性在函数执行时就不起作用,相当于被忽略。
注:
上面两段代码输出的差异是 Node.js 和 Chrome 之间的环境差异。
- Chrome
console.log(app); // ƒ (x) { console.log(x); }
console.log('app', app); // app ƒ (x) { console.log(x); }
- Node.js
console.log(app); // { [Function: app] listen: [Function] }
console.log('app', app); // app ƒ (x) { console.log(x); }