寫在前面
首先這篇文章是來自阮一峰大佬的2010年的部落格!!!!戳這裡
我2010的時候還在談戀愛(逃)
自己在學習到物件導向這裡有些疑惑,越學越糊塗,可能是Java的副影響。。 : -(
打算重頭梳理一下,然後看了這篇部落格,覺得讀完了應該自己輸出一遍才能是自己的。
在JavaScript裡面物件是很常見,在這裡函式也成為函式物件。但是這裡物件又不是真正的物件,它的語法中沒有Class(不涉及ES6的話),那麼封裝成物件應該怎麼去做呢?,下面就來具體說說:
1.原始模式
我們有兩隻貓,它有自己的顏色和名字:
var cat1 = {
name: 'po',
color: 'orange'
}
var cat2 = {
name: 'da',
color: 'white'
}
複製程式碼
缺點很明顯,如果我們有上千只貓,那我們就要累死了。所以就需要進行改進。
2.原始模式改進
function Cat(name, color){
return {
'name': name,
'color': color
}
}
var cat1 = Cat('po', 'orange')
var cat2 = Cat('da', 'white')
複製程式碼
這樣是不是就好看了許多,但是缺點是cat1和cat2沒有實質關聯,兩者純粹是函式呼叫。這樣跟我們的物件導向一點都不像。
3.建構函式模式
由於以上的缺點就出現了建構函式的形式,如下:
function Cat(name, color){
this.name = name
this.color = color
}
var cat1 = new Cat('po', 'orange')
var cat2 = new Cat('da', 'white')
alert(cat1.name) //po
alert(cat2.name) //da
複製程式碼
這樣一來就可以將cat1和cat2創造了關聯,還使用了new來進行例項化。
這時cat1和cat2會自動含有一個constructor屬性,指向它們的建構函式。
console.log(cat1.constructor === Cat) //true
console.log(cat2.constructor === Cat) //true
複製程式碼
上面這段話是大佬原文中的話,但是我覺得這段話造成了誤導。所以重新說一下。上面兩段程式碼為true,沒錯。但是!!在cat1和cat2本身上是沒有constructor屬性,而是會去Cat.prototype上面去找,所以準確的來說應該是這樣的
console.log(Cat.prototype === Cat) //true
複製程式碼
這裡順帶提一下new做了哪些事
var temp = {}
temp.__proto__ = Cat.prototype
Cat.call(temp)
return temp
複製程式碼
看了new做的第二件事,就應該理解了為什麼cat1和cat2本身沒有constructor。
建構函式模式問題
這麼好的方法實現,為什麼還要改進呢?
//如果我需要新增一個eat該怎麼寫呢?
function Cat(name, color){
this.name = name
this.color = color
this.eat = function(){ console.log('eaaaaaaaaaaaaat') }
}
var cat1 = new Cat('po', 'orange')
var cat2 = new Cat('da', 'white')
console.log(cat1.eat) //eaaaaaaaaaaaaat
console.log(cat2.eat) //eaaaaaaaaaaaaat
console.log(cat1.eat === cat2.eat) //false
複製程式碼
看上面,確實是實現了eat的方法,但是這個方法對應的不是同一塊記憶體,這是為什麼呢?因為我們new幹了這件壞事,new中每次都是建立了一個空物件。
Prototype模式
怎麼改進上面的問題呢?
Cat.prototype.eat = function(){ console.log('eaaaaaaaaaaaaat') }
cat1.eat() //eaaaaaaaaaaaaat
cat2.eat() //eaaaaaaaaaaaaat
console.log(cat1.eat === cat2.eat) //true
複製程式碼
對,直接在建構函式的原型上面去找eat方法就可以。兒子沒有方法去父親身上找,這不就有點像物件導向了嗎?
未完。。。