工廠模式
優點:接受參數,可以無數次的調用這個函數,創建Person對象,而每次他都可以返回一個包含三個屬性一個方法的對象。
缺點:雖然解決了創建多個相似對象的問題,但是沒有解決對象識別的問題(即怎么知道一個對象的類型)。
構造函數模式
JS中可以創建自定義的構造函數,從而定義自定義對象屬性和方法。
♦ Person()中的代碼和createPerson()的不同之處:
1、沒有顯式地創建對象
2、直接將屬性和方法賦給了this對象
3、沒有return語句
♦ 要創建Person對象的新實例,必須使用new操作符。以這種方式調用構造函數世紀上會經歷一下四個步驟:
1、創建一個新對象。
2、將構造函數的作用域賦給新對象(因此this就指向這個新對象)
3、執行構造函數中的代碼(為這個新對象添加屬性)
4、返回新對象
優點:創建自定義的構造函數意味着將來可以將它的實例標識為一種特定的類型。
缺點:每個方法都要在每個實例上重新創新一遍。person1,person2都有一個名為sayName()的方法,但這兩個方法不是同一個Function的實例。因為ECMAScript中的函數是對象,所以每定義一個函數都是實例化了一個對象。
原型模式
♦理解原型對象
1、我們創建的每個函數都有一個prototype(原型)屬性,這個屬性是一個指針,指向函數的原型對象。
2、默認情況下,所有原型對象都自動獲得一個constructor屬性,這個屬性是一個指向prototype屬性所在函數的指針。
3、當調用構造函數創建一個新實例后,該實例的內部將包含一個指針(內部屬性)[[Prototype]],指向構造函數的原型對象。
注意:
1、Person 的每個實例都包含一個內部屬性,該屬性僅僅指向了Person。prototype;換句話說,他么與構造函數之間沒有直接的關系。
2、雖然這兩個實例都不包含屬性和方法,但我們卻可以調用person1.sayName()。這是通過查找對象屬性的過程來實現的。
當代碼讀取某個對象的屬性時,都會執行一次搜索,目標是具有給定名字的屬性。搜索首先從對象實例本身開始,如果在實例中找到了具有給定名字的屬性,則返回該屬性的值,如果沒有找到,則繼續搜索指針指向的原型對象,在原型對象中查找具有給定名字的屬性。
優點:減少了代碼的重復,也可用標識來創建對象。
缺點:1、它省略了為構造函數傳遞初始化參數這一環節,結果所有勢力在默認情況下都將取得相同的屬性值。
2、原型中所有屬性是被很多勢力共享的,這種共享對函數來說非常適合,對於那些包含基本值的屬性也還說得過去,但是對於包含引用類型值的屬性來說,就是一個問題了,因為實例一般都有屬於自己的全部屬性。
組合使用構造函數模式和原型模式
構造函數模式用於定義實例屬性,而原型模式用於定義方法和共享的屬性。這樣,每個實例都有自己的一份實力屬性的副本,但同時又共享着對方法的引用,最大限度的節省了內存。而且還支持向構造函數傳遞參數。這種方式也是ECMAScript種使用最廣泛,認同度最高的一種創建自定義類型的方法。
另外還有動態原型、寄生構造函數模式、穩妥構造函數模式等方式。