建立javascript對象的方法

1、工廠模式

function person (name,age) {
    var p=new Object();
    p.name=name;
    p.age=age;
    p.showMessage=function(){
        console.log("name:"+this.name+" age:"+this.age);
    }
    return p;
}
var p1=person("k1",28);
var p2=person("k2",29);
console.log(p1.showMessage==p2.showMessage);//false  不是同一個showMessage方法
console.log(p1.constructor);//[object]  都是object

工廠模式的缺陷是:沒解決對象識別的問題,並且每一個對象的showMessage方法都不是同一個方法(每一個方法在每一個對象實例上都從新建立了一遍),增長了開銷
javascript

2、構造函數模式

function Person (name,age) {
    this.name=name;
    this.age=age;
    this.showMessage=function(){
        console.log("name:"+this.name+" age:"+this.age);
    }
}
var p1=new Person("k1",28);
var p2=new Person("k2",29);
console.log(p1.showMessage==p2.showMessage);//false  不是同一個showMessage方法
console.log(p1.constructor);//[Person]
console.log(p1 instanceof Person);// true

構造函數模式解決了對象識別的問題,可是每一個對象的showMessage方法不是同一個方法(每一個方法在每一個對象實例上都從新建立了一遍),增長了開銷java

3、原型模式

function Person () {
    
}
Person.prototype.name ="k";
Person.prototype.age =29;
Person.prototype.showMessage=function () {
    console.log("name:"+this.name+" age:"+this.age);
};

var p1=new Person();
p1.showMessage();//name:k age:29

var p2=new Person();
p2.showMessage();//name:k age:29

console.log(p1.showMessage==p2.showMessage);// true --引用的是同一函數
console.log(p1.constructor)//[Person]  --對象識別
console.log(p1 instanceof Person)//true  --對象識別
console.log(Person.prototype.isPrototypeOf(p1));// true
console.log(Object.getPrototypeOf(p1)==Person.prototype);// true

原型模式解決了「每一個方法在每一個對象實例上都從新建立了一遍」的問題,也解決了對象識別的問題數組

原型模式有個很大的問題是,由於掛載在函數prototype下面的全部對象、變量、函數都是被該函數的全部實例共享的,雖然經過實例p一、p2能夠訪問到prototype的屬性,可是卻不能修改屬性值,例如p1.name="k1",只是在p1實例上添加了一個name="k1"的屬性,並沒改到prototype.name。若是是值類型還好,若是是引用類型的話,就會有問題了,看以下的例子閉包

function Person () {    
};
Person.prototype.age =10;
Person.prototype.array=[1,2,3];

var p1=new Person();
var p2=new Person();
console.log(p1.array);// [1,2,3]
console.log(p2.array); //[1,2,3]
p1.array.push(4);
console.log(p1.array);//[1,2,3,4]
console.log(p2.array);//[1,2,3,4]

p1往array裏面添加了值,在p2也反映出來了,由於他們都是指向同一個arrayapp

4、組合使用構造函數模式和原型模式

這是最多見的建立對象的方式,結合了構造函數和原型模式的優勢函數

function Person (name,age) {
    this.name=name;
    this.age=age;
}

Person.prototype.showMessage = function() {
    console.log("name:"+this.name+" age:"+this.age);
};

var p1=new Person("k",30);
p1.showMessage();

5、動態原型模式

主要是解決:把全部的信息都封裝在構造函數中,更符合oo的思想this

function Person (name,age) {
    this.name=name;
    this.age=age;
    if(typeof this.showMessage!="function"){
        Person.prototype.showMessage=function(){
            console.log("name:"+this.name+" age:"+this.age);
        }
    }
}

var p1=new Person("k",30);
p1.showMessage();

6、寄生構造函數模式 

function Person (name,age) {
    var o=new Object();
    o.name=name;
    o.age=age;
    o.sayName=function(){
        console.log(this.name);
    };
    return o;
}
var p1=new Person("k",28);
p1.sayName();

寄生構造函數模式和工廠模式是如出一轍的,只不過建立對象的時候使用了new 關鍵字,上例:var p1=new Person("k",28)。spa

它的主要做用是:在這個構造函數裏面進行功能的擴展,例如,我想定義一個數組類型MyArray,它是以Array數組爲基礎的,有一個本身的方法,以下
prototype

function MyArray(){
    var values=new Array();
    values.push.apply(values,arguments);
    //本身定義的方法
    values.toPipedString=function(){ 
        return this.join('|');
    };
    return values;
}
var colors=new MyArray("red","blue","green");
console.log(colors.toPipedString());
console.log(colors instanceof Array);

7、穩妥構造函數模式

穩妥構造函數遵循與寄生構造函數類型的模式,但有兩點不一樣:一是不使用this,二是不使用new 調用構造函數code

function Person (name,age) {
    var o=new Object();
    var tempAge=age;

    o.name=name;
    o.age=age;

    o.sayName=function(){
        console.log(name);
    }
    o.sayAge=function(){
        console.log(tempAge);
    }
    return o;
}

var p1=Person("k1",28);
p1.sayName(); // k1
p1.sayAge(); // 28

p1.name="k2";
p1.age=30;
p1.sayName();  // k1
p1.sayAge();   //28

看到如上的輸出就很好理解什麼叫穩妥對象模式了,就是用這種模式建立的對象,沒有其餘辦法可以改變初始化時候傳入的值,這裏是Person("k1",28),這樣的對象就是穩妥對象,實際上這裏使用到就是javascript的閉包了。

相關文章
相關標籤/搜索