JavaScript物件導向之一(封裝)

Pomelo1213發表於2018-04-10

寫在前面


首先這篇文章是來自阮一峰大佬的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方法就可以。兒子沒有方法去父親身上找,這不就有點像物件導向了嗎?

未完。。。

相關文章