https://github.com/nswbmw/N-blog/tree/master/book
啟動(dòng)服務(wù)
- mongod --config /usr/local/etc/mongod.conf
- cd /usr/local/bin 終端進(jìn)去
- ./mongo 查看并且鏈接
終止服務(wù)
- pkill mongod
-
引入:
- import {firstName, lastName, year} from './profile';
-
輸出:
- export {firstName, lastName, year};
-
初始化:
- npm init
-
下載模塊:
- npm i express --save
var express = require('express');
var app = express();
app.use(express.bodyParser());//現(xiàn)實(shí)body
app.all('/', (req, res) => {
res.send(req.body.title + req.body.text);
});
app.listen(3000);
- res.send('Hello World') 比 res.end('Hello World')
- 省去諸如添加Content-Length之類的事情
- 每次修改代碼保存后译打,就自自動(dòng)啟動(dòng)
npm WARN checkPermissions Missing write access(權(quán)限問(wèn)題
sudo npm install -g supervisor
運(yùn)行 supervisor --harmony index 啟動(dòng)程序 cd進(jìn)去
kill node 關(guān)閉
supervisor start app
停止進(jìn)程: control+c
//localhost:3000/users/nswbmw
const express = require('express')
const app = express()
app.get('/',(req,res) => {
res.send('hello, express ')
})
app.get('/users/:name',(req,res) => {
res.send('hello' + req.params.name)
})
app.listen(3000)
- req.query: 解析后的 url 中的 querystring愚铡,如 ?name=haha夺饲,req.query 的值為 {name: 'haha'}
- req.params: 解析 url 中的占位符辉巡,如 /:name,訪問(wèn) /haha,req.params 的值為 {name: 'haha'}
- req.body: 解析后請(qǐng)求體猖吴,需使用相關(guān)的模塊摔刁,如 body-parser,請(qǐng)求體為 {"name": "haha"}海蔽,則 req.body 為 {name: 'haha'}
模塊加載
exports.Hello = Hello
var Hello = require('./hello').Hello 來(lái)獲取
--
module.exports = Hello
var Hello = require('./hello')
路由
index.js
'use strict'
const express = require('express')
const app = express()
const indexRouter = require('./routes/index')
const userRouter = require('./routes/users')
app.use('/',indexRouter)
app.use('/users',userRouter)
app.listen(3000)
router index.js
'use strict'
const express = require('express')
const router = express.Router()
router.get('/', (req, res) => {
res.send('hello, express')
})
module.exports = router
router users.js
'use strict'
const express = require('express')
const router = express.Router()
router.get('/users/:name',(req,res) => {
res.send('hello, '+req.params.name)
})
module.exports = router
- npm i ejs --save
模版
index.js
'use strict'
const path = require('path')
const express = require('express')
const app = express()
const indexRouter = require('./routes/index')
const userRouter = require('./routes/users')
app.set('views', path.join(__dirname, 'views'))// 設(shè)置存放模板文件的目錄,查找模版路徑
app.set('view engine', 'ejs')// 設(shè)置模板引擎為 ejs
app.use('/',indexRouter)
app.use('/users',userRouter)
app.listen(3000)
routes/users.js
'use strict'
const express = require('express')
const router = express.Router()
router.get('/:name', (req, res) =>{
res.render('users', {
name: req.params.name
})
})
module.exports = router
//通過(guò)調(diào)用 res.render 函數(shù)渲染 ejs 模板共屈,res.render 第一個(gè)參數(shù)是模板的名字绑谣,這里是 users 則會(huì)匹配 views/users.ejs,第二個(gè)參數(shù)是傳給模板的數(shù)據(jù)拗引,這里傳入 name借宵,則在 ejs 模板中可使用 name。res.render 的作用就是將模板和數(shù)據(jù)結(jié)合生成 html矾削,同時(shí)設(shè)置響應(yīng)頭中的 Content-Type: text/html壤玫,告訴瀏覽器我返回的是 html,不是純文本哼凯,要按 html 展示∮洌現(xiàn)在我們?cè)L問(wèn) localhost:3000/users/haha
views/users.ejs
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
body {padding: 50px;font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;}
</style>
</head>
<body>
<h1><%= name.toUpperCase() %></h1>
<p>hello, <%= name %></p>
</body>
</html>
上面html name.toUpperCase()大寫(xiě)
<% code %>:運(yùn)行 JavaScript 代碼,不輸出
<%= code %>:顯示轉(zhuǎn)義后的 HTML內(nèi)容
<%- code %>:顯示原始 HTML 內(nèi)容
supplies: ['mop', 'broom', 'duster']
//模版拼接
<ul>
<% for(var i=0; i<supplies.length; i++) {%>
<li><%= supplies[i] %></li>
<% } %>
</ul>
//形成的樣式
<ul>
<li>mop</li>
<li>broom</li>
<li>duster</li>
</ul>
模版引用
我們使用模板引擎通常不是一個(gè)頁(yè)面對(duì)應(yīng)一個(gè)模板断部,這樣就失去了模板的優(yōu)勢(shì)猎贴,而是把模板拆成可復(fù)用的模板片段組合使用,如在 views 下新建 header.ejs 和 footer.ejs蝴光,并修改 users.ejs:
views/header.ejs
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
body {padding: 50px;font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;}
</style>
</head>
<body>
views/footer.ejs
</body>
</html>
views/users.ejs
拼接成網(wǎng)頁(yè)<%-include('文件名字')%>
<%- include('header') %>
<h1><%= name.toUpperCase() %></h1>
<p>hello, <%= name %></p>
<%- include('footer') %>
中間件
index.js
const express = require('express');
const app = express();
app.use(function(req, res, next) {
console.log('1');
next();
});
app.use(function(req, res, next) {
console.log('2');
res.status(200).end();
});
app.listen(3000);
訪問(wèn) localhost:3000她渴,終端會(huì)輸出:
1
2
錯(cuò)誤處理
index.js
const express = require('express');
const app = express()
app.use(function(req, res, next) {
console.log('1')
next(new Error('haha'))
});
app.use(function(req, res, next) {
console.log('2')
res.status(200).end()
});
//錯(cuò)誤處理
app.use(function(err, req, res, next) {
console.error(err.stack)
res.status(500).send('Something broke!')
})
app.listen(3000)
//此時(shí)訪問(wèn) localhost:3000,命令行輸出:1蔑祟,瀏覽器會(huì)顯示:Something broke!趁耗。
events 事件
var events = require('events');
var emitter = new events.EventEmitter()
emitter.on('someEvent', function(arg1, arg2) {
console.log('listener1', arg1, arg2)
})
emitter.on('someEvent', function(arg1, arg2) {
console.log('listener2', arg1, arg2)
})
emitter.emit('someEvent', 'byvoid', 1991)
//運(yùn)行結(jié)果
//listener1 byvoid 1991
//listener2 byvoid 1991
以上例子中,emitter 為事件 someEvent 注冊(cè)了兩個(gè)事件監(jiān)聽(tīng)器,然后發(fā)射了 someEvent 事件。運(yùn)行結(jié)果中可以看到兩個(gè)事件監(jiān)聽(tīng)器回調(diào)函數(shù)被先后調(diào)用做瞪。這就是EventEmitter最簡(jiǎn)單的用法对粪。接下來(lái)我們介紹一下EventEmitter常用的API。
EventEmitter.on(event, listener) 為指定事件注冊(cè)一個(gè)監(jiān)聽(tīng)器,接受一個(gè)字
符串event 和一個(gè)回調(diào)函數(shù)listener装蓬。
EventEmitter.emit(event, [arg1], [arg2], [...]) 發(fā)射 event 事件,傳
遞若干可選參數(shù)到事件監(jiān)聽(tīng)器的參數(shù)表著拭。
EventEmitter.once(event, listener) 為指定事件注冊(cè)一個(gè)單次監(jiān)聽(tīng)器,即
監(jiān)聽(tīng)器最多只會(huì)觸發(fā)一次,觸發(fā)后立刻解除該監(jiān)聽(tīng)器。
EventEmitter.removeListener(event, listener) 移除指定事件的某個(gè)監(jiān)聽(tīng)
器,listener 必須是該事件已經(jīng)注冊(cè)過(guò)的監(jiān)聽(tīng)器牍帚。
EventEmitter.removeAllListeners([event]) 移除所有事件的所有監(jiān)聽(tīng)器, 如果指定 event,則移除指定事件的所有監(jiān)聽(tīng)器儡遮。
fs.readfile
//異步的 fs.readFile()
//同步的 fs.readFileSync()
var fs = require('fs');
fs.readFile('content.txt', function(err, data) {
if (err) {
console.error(err);
} else {
console.log(data);
}
});
//假設(shè) content.txt 中的內(nèi)容是 UTF-8 編碼的 Text 文本文件示例,運(yùn)行結(jié)果如下:
//<Buffer 54 65 78 74 20 e6 96 87 e6 9c ac e6 96 87 e4 bb b6 e7 a4 ba e4 be 8b>
var fs = require('fs');
fs.readFile('content.txt', 'utf-8', function(err, data) {
if (err) {
console.error(err);
} else {
console.log(data);
}
});
//那么運(yùn)行結(jié)果則是:
//Text 文本文件示例
npm
無(wú)參數(shù)的 npm install 的功能就是 檢查當(dāng)前目錄下的 package.json,并自動(dòng)安裝所有指定的依賴。
express 架構(gòu)分離
- 這是一個(gè)典型的 MVC 架構(gòu),瀏覽器發(fā)起請(qǐng)求,由路由控制器接受,根據(jù)不同的路徑定 向到不同的控制器暗赶”杀遥控制器處理用戶的具體請(qǐng)求,可能會(huì)訪問(wèn)數(shù)據(jù)庫(kù)中的對(duì)象,即模型部分□逅妫控制器還要訪問(wèn)模板引擎,生成視圖的 HTML,最后再由控制器返回給瀏覽器,完成一次請(qǐng)求十嘿。
express 路徑匹配
如我們想要展示一個(gè)用戶的個(gè)人頁(yè)面,路徑為 /user/[username],可以用下面的方法定義路由規(guī)則:
app.get('/user/:username', function(req, res) {
res.send('user: ' + req.params.username);
});
REST風(fēng)格
- 請(qǐng)求方式 安全 冪等
- GET 是 是
- POST 否 否
- PUT 否 是
- DELETE 否 是
- 所謂安全是指沒(méi)有副作用,即請(qǐng)求不會(huì)對(duì)資源產(chǎn)生變動(dòng),連續(xù)訪問(wèn)多次所獲得的結(jié)果不受訪問(wèn)者的影響。而冪等指的是重復(fù)請(qǐng)求多次與一次請(qǐng)求的效果是一樣的,比如獲取和更新操作是冪等的,這與新增不同岳锁。刪除也是冪等的,即重復(fù)刪除一個(gè)資源,和刪除一次是 一樣的绩衷。
Express 對(duì)每種 HTTP 請(qǐng)求方法綁定:
GET
app.get(path, callback)POST
app.post(path, callback)PUT
app.put(path, callback)DELETE
app.delete(path, callback)PATCH
app.patch(path, callback)TRACE
app.trace(path, callback)CONNECT
app.connect(path, callback)OPTIONS
app.options(path, callback)所有方法
app.all(path, callback)
Express 路由控制權(quán)轉(zhuǎn)移
Express 提供了路由控制權(quán)轉(zhuǎn)移的方法,即回調(diào)函數(shù)的第三個(gè)參數(shù)next,通過(guò)調(diào)用 next(),會(huì)將路由控制權(quán)轉(zhuǎn)移給后面的規(guī)則,例如:
app.all('/user/:username', function(req, res, next) {
console.log('all methods captured');
next();
});
app.get('/user/:username', function(req, res) {
res.send('user: ' + req.params.username);
});
//如果調(diào)用next(“route”),則會(huì)跳過(guò)當(dāng)前路由的其它中間件,直接將控制權(quán)交給下一個(gè)路由咳燕。
使用模版引擎
我們?cè)?app.js 中通過(guò)以下兩個(gè)語(yǔ)句設(shè)置了模板引擎和頁(yè)面模板的位置:
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
表明要使用的模板引擎是 ejs,頁(yè)面模板在 views 子目錄下勿决。在 routes/index.js 的 exports.index 函數(shù)中通過(guò)如下語(yǔ)句調(diào)用模板引擎:
res.render('index', { title: 'Express' });
res.render 的功能是調(diào)用模板引擎,并將其產(chǎn)生的頁(yè)面直接返回給客戶端。它接受 兩個(gè)參數(shù),第一個(gè)是模板的名稱,即 views 目錄下的模板文件名,不包含文件的擴(kuò)展名;第 二個(gè)參數(shù)是傳遞給模板的數(shù)據(jù),用于模板翻譯招盲。index.ejs 內(nèi)容如下:
<h1><%= title %></h1>
<p>Welcome to <%= title %></p>
上面代碼其中有兩處 <%= title %>,用于模板變量顯示,它們?cè)谀0宸g時(shí)會(huì)被替換 成 Express,因?yàn)?res.render 傳遞了 { title: 'Express' }低缩。
ejs 的標(biāo)簽系統(tǒng)非常簡(jiǎn)單,它只有以下3種標(biāo)簽。
<% code %>:JavaScript 代碼曹货。
<%= code %>:顯示替換過(guò) HTML 特殊字符的內(nèi)容咆繁。
<%- code %>:顯示原始 HTML 內(nèi)容。 我們可以用它們實(shí)現(xiàn)頁(yè)面模板系統(tǒng)能實(shí)現(xiàn)的任何內(nèi)容控乾。
會(huì)話支持Cookie
為了在無(wú)狀態(tài)的 HTTP 協(xié)議之上實(shí)現(xiàn)會(huì)話,Cookie 誕生了么介。Cookie 是一些存儲(chǔ)在客戶 端的信息,每次連接的時(shí)候由瀏覽器向服務(wù)器遞交,服務(wù)器也向?yàn)g覽器發(fā)起存儲(chǔ) Cookie 的 請(qǐng)求,依靠這樣的手段服務(wù)器可以識(shí)別客戶端。我們通常意義上的 HTTP 會(huì)話功能就是這樣 實(shí)現(xiàn)的蜕衡。具體來(lái)說(shuō),瀏覽器首次向服務(wù)器發(fā)起請(qǐng)求時(shí),服務(wù)器生成一個(gè)唯一標(biāo)識(shí)符并發(fā)送給 客戶端瀏覽器,瀏覽器將這個(gè)唯一標(biāo)識(shí)符存儲(chǔ)在 Cookie 中,以后每次再發(fā)起請(qǐng)求,客戶端 瀏覽器都會(huì)向服務(wù)器傳送這個(gè)唯一標(biāo)識(shí)符,服務(wù)器通過(guò)這個(gè)唯一標(biāo)識(shí)符來(lái)識(shí)別用戶壤短。
methodOverride
因?yàn)槲覀儐螕舫霭l(fā)的是post,而服務(wù)器上是put事件.
現(xiàn)在想讓服務(wù)器端依然是put接受,html上依然是post請(qǐng)求. 加app.use(express.methodOverride());
http://www.bubuko.com/infodetail-503315.html
重定位
'use strict'
const express = require('express')
const app = express()
app.get('/', function (req, res) {
console.log('1')
});
app.get('/one', function(req, res) {
console.log('2')
return res.redirect('/');//是重定向功能,
})
//訪問(wèn)http://localhost:3000/one 會(huì)輸出:2,1
connect-flash
const express = require('express')
const session = require('express-session')
const flash = require('connect-flash');
const app = express()
app.use(session({
secret: 'one', //通過(guò)設(shè)置 secret 來(lái)計(jì)算 hash 值并放在 cookie 中慨仿,使產(chǎn)生的 signedCookie 防篡改
cookie: {maxAge: 60000}, // 過(guò)期時(shí)間久脯,過(guò)期后 cookie 中的 session id 自動(dòng)刪除
}))
app.use(flash());//中間件
app.get('/', function (req, res) {
//取出來(lái),然后就消失了
console.log(req.flash('one'))
res.send('success')
})
app.get('/one', function(req, res) {
req.flash('one','1')//存 key value值
return res.redirect('/')//是重定向功能,
})
//這是session 設(shè)置詳情
'use strict'
const express = require('express')
const session = require('express-session')
const flash = require('connect-flash')
const MongoStore = require('connect-mongo')(session);
const app = express()
app.use(session({
name: 'app'
secret: 'one', //通過(guò)設(shè)置 secret 來(lái)計(jì)算 hash 值并放在 cookie 中镰吆,使產(chǎn)生的 signedCookie 防篡改
cookie: {maxAge: 60000}, // 即60000后session和相應(yīng)的cookie失效過(guò)期除
resave: false,//是指每次請(qǐng)求都重新設(shè)置session cookie帘撰,假設(shè)你的cookie是10分鐘過(guò)期,每次請(qǐng)求都會(huì)再設(shè)置10分鐘
saveUninitialized: true//是指無(wú)論有沒(méi)有session cookie万皿,每次請(qǐng)求都設(shè)置個(gè)session cookie 摧找,默認(rèn)給個(gè)標(biāo)示為 connect.sid
//數(shù)據(jù)庫(kù)儲(chǔ)存
store: new MongoStore({ //創(chuàng)建新的mongodb數(shù)據(jù)庫(kù)
host: 'localhost', //數(shù)據(jù)庫(kù)的地址,本機(jī)的話就是127.0.0.1牢硅,也可以是網(wǎng)絡(luò)主機(jī)
port: 27017, //數(shù)據(jù)庫(kù)的端口號(hào)
db: 'test-app' //數(shù)據(jù)庫(kù)的名稱蹬耘。
})
}))
app.use(flash());//中間件
app.get('/', function (req, res) {
//取出來(lái),然后就消失了
console.log(req.flash('one'))
res.send('success')
});
app.get('/one', function(req, res) {
req.flash('one','1')//存 key value值
return res.redirect('/')//是重定向功能,
})
// 監(jiān)聽(tīng)端口减余,啟動(dòng)程序
app.listen(3000, function () {
console.log(`success`)
})
require
我們要在 /home/byvoid/develop/foo.js 中使用 require('bar.js') 命令,Node.js會(huì)依次查找:
/home/byvoid/develop/node_modules/bar.js
/home/byvoid/node_modules/bar.js
/home/node_modules/bar.js
/node_modules/bar.js
循環(huán)便利综苔,里面異步回調(diào)-有坑
var fs = require('fs');
var files = ['a.txt', 'b.txt', 'c.txt'];
for (var i = 0; i < files.length; i++) {
fs.readFile(files[i], 'utf-8', function(err, contents) {
console.log(files);
console.log(i);
console.log(files[i]);
});
}
運(yùn)行結(jié)果如下:
[ 'a.txt', 'b.txt', 'c.txt' ]
3
undefined
[ 'a.txt', 'b.txt', 'c.txt' ]
3
undefined
[ 'a.txt', 'b.txt', 'c.txt' ]
3
undefined
//三次輸出的 i 的值都是 3,超出了 files 數(shù)組的下標(biāo) 范圍,因此 files[i] 的值就是 undefined 了。
//現(xiàn)在問(wèn)題就明朗了:原因是3次讀取文件的回調(diào)函數(shù)事實(shí)上是同一個(gè)實(shí)例,退出循環(huán)時(shí) i 的值就是 files.length 的值位岔。既然 i 的值是 3,引用到的 i 值是上面循環(huán)執(zhí)行結(jié)束后的值,因此不能分辨如筛。
//解決方案
var fs = require('fs');
var files = ['a.txt', 'b.txt', 'c.txt'];
files.forEach(function(filename) {
fs.readFile(filename, 'utf-8', function(err, contents) {
console.log(filename + ': ' + contents);
});
});
構(gòu)造函數(shù)
//創(chuàng)建復(fù)雜的對(duì)象。
function User(name, uri) {
this.name = name;
this.uri = uri;
this.display = function() {
console.log(this.name);
}
}
//以上是一個(gè)簡(jiǎn)單的構(gòu)造函數(shù),接下來(lái)用new 語(yǔ)句來(lái)創(chuàng)建對(duì)象:
var someuser = new User('byvoid', 'http://www.byvoid.com');
//然后就可以通過(guò)someuser 來(lái)訪問(wèn)這個(gè)對(duì)象的屬性和方法了抒抬。
this指針
//this 指針不屬于某個(gè)函數(shù),而是函數(shù)調(diào)用時(shí)所屬的對(duì)象杨刨。
var someuser = {
name: 'byvoid',
func: function() {
console.log(this.name);
}
};
var foo = {
name: 'foobar'
};
someuser.func(); // 輸出 byvoid
foo.func = someuser.func;
foo.func(); // 輸出 foobar
name = 'global';
func = someuser.func; func(); // 輸出 global
call 和 apply
//call 和 apply 的功能是一致的,兩者細(xì)微的差別在于 call 以參數(shù)表來(lái)接受被調(diào)用函 數(shù)的參數(shù),而 apply 以數(shù)組來(lái)接受被調(diào)用函數(shù)的參數(shù)。
var someuser = {
name: 'byvoid',
display: function(words) {
console.log(this.name + ' says ' + words);
}
};
var foo = {
name: 'foobar'
};
someuser.display.call(foo, 'hello'); // 輸出 foobar says hello
輸出了 foobar.someuser.display 是 被調(diào)用的函數(shù),它通過(guò) call 將上下文改變?yōu)?foo 對(duì)象,因此在函數(shù)體內(nèi)訪問(wèn) this.name 時(shí),實(shí)際上訪問(wèn)的是 foo.name,因而輸出了foobar擦剑。
bind綁定
bind 方法來(lái)永久地綁定函數(shù)的上下文,使其無(wú)論被誰(shuí)調(diào)用,上 下文都是固定的
var someuser = {
name: 'byvoid',
func: function() {
console.log(this.name);
}
};
var foo = {
name: 'foobar'
};
foo.func = someuser.func;
foo.func(); // 輸出 foobar
foo.func1 = someuser.func.bind(someuser);
foo.func1(); // 輸出 byvoid func = someuser.func.bind(foo);
func(); // 輸出 foobar func2 = func;
func2(); // 輸出 foobar
使用 bind 綁定參數(shù)表
bind 方法還有一個(gè)重要的功能:綁定參數(shù)表
var person = {
name: 'byvoid', 7 says: function(act, obj) {
console.log(this.name + ' ' + act + ' ' + obj); }
};
person.says('loves', 'diovyb'); // 輸出 byvoid loves diovyb
byvoidLoves = person.says.bind(person, 'loves');
byvoidLoves('you'); // 輸出 byvoid loves you
可以看到,byvoidLoves 將 this 指針綁定到了 person,并將第一個(gè)參數(shù)綁定到 loves,之后在調(diào)用 byvoidLoves 的時(shí)候,只需傳入第三個(gè)參數(shù)妖胀。這個(gè)特性可以用于創(chuàng)建 一個(gè)函數(shù)的“捷徑”.
原型鏈
兩個(gè)特殊的對(duì)象: Object 與 Function,它們都是構(gòu)造函數(shù),用于生成對(duì)象可免。Object.prototype 是所有對(duì)象的祖先,Function.prototype 是所有函數(shù)的原型,包括構(gòu)造函數(shù)。
我把 JavaScript 中的對(duì)象分為三類:
一類是用戶創(chuàng)建的對(duì)象,用戶創(chuàng)建的對(duì)象,即一般意義上用 new 語(yǔ)句顯式構(gòu)造的對(duì)象做粤。
一類是構(gòu)造函數(shù)對(duì)象,構(gòu)造函數(shù)對(duì)象指的是普通的構(gòu)造函數(shù),即通過(guò) new 調(diào)用生成普通對(duì)象的 函數(shù)。
一類是原型對(duì)象,原型對(duì)象特指構(gòu)造函數(shù) prototype 屬性指向的 對(duì)象捉撮。
這三類對(duì)象中每一類都有一個(gè) __proto__ 屬 性,它指向該對(duì)象的原型,從任何對(duì)象沿著它開(kāi)始遍歷都可以追溯到 Object.prototype怕品。
構(gòu)造函數(shù)對(duì)象有 prototype 屬性,指向一個(gè)原型對(duì)象,通過(guò)該構(gòu)造函數(shù)創(chuàng)建對(duì)象時(shí),被創(chuàng) 建對(duì)象的 __proto__ 屬性將會(huì)指向構(gòu)造函數(shù)的 prototype 屬性。原型對(duì)象有 constructor 屬性,指向它對(duì)應(yīng)的構(gòu)造函數(shù)巾遭。
function Foo() {
}
Object.prototype.name = 'My Object';
Foo.prototype.name = 'Bar';
var obj = new Object();
var foo = new Foo();
console.log(obj.name); // 輸出 My Object
console.log(foo.name); // 輸出 Bar
console.log(foo.__proto__.name); // 輸出 Bar
console.log(foo.__proto__.__proto__.name); // 輸出 My Object
console.log(foo.__proto__.constructor.prototype.name); // 輸出 Bar
[圖片上傳失敗...(image-badd9-1512039587570)]
對(duì)象定義
盡量將所有的成員函數(shù)通過(guò)原型定義,將屬性在構(gòu)造函數(shù)內(nèi)定義,然后對(duì)構(gòu)造函數(shù)使用 new 關(guān)鍵字創(chuàng)建對(duì)象肉康。絕對(duì)不要把屬性作為原型定義,因?yàn)楫?dāng)要定義的屬性是一個(gè)對(duì)象的 時(shí)候,不同實(shí)例中的屬性會(huì)指向同一地址。
正確:
function FooObj(bar) {
//在構(gòu)造函數(shù)中初始化屬性
this.bar = bar;
this.arr = [1, 2, 3];
}
//使用原型定義成員函數(shù)
FooObj.prototype.func = function() {
console.log(this.arr);
};
var obj1 = new FooObj('obj1');
var obj2 = new FooObj('obj2');
obj1.arr.push(4);
obj1.func(); // [1, 2, 3, 4]
obj2.func(); // [1, 2, 3]