Javascript的對象建立方法

建立對象

1.1 經過Object對象建立

var person = new Object();
person.name = "Albert";
person.sayName = function(){
    console.log(this.name);
};

1.2 經過字面量建立

var person = {
    name : "Albert",
    sayName : function(){
        console.log(this.name)
    }
};

Object和字面量建立的問題:

建立不少對象的時候會產生大量重複代碼。javascript

1.3 工廠模式

function createPerson(name){
    var o = new Object();
    o.name = name;
    o.sayName = function(){
        console.log(this.name)
    }
    return o;
}
var person = createPerson("Albert");

工廠模式的問題:

沒法識別對象類型,即沒法經過instanceofconstructor來識別對象類型:java

person instanceof ???;
person.constructor == ???;

1.4 構造函數

function Person(name){
    this.name = name;
    this.sayName = function(){
        console.log(this.name)
    }
}
var person = new Person("Albert");
console.log(person.constructor == Person)//true
console.log(person instanceof Person)//true

構造函數的問題:

每一個方法都要在每一個實例上從新建立一次,尤爲是函數,這樣每一個Person的實例都包含了一個不一樣的sayName的函數實例。node

注意1
構造函數沒有return語句。要建立Person的新實例,必須採用new操做符,new操做符大致上完成了一下4件事情:windows

  • 建立一個新的對象(本例中Person建立的新對象,記爲person);瀏覽器

  • 將構造函數的做用域賦給新對象(this=>person);安全

  • 執行構造函數中的代碼(Person中的this.name=name;this.say.....);閉包

  • 返回新對象app

注意2
構造函數也是函數,若是不經過new操做符調用,則做用環境爲全局(瀏覽器中爲windows,node環境中爲global函數

function Person(name){
    this.name = name;
    this.sayName = function(){
        console.log(this.name)
    }
}

Person("BB");
global.sayName()//BB
console.log(global.name)//BB

1.5 原型模式

function Person(name){}
Person.prototype.name = "Albert";
Person.prototype.sayName = function(){
        console.log(this.name)
    }

var person = new Person();
console.log(Object.getPrototypeOf(person)==Person.prototype);//true

瀏覽器支持:IE9+,這樣全部的Person實例共享name屬性及sayName函數this

注意1

  • 對象的某個屬性是否來自實例,可經過hasOwnProperty()來肯定,若是是在原型中,則返回false

  • 判斷對象是否具有屬性,能夠經過in操做符,例如console.log("name" in person)//true來判斷,不管是在原型仍是實例中,都返回true,經過for-in循環時,實例及原型中均會被枚舉。

注意2
在定義原型時,若是用字面量代替爲prototype屬性定義,則原型的constructor屬性不會指向Person。由於經過字面量定義,徹底重寫了默認的prototype對象。可是此時instanceof仍是可以返回正確的結果。

function Person(name){};
Person.prototype={
    name : "Albert",
    sayName : function(){
        console.log(this.name);
    }
};
var person = new Person();
console.log(person instanceof Person);//true
console.log(person.constructor == Person);//false
console.log(person.constructor == Object);//true

因此能夠再補充定義:

Object.defineProperty(Person.prototype,"constructor",{
    enumerable:false,
    value:Person
})

注意3
在重定義原型前,不能建立對象實例,不然會形成實例的原型指向錯誤

function Person(name){};
var person = new Person();
Person.prototype={
    name : "Albert",
    sayName : function(){
        console.log(this.name);
    }
};
person.sayName(); //error

此例中person的原型被指向了Person的默認原型,固調用sayName函數會發生錯誤。

原型模式的問題:

  • 小問題:爲了省略構造函數傳遞初始化參數,全部的實例在默認狀況下都會去的想通的屬性值

  • 原型屬性被全部實例共享(適合function類型的值),而一般狀況下,引用類型(ArrayObject)屬性值通常不但願對全部實例共享。

1.6 構造函數與原型組合

利用構造函數都是實例屬性和原型的共享特性,分別定義對應的內容,組合共同完成對象建立,並且該模式還支持想構造函數傳遞參數。

function Person(name){
    this.name = name;
    this.friends = ["Bob","Harry"];//引用類型爲實例屬性
};
Person.prototype.sayName = function(){
        console.log(this.name);
};

1.7 動態原型模式

將1.6中的組合封裝在一個構造函數中的模式。具體方法爲:檢查某個應該存在的方法是否有效來決定是否須要初始化原型。

function Person(name){
    this.name = name;
    this.friends = ["Bob","Harry"];//引用類型爲實例屬性
    //****ProtoType****
    if(typeof this.sayName != "function"){
        Person.prototype.sayName = function(){
            console.log(this.name);
        };
    }
};

1.8 寄生構造模式

構造函數在不反回值的狀況下,默認會返回新對象實例。
而經過在函數末尾添加return語句,能夠重寫new後調用函數時的返回值。

function Person(name){
    var o = new Object();
    o.name = name;
    o.sayName = function(){
        console.log(this.name);
    };
    return o;
};
var person = new Person("Albert");
console.log(person instanceof Person);//false

該函數除了使用new操做符和把包裝函數取名叫「構造函數」之外,和工廠模式實際上是如出一轍的。
該模式屬於比較特殊的構造模式,可用於不容許修改原對象的狀況。

function SpecialArray(){
    var values = new Array();
    values.push.apply(values,arguments);
    values.toPipedString = function(){
        return this.join("|");
    };
    return values
}

1.9 穩妥(durable)構造函數模式

該模式構造出來的對象沒有公共屬性,不適用this對象,不適用new操做符,適用於在一些安全環境中,可防止數據被其它應用(如Mashup)改動(利用閉包特性),相似於寄生構造函數模式,單不適用thisnew

function Person(name){
    var o = new Object();
    //****定義私有變量和函數****
    var _name = name;
    o.sayName = function(){
        console.log(_name);
    };    
    return o;
};
var person = Person("Albert");

這種模式中,除了sayName()方法之外,沒有其它辦法訪問_name的值。

相關文章
相關標籤/搜索