charset=UTF-8" pageEncoding="UTF-8"%>
<html>
<head>
<script type="text/javascript">
/*
更簡單的原型模式以及由此帶來的問題:
在本人博客“ js面向對象2--js中工廠模式的演化(重要,詳細)”中的原型模式
是最基本也最正確的原型模式的用法,但是每次都用Person.prototype.屬性名稱
來個原型模式添加方法和屬性未免太過繁瑣。
爲了減少不必要的輸入,也爲了從視覺上更好的封裝原型的功能,更常見的做法是用一個
包含所有屬性和方法的對象資源面來重寫這個原型對象,如下:
*/
//正常的原型寫法:
function Person(){}
Person.prototype.name = "chenchaoyang";
Person.prototype.age = 12;
Person.prototype.job = "Software enginner";
Person.prototype.sayName = function (){
alert(this.name);
}
var person1 = new Person();
//簡單的原型寫法
function Person(){}
Person.prototype = {
name:"chenchaoyang",
age:"12",
job:"Software enginner",
sayName:function(){
console.log(this.name);
}
}
var person2 = new Person();
function onloadFunction()
{
console.log(person1.constructor); //Person()
console.log(person2.constructor); //Object()
}
/*
在上面代碼,我們將Person.prototype 設置爲等於一個以對象字面量形式創建的
新對象,最終結果相同,但有一個例外,constructor屬性不再指向Person了。
原因:
每創建一個函數,就會同事創建它的prototype對象,這個對象也會自動獲得constructor
屬性。而我們在這裏使用的語法,本質上完全重寫了默認的prototype對象,因此constructor
屬性也就變成了新對象的constructor屬性(指向Object構造函數),不再指向Person函數,
此時儘管instanceof操作符還能返回正確的結果,但通過constructor已經無法確定對象
的類型了。
如果在編程過程中,一個對象的constructor值很重要,可以像下面這樣的方法去改寫:
*/
function Person(){}
Person.prototype = {
constructor : Person, //人爲的制定原型對象的構造函數指向
name : "chenchaoyang",
age :13,
sayName : function(){
alert(this.name);
}
}
/*
注意:以上面的方式重設constructor屬性會導致它[[Enumerable]]特性被設置爲true。默認
情況下,原聲constructor屬性是不可枚舉的,因此如果你使用兼容EcmAScript5的JavaScript
引擎,可以試一試Object.defineProperty().如下:
function Person(){}
Person.prototype = {
name : "chenchaoyang",
age : 12,
job : "Soft Enginner",
sayName : function(){
console.log(this.name);
}
//重寫原型對象的構造函數,只適用於ECMAScript5兼容的瀏覽器
Object.defineProperty(Person.prototype,"constructor",{
enumerable:false,
value:Person
})
}
此種模式堪稱完美。。。。。。。。。Over
*/
</script>
</head>
<body οnlοad="onloadFunction();">
</body>
</html>