Js基礎之創建對象的方法

一、單個對象

創建單個對象時,可以採用對象字面量{}或者new+object構造函數來創建;

var person1 = new Object(); //person1是由new+object構造函數創建
person1.name = 'ermiao';
person1.age = 18;    

var person2 = {       //person2是由對象字面量{}創建
    name:'Ermiao',
    age: 18
}

二、多個對象

創建多個對象時,相似的對象若每個都要單獨創建,會產生重複的代碼,因此採用以下方法:

1.工廠模式

工廠模式是抽象出創建對象過程中的重複步驟,並用一個函數封裝起來的模式

function createPerson(name,age){
    var p = new Object();
    p.name = name;
    p.age = age;
    p.say = function(){
        alert(this.name);
    }
    return p
}

var person1 = createPerson('ermiao',18);

優點:解決了創建多個相似對象的問題

缺點:無法判斷對象的類型

2.構造函數模式

除了採用自帶的Object構造函數,還可以創建自定義構造函數

function Person(name,age){  //創建自定義的構造函數
    this.name = name;
    this.age = age;
    this.say = function(){
        alert(this.name);
    }
}
var person1 = new Person('ermiao',18);  //person1由new+自定義構造函數創建
var person2 = new Person('Ermiao',18);  //person2由new+自定義構造函數創建

對比工廠模式,(自定義)構造函數模式不用顯示創建對象、不用返回對象、把對象的屬性值都賦給了this。

在JavaScript中,構造函數和普通函數的唯一區別是調用方式不同。按照慣例,構造函數名的首字母應大寫。

任何函數只要能夠被new調用就叫構造函數不被new調用就是普通函數。如上例的Person函數,若不被new調用,就是普通函數,this指向全局變量window。

在用new+自定義構造函數生成實例時,經歷了以下步驟:

  • 創建一個新對象
  • 將構造函數的作用域賦給新對象
  • 執行構造函數的代碼(添加屬性)
  • 返回新對象

優點:通過自定義構造函數創建的實例可以標識爲特殊的類型(能夠判斷類型)。例如上例中person1和person2都是Person的實例,也都是Object的實例(繼承)

缺點:被同一構造函數創建的多個對象之間沒有聯繫。如上例person1和person2的say()函數是兩個不同的函數,完成相同任務的函數不必要創建兩遍並在執行前綁定在特定對象上。

3.原型模式

爲了增加同一構造函數創建的多個對象之間的聯繫,每個函數都有一個prototype(原型)屬性指向原型對象。原型對象包含特定類型的所有實例共享的屬性和方法(如上例的say方法只在原型對象定義一次,並由person1和person2共享)

關於原型對象的內容請看:一文看懂原型鏈

var Person = function(){}; //原型模式不定義構造函數,只定義原型對象中的共享屬性 

Person.prototype = {
    constructor: Person, //採用對象字面量給prototype賦值,一定要將constructor改成Person
    name:'ermiao',
    age:18,
    say:function(){
        alert(this.name);
    }
};

優點:能夠使實例之間共享屬性和方法

缺點:若所有屬性都是共享不太方便,並且若共享屬性是引用類型的,則能夠同時更改可能導致錯誤

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

最常用的方法是組合使用構造函數和原型模式,由構造函數創建獨有屬性,由原型對象定義共享屬性。

var Person = function(name,age){ //構造函數模式
    this.name = name;
    this.age = age;
}; 

//採用對象字面量給prototype賦值,一定要將constructor改成Person   
Person.prototype = {  //原型模式
    constructor: Person,
    say:function(){
        alert(this.name);
    }
};

優點:既能定義實例屬性又能定義實例共享屬性

缺點:要定義兩次屬性(構造函數,原型對象)

5.動態原型模式

該模式是在構造函數中初始化原型對象屬性(必要情況下),只在初次調用構造函數時才執行。

var Person = function(name,age){
    this.name = name;
    this,age = age;
    if(typeOf this.say != 'function'){    //此處也可用instanceOf判斷
        Person.prototype.say = function(){
            alert(this.name);
        };
    }
}

var person1 = new Person('ermiao',18);

person1.say(); //輸出'ermiao'

注意:使用動態原型模式不能用對象字面量來定義原型屬性,會改變原型的constructor屬性(指向object)

優點:保留構造函數和原型模式的優點,又封裝在一起

缺點:定義原型屬性時不能用對象字面量

6.寄生構造函數模式

該模式除了使用new操作符調用函數,其他和工廠模式是一樣的(效果一樣,寫法一樣)

//工廠模式定義函數
var Person = function(name,age){  //區別1:函數名按構造函數規則寫
    var p = new Object();
    p.name = name;
    p.age = age;
    p.say = function(
        alert(this.name);
    )
    return p
};
var person1 = new Person('ermiao',18);  //區別2:使用new操作符調用函數

注意:同工廠模式一樣,返回的對象和構造函數、構造函數的原型沒有任何關係。

當使用new操作符調用構造函數時,若構造函數中沒有返回值(return),則默認返回創建的實例;若構造函數中有返回值,則以返回值優先

優點:只是看起來比工廠模式更像創建對象(但實質和工廠模式一樣)

缺點:返回的對象和構造函數沒關係,不能判斷對象的特有類型,不建議使用該模式

7.穩妥構造函數模式

穩妥對象是指沒有公共屬性也不使用this的對象。

該模式不使用this和new,在函數中,只爲返回對象綁定方法,不綁定數據,傳入或內部定義的參數作爲私有變量只能由返回對象的方法調用。(相當於c++中類的私有變量)

function Person(name,age){
    var p = new Object(); //創建返回對象
    //定義私有變量
    var para_name = name;
    var para_age = age;
    //定義返回對象的方法
    p.sayName = function(){
        alert(para_name);
    };
    p.sayAge = function(){
        alert(para_age);
    };
}

var person1 = Person('ermiao',18);

person1.sayName(); //輸出'ermiao'
person1.sayAge(); //輸出18
person1.name; //輸出undefined

優點:比較安全,不使用this和new,將所有數據成員私有化

缺點:不可以添加成員

注意:同工廠模式一樣,返回的對象和構造函數、構造函數的原型沒有任何關係。

 

 

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章