JavaScript 建立對象的幾種模式

在JavaScript中雖然說能夠用Object的構造函數或者字面量建立單個對象,可是用這些方式來建立多個對象時就有一個明顯的缺點,產生了大量的重複代碼。爲解決這些問題,許多模式就應運而生。c#

1. 工廠模式函數

因爲在ECMAScript中沒法建立類,因此就發明了一種函數,用來封裝以特定接口建立對象的細節。this

可是以這種方式建立的對象沒有解決對象識別問題,即怎樣知道一個對象的類型。spa

function createPerson(name,age,job)
{
var o = new Object();
o.name=name;
o.age=age;
o.job=job;
o.sayHellow=function()
{alert("Hellow"+o.name)};
return o;
}

var person1 = createPerson("Jack",34,"Doctor");

2. 構造函數模式prototype

這種方式建立的對象都是屬於同一類型的,下面的例子中,全部的對象都是Person類型。指針

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

var person1 = new Person("Jack",24,"Doctor");
var person2 = new Person("Simon",34,"Teacher");

alert(person1 instanceof Object); // true
alert(person1 instanceof Person); // true
alert(person2 instanceof Object); // true
alert(person2 instanceof Person); // true

可是這個模式也有缺點,那就是每一個方法都要在每一個對象的實例中從新建立一遍。就如上面的例子,person1 和person2的sayName方法其實不是Function的同一個實例,是位於兩個不一樣位置的函數指針。code

因此能夠改進下:對象

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

var person1 = new Person("Jack",24,"Doctor");
var person2 = new Person("Simon",34,"Teacher");

alert(person1 instanceof Object); // true
alert(person1 instanceof Person); // true
alert(person2 instanceof Object); // true
alert(person2 instanceof Person); // true

3. 原型模式blog

想弄明白這個模式,必需要想理解prototype.接口

這個模式有個很大的問題,就是全部對象的屬性和方法都是共享的,可是咱們可能僅僅想讓Person類共享這個sayName 方法,你們應該都想到了,能夠用構造函數模式+原型模式來解決這個問題。

function Person(){}
Person.prototype.name="Jack";
Person.prototype.age=33;
Person.prototype.job="IT";
Person.prototype.sayName = function(){alert("Hellow"+ this.name);};

// 字面量寫法
function Person(){}
Person.prototype =
{
name: "Jack",
age: 33,
job: "IT",
sayName=function(){alert("Hellow "+this.name);}
}

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

用構造函數定義實例屬性,存放不共享的數據,用原型模式定義共享的方法和屬性,這樣能夠盡最大可能減小內存開銷。

有點相似於c#類的實例成員和靜態成員,但只是像。

這中模式是目前用的最普遍,承認太最高的。

function Person(name,age,job)
{
  this.name=name;
  this.age=age;      
  this.job=job;  
  this.friends=["Toby","Linford"];  
}
Person.prototype=
{
 constructor: Person,
 sayName: function(){alert(this.name);}
}

var person1 = new Person("Jack",33,"SDE");
var person2 = new Person("Lucy",25,"Teacher");

person1.friends.push("Jim");

alert(person1.friends); // Toby,Linford,Jim
alert(person2.friends); // Toby,Linford

alert(person1.friends==person2.friends); // false
alert(person1.sayName==person2.sayName); //true

5.動態原型模式

function Person(name,age,job)
{
  this.name=name;
  this.age=age;      
  this.job=job;  
  if(typeof sayName != "function")
  {
    Person.prototype.sayName=function()
    {
       alert(this.name);
     }
   };
}

6. 寄生構造函數模式

其基本思想就是一個函數,該函數的做用僅僅就是封裝建立對象的代碼,而後再返回新建立的對象。

function createPerson(name,age,job)
{
var o = new Object();
o.name=name;
o.age=age;
o.job=job;
o.sayHellow=function()
{alert("Hellow"+o.name)};
return o;
}

var person1 = createPerson("Jack",34,"Doctor");

從上面代碼看來和工廠模式是同樣的。可是這個模式能夠在特殊的狀況爲對象(特別是內置的對象,如Array)添加構造函數。

7.穩妥構造函數模式

和寄生構造函數模式相似,但有兩個不一樣點,一是建立對象的實例方法不引用this,二是不使用new 調用構造函數。

function Person(name, age, job)
{
  //定義要返回的對象
  var o = new Object();
  //定義私有變量和方法

  //添加方法
  o.sayName=function(){alert(name);};
  
  return o;
}

在上面的例子中,只有經過sayName才能夠訪問name.

相關文章
相關標籤/搜索