JS中的原型對象(二)

本篇介紹重寫原型對象的原理及對實例的影響;原型對象的問題

重寫原型對象

請看下例:

function Person(){
}
var Edward = new Person();
Person.prototype.name = "Sheldon";
Person.Prototype.age = 29;
Person.prototype.job = "Physical Scientist";
Person.prototype.sayName = function(){
    alert(this.name);
};

Edward.sayName ();            //"Sheldon"(沒有問題)

在上例中,每添加一個屬性或方法就要輸入一遍 Person.prototype ,爲了簡化,更常見的做法是用一個新的對象字面量來重寫原型,如:

function Person(){

}
Person.prototype = {
    name : "Sheldon",
    age : 29,
    job : "Physical Scientist",
    sayName : function(){
        alert(this.name);
    }
};

在上例中, Person.prototype 實質上被設置成了一個新對象,這個新對象自動獲得的新的 constructor 屬性也不再指向 Person 函數。儘管 instanceof 操作符還能返回正確的結果,但通過 constructor 已無法正確確定對象類型了。

var Amy = new Person();

alert(Amy instanceof Object);         //true
alert(Amy instanceof Person);         //true
alert(Amy.constructor == Person);     //false
alert(Amy.constructor == Object);     //true

如果 constructor 值很重要,可以將它特意設置回適當的值,但這會導致它的 Enumerable 特性被設置爲 true

function Person(){

}
Person.prototype = {
    constructor : Person,
    name : "Sheldon",
    age : 29,
    job : "Physical Scientist",
    sayName : function(){
        alert(this.name);
    }
};

原型的動態性

原型具有動態性,即當原型有修改時,無論實例在原型修改前創建還是修改後創建,原型修改的內容都可以在實例體現。

function Person(){
}
var Edward = new Person();

Person.prototype.sayHello = function(){
    alert("Hello");
};

Edward.sayName ();            //"Hello"(沒有問題)

除了自定義類型,所有的原生引用類型(Object、Array、String,等等 )都採用這種模式。通過原生對象的原型,不僅可以獲得所有默認方法的引用,也可以定義新方法。

重寫原型之後,現有原型與之前已經存在的原型實例之間沒有聯繫,它們引用的仍然是最初的原型。

function Person(){
}
var Edward = new Person();

Person.prototype = {
    sayHi : function(){
        alert("Hi");
    }
};
Edward.sayHi();          //Error

原型對象的問題

因爲原型中的屬性都被所有實例共享,因此,所有實例在默認情況下都將取得相同的屬性值。如果原型中有包含引用值的屬性,當修改某一實例的該屬性時,這次的修改將同步至其他實例,這將導致問題的產生。如:

function Person(){

}
Person.prototype = {
    constructor : Person,
    name : "Sheldon",
    age : 29,
    job : "Physical Scientist",
    friends : ["Amy","Edward","Penny"]
    sayName : function(){
        alert(this.name);
    }
};

var person1= new Person();
var person2 = new Person();

person1.friends.push("John");

alert(person1.friends);       //"Amy,Edward,Penny,John"
alert(person2.friends);       //"Amy,Edward,Penny,John"
alert(person1.friends == person2.friends)      //true

這正是很少有人單獨使用原型模式的原因。

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