Javascript建立對象的幾種方式?

javascript 中常見的建立對象的幾種方式:

 1. 使用Object構造函數建立;

使用Object構造函數來建立一個對象,下面代碼建立了一個person對象,並用兩種方式打印出了Name的屬性值。

var person = new Object();
person.name="kevin";
person.age=31;
alert(person.name);
alert(person["name"])

2. 使用對象字面量建立一個對象;

var person ={
      name:"Kevin",
      age:31,
      5:"Test"
};
alert(person.name);
alert(person["5"]);

3. 使用工廠模式建立對象;

返回帶有屬性和方法的person對象。

function createPerson(name, age,job){
    var o = new Object();
    o.name=name;
    o.age=31;
    o.sayName=function()
    {
        alert(this.name);
    };
    return o;
}
createPerson("kevin",31,"se").sayName();

用函數來封裝以特定接口建立對象的細節,解決了建立多個類似對象的問題可是沒有解決對象識別的問題(怎麼知道一個對象的類型)。javascript

4. 使用自定義構造函數模式建立對象;

這裏注意命名規範,做爲構造函數的函數首字母要大寫,以區別其它函數。這種方式有個缺陷是sayName這個方法,它的每一個實例都是指向不一樣的函數實例,而不是同一個。構造函數模式,構造函數添加屬性和方法,使用的時候new一個自定義的對象

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

var person = new Person("kevin",31,"SE");
person.sayName();

new一個構造函數的內部操做步驟:java

1)、建立一個新對象;編程

2)、將構造函數的做用域賦給新對象(所以this就指向了這個新對象);函數

3)、執行構造函數中的代碼;this

4)、返回新對象。spa

使用構造函數建立的實例,都會有一個constructor屬性,指向構造函數。prototype

建立自定義的構造函數意味着未來能夠將它的實例標識爲一種特定的類型。這正是賽過工廠模式的地方。指針

與普通函數的區別在於new調用,不用new來調用,與普通函數無差。code

不使用new調用的時候,就至關於window調用了構造函數,屬性和方法都被添加到了window對象上去。對象

也能夠這樣使用:(call就是爲了改變上下文環境而生)

var o = new Object();
Person.call(o,"Dadaoshenyi",25,"Enginner");
o.sayName();//"Dadaoshenyi"

構造函數建立對象的問題:每一個方法都要在實例上重寫一遍。因爲函數也是對象,所以每次定義一個函數,也就實例化了一個對象。

5. 使用原型模式建立對象;

解決了方法4中提到的缺陷,使不一樣的對象的函數(如sayFriends)指向了同一個函數。

但它自己也有缺陷,就是實例共享了引用類型friends,從下面的代碼執行結果能夠看到,兩個實例的friends的值是同樣的,這可能不是咱們所指望的。原型模式,定義構造函數,構造函數原型上添加屬性和方法。 

function Person(){

}

Person.prototype = {
    constructor : Person,
    name:"kevin",
    age:31,
    job:"SE",
    friends:["Jams","Martin"],
    sayFriends:function()
    {
        alert(this.friends);
    }
};
var person1 = new Person();
person1.friends.push("Joe");
person1.sayFriends();//Jams,Martin,Joe
var person2 = new Person(); 
person2.sayFriends();//James,Martin,Joe

構造函數的原型||對象實例的內部指針([[Prototype(__proto__)]]指向Person.prototype)。

實例對象的內部指針指向構造函數的原型。

原型模式的優勢:自定義的構造函數,可讓全部的對象實例共享原型對象所包含的屬性和方法。原生的引用類型也是採用這種模式。

問題在於:一、省略了構造函數傳遞參數的步驟。二、全部實例共享方法和屬性,這樣,實例修改原來的屬性或者方法,將會在全部的實例上表現出來。被捆綁到了一塊兒。只是一個引用,不是一個副本。

6. 組合使用原型模式和構造函數建立對象;

解決了方法5中提到的缺陷,並且這也是使用最普遍、認同度最高的建立對象的方法。組合使用構造函數模式和原型模式,最經常使用的一種模式。 

function Person(name,age,job)
{
    this.name=name;
    this.age=age;
    this.job=job;
this.friends=["Jams","Martin"]; } Person.prototype.sayFriends=function() { alert(this.friends); };
  // Person.prototype = {
     // constructor: Person,
     // sayFriends: function() {
        // alert(this.friends);
     // }
  // };
var person1 = new Person("kevin",31,"SE");
var person2 = new Person("Tom",30,"SE");
person1.friends.push("Joe");
person1.sayFriends();//Jams,Martin,Joe
person2.sayFriends();//Jams,Martin

優勢:使用構造函數來建立實例屬性,且能夠修改設定的值。使用原型建立共享方法和共享的屬性。最大限度的節省了內存。

7. 動態原型模式;

這個模式的好處在於看起來更像傳統的面向對象編程,具備更好的封裝性,由於在構造函數裏完成了對原型建立。這也是一個推薦的建立對象的方法。動態原型模式,將上面的對象原型方法||屬性的建立方法哦了構造函數裏面完成。具備更好的封裝性。結果是同樣的。 

function Person(name,age,job)
{
    //屬性
    this.name=name;
    this.age=age;
    this.job=job;
    this.friends=["Jams","Martin"];
    //方法
    if(typeof this.sayName != "function")
    {
        Person.prototype.sayName=function()
        {
            alert(this.name);
        };
        
        Person.prototype.sayFriends=function()
        {
            alert(this.friends);
        };
    }
}

var person = new Person("kevin",31,"SE");
person.sayName();
person.sayFriends();

另外還有兩個建立對象的方法,寄生構造函數模式和穩妥構造函數模式。因爲這兩個函數不是特別經常使用,這裏就不給出具體代碼了。

寫了這麼多建立對象的方法,其實真正推薦用的也就是方法6和方法7。固然在真正開發中要根據實際須要進行選擇,也許建立的對象根本不須要方法,也就不必必定要選擇它們了。

相關文章
相關標籤/搜索