1. 工廠模式
(一)實現方法:在函數內創建一個對象並給對象賦予屬性及方法,最終將對象返回。
function cPerson(name,sex,age){
var o = new Object();
o.name = name;
o.sex = sex;
o.age = age;
o.show = function(){
console.log(this.name,this.age,this.sex);
}
return o;
}
var p1 = cPerson('瀚哲,'男','18');
p1.show();
var p2 = cPerson('醜小鴨','女','18');
p2.show();
(二)工廠方式的問題:使用工廠模式能夠創建一個包含所有信息的對象,可以無數次的調用的這個函數。雖然其解決了創建多個相似對象的問題,但卻沒有解決對象識別的問題(即如何得知一個對象的來源和類型),因此出現了構造函數。
2. 構造函數模式
(一)實現方法
function CPerson(name,sex,age) {
this.name = name;
this.sex = sex;
this.age = age;
this.show = function () {
console.log(this.name, this.age, this.sex);
}
}
var p1 = new CPerson('瀚哲 ','男','18');
p1.show();
var p2 = new CPerson('醜小鴨','女','14');
p2.show();
(二)構造函數與工廠模式的不同之處:
1.構造函數首字母大寫
2.沒有顯式地創建對象
3.將屬性和方法賦值給了 this 對象
4.沒有return語句
(三)以這種方式來調用構造函數會大致經歷以下幾個步驟:
1.創建一個新的對象
2.將構造函數的作用域賦值給這個對象(因此this就指向了這個對象)
3.執行構造函數中的代碼(即給新對象添加屬性和方法的過程)
4.返回對象
(四)構造函數的問題:
1.使用構造函數的最大的問題在於每次創建實例的時候都要重新創建一次方法(理論上每次創建對象的時候對象的屬性均不同,而對象的方法是相同的),然而創建兩次完全相同的方法是沒有必要的,因此,我們可以將函數移到對象外面;
2.在全局作用域中定義了許多僅供特定對象使用的方法,浪費空間,顯然失去了面向對象封裝性了,因此可以通過原型來解決此問題。
3. 原型模式
(一)實現方法: 創建的每個函數都有prototype(原型)屬性,這個屬性是一個指針,指向一個對象,而這個對象的用途是包含可以由特定類型的所有實例共享的屬性和方法。使用原型對象的好處就是可以讓所有對象實例共享它所包含的屬性及方法。
function CPerson(){
}
CPerson.prototype.name='瀚哲';
CPerson.prototype.sex='男';
CPerson.prototype.age=100;
CPerson.prototype.show=function(){
console.log(this.name, this.age, this.sex);
}
var p1 = new CPerson();
p1.show(); //瀚哲 18 男
var p2 = new CPerson();
p2.show();//瀚哲 18 男
console.log(p1.show == p2.show) //打印值爲true
(二)原型模式的問題:
1.它省略了構造函數傳遞初始化參數這一環節,結果所有實例在默認情況下都取得了相同的屬性值,這樣非常不方便;
2.原型模式的最大問題在於共享的本性所導致,由於共享,因此一個實例修改了引用,另一個也隨之更改了引用。因此我們通常不單獨使用原型,而是結合原型模式與構造函數模式。
4. 混合模式
function CPerson(name,sex,age) {
this.name = name;
this.sex = sex;
this.age = age;
this.show();
}
CPerson.prototype.show = function(){
alert(this.name + this.sex + this.age)
}
var CPerson1 = new CPerson("甄瀚哲","男",18);
var CPerson2 = new CPerson("醜小鴨","女",18);
CPerson1.show();
CPerson2.show();
混合模式中構造函數模式用於定義實例屬性,而原型模式用於定義方法和共享屬性。每個實例都會有自己的一份實例屬性,但同時又共享着方法,最大限度的節省了內存。另外這種模式還支持傳遞初始參數。