node.js 筆記

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)分離

image
  • 這是一個(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]

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末灼舍,一起剝皮案震驚了整個(gè)濱河市吼和,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌骑素,老刑警劉巖炫乓,帶你破解...
    沈念sama閱讀 211,042評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異献丑,居然都是意外死亡末捣,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門(mén)创橄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)箩做,“玉大人,你說(shuō)我怎么就攤上這事妥畏“畎睿” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,674評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵醉蚁,是天一觀的道長(zhǎng)燃辖。 經(jīng)常有香客問(wèn)我,道長(zhǎng)馍管,這世上最難降的妖魔是什么郭赐? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,340評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮确沸,結(jié)果婚禮上捌锭,老公的妹妹穿的比我還像新娘。我一直安慰自己罗捎,他們只是感情好观谦,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,404評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著桨菜,像睡著了一般豁状。 火紅的嫁衣襯著肌膚如雪捉偏。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,749評(píng)論 1 289
  • 那天泻红,我揣著相機(jī)與錄音夭禽,去河邊找鬼。 笑死谊路,一個(gè)胖子當(dāng)著我的面吹牛讹躯,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播缠劝,決...
    沈念sama閱讀 38,902評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼潮梯,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了惨恭?” 一聲冷哼從身側(cè)響起秉馏,我...
    開(kāi)封第一講書(shū)人閱讀 37,662評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎脱羡,沒(méi)想到半個(gè)月后萝究,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,110評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡锉罐,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年糊肤,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片氓鄙。...
    茶點(diǎn)故事閱讀 38,577評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡馆揉,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出抖拦,到底是詐尸還是另有隱情升酣,我是刑警寧澤,帶...
    沈念sama閱讀 34,258評(píng)論 4 328
  • 正文 年R本政府宣布态罪,位于F島的核電站噩茄,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏复颈。R本人自食惡果不足惜绩聘,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,848評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望耗啦。 院中可真熱鬧凿菩,春花似錦、人聲如沸帜讲。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,726評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)似将。三九已至获黔,卻和暖如春箱玷,著一層夾襖步出監(jiān)牢的瞬間真屯,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,952評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工颜阐, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留纫骑,地道東北人塔嬉。 一個(gè)月前我還...
    沈念sama閱讀 46,271評(píng)論 2 360
  • 正文 我出身青樓隔显,卻偏偏與公主長(zhǎng)得像项鬼,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子耻陕,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,452評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容