也許你還沒有理解構(gòu)造函數(shù)和原型對(duì)象的時(shí)候已經(jīng)在javascript的路上走了很久,但直到你很好的掌握它們之前你不會(huì)真正欣賞這門語言,由於Javascript缺乏類,它使用構(gòu)造函數(shù)和原型對(duì)象來給對(duì)象帶來與類相似的功能,但是,這些相似的功能並不一定表現(xiàn)的跟類完全一致,在本章中,你會(huì)詳細(xì)看到j(luò)avascript如何使用構(gòu)造函數(shù)和原型對(duì)象來創(chuàng)建對(duì)象。
4.1構(gòu)造函數(shù)
構(gòu)造函數(shù)就是你用new創(chuàng)建對(duì)象時(shí)調(diào)用的函數(shù)。到目前爲(wèi)止,你已經(jīng)見過好幾次內(nèi)建javascript構(gòu)造函數(shù)了,例如,Object,Array和Function。使用構(gòu)造函數(shù)的好處在於用同一個(gè)構(gòu)造函數(shù)創(chuàng)建的對(duì)象都具有同樣的屬性和方法。如果想創(chuàng)建多個(gè)相同的對(duì)象,你可以創(chuàng)建自己的構(gòu)造函數(shù)以及引用類型
構(gòu)造函數(shù)也是函數(shù)。你會(huì)用同樣的方法定義它,唯一的區(qū)別是構(gòu)造函數(shù)名字應(yīng)該首字母大寫,以此區(qū)分其他函數(shù)。下列定義了一個(gè)空的Person函數(shù)。
function Person(){
//intertionally empty
}
這個(gè)函數(shù)就是構(gòu)造函數(shù)。構(gòu)造函數(shù)和其他函數(shù)並沒有絕對(duì)的與發(fā)上的區(qū)別。唯一的線索就時(shí)首字母大寫。
定義好構(gòu)造函數(shù)後,你就可以用它來創(chuàng)建對(duì)象,例如下面的Person對(duì)象
var person1=new Person();
var person2=new Person();
如果沒有需要傳遞給構(gòu)造函數(shù)的參數(shù),你甚至可以忽略小括號(hào)。
var person1=new Person;
var person2=new Person;
即使Person構(gòu)造函數(shù)並沒有顯式返回任何東西,person1和person2都會(huì)被認(rèn)爲(wèi)時(shí)一個(gè)新的Person類型的實(shí)例。new操作符會(huì)自動(dòng)創(chuàng)建給定類型的對(duì)象並返回給它們。這也意味著,你可以用instanceof操作符獲取對(duì)象的類型。如下所示。
console.log(person1 instanceof Person);
console.log(person1 instanceof Person);
由於person1和person2被Person構(gòu)造函數(shù)創(chuàng)建,用instanceof檢查它們是否爲(wèi)Person類型時(shí)返回true。
你也可以用構(gòu)造函數(shù)屬性來檢查一個(gè)對(duì)象的類型。每個(gè)對(duì)象在創(chuàng)建時(shí)都自動(dòng)擁有一個(gè)構(gòu)造函數(shù)屬性,其中包含一個(gè)指向其構(gòu)造函數(shù)的引用。那些通過對(duì)象字面形式或Object構(gòu)造函數(shù)創(chuàng)建出來的泛用對(duì)象,其構(gòu)造函數(shù)指向Object;那些通過自定義構(gòu)造函數(shù)創(chuàng)建出來的對(duì)象,其構(gòu)造函數(shù)屬性指向創(chuàng)建它的構(gòu)造函數(shù)。如下例person1和person2的constructor屬性Person。
console.log(person1.constructor ===Person);
console.log(person2.constructo===Person);
console.log函數(shù)對(duì)兩個(gè)對(duì)象都輸出true。因爲(wèi)它們都是用Person構(gòu)造函數(shù)創(chuàng)建的。
雖然對(duì)象實(shí)例機(jī)器構(gòu)造函數(shù)之間存在這樣的關(guān)係。但是還是建議你使用instanceof來檢查對(duì)象類型。這是因爲(wèi)構(gòu)造函數(shù)屬性可以被覆蓋,並不一定完全準(zhǔn)確。
當(dāng)然,一個(gè)空的構(gòu)造函數(shù)並不是十分游泳的。使用構(gòu)造函數(shù)的目的時(shí)爲(wèi)了輕鬆創(chuàng)建許多擁有相同屬性和方法的對(duì)象。爲(wèi)此,你只需要在構(gòu)造函數(shù)內(nèi)簡單的給this天界你想要的任何屬性即可。如下例。
function Person(name){
this.name =name;
this.sayName=function(){
console.log(this.name);
}}
該板根的Person構(gòu)造函數(shù)接受一個(gè)命名參數(shù)name並將賦給this對(duì)象的name屬性。同時(shí),構(gòu)造函數(shù)還給對(duì)象添加一個(gè)sayName()方法。當(dāng)你調(diào)用構(gòu)造函數(shù)時(shí),new會(huì)自動(dòng)創(chuàng)建this對(duì)象。且其類型就是構(gòu)造函數(shù)的類型,(在本例中爲(wèi)Person)構(gòu)造函數(shù)本身不不需要返回一個(gè)值,new操作符會(huì)幫你返回。
現(xiàn)在你而可以用Person構(gòu)造函數(shù)來創(chuàng)建具有初始name屬性的對(duì)象了。
var person1=new Person("Nicholas");
var person2=new Person("Greg");
console.log(person1.name);
console.log(person2.name);
person1.sayName();
person2.sayName();
每個(gè)對(duì)象都有自己的name屬性,所以sayName()方法可以根據(jù)不同對(duì)象返回不同的值。
注意:你也可以在構(gòu)造函數(shù)中顯式調(diào)用return,如果返回的值是一個(gè)對(duì)象,它會(huì)代替新創(chuàng)建的對(duì)象實(shí)例返回。如果返回的值時(shí)一個(gè)原始類型那個(gè),他會(huì)被忽略,新創(chuàng)建的對(duì)象實(shí)例會(huì)被返回。
構(gòu)造函數(shù)允許你用一致的方式初始化一個(gè)類型的實(shí)例。在使用對(duì)象錢設(shè)置好所有的屬性。如下例。你也可以在構(gòu)造函數(shù)中用Ocject.defineProperty()方法 來幫助我們初始話。
function Person(name){
Object.defineProperty(this,"name"{
get:function(){
return name;},
set:function(newName){
name =newName;
},
enumerable:true,
configurable:true
});
this.sayName=function(){
console.log(this.name)}
}
在這個(gè)版本的Person構(gòu)造函數(shù)中,name屬性是一個(gè)訪問者屬性,利用name參數(shù)來保存實(shí)際的值,之所以能這樣做,是因爲(wèi)命名參數(shù)就相當(dāng)於一個(gè)本地變量。
始終確保用new調(diào)用構(gòu)造函數(shù);否則,你就是在冒改全局對(duì)象的風(fēng)險(xiǎn),而不是創(chuàng)建一個(gè)新的對(duì)象,考慮如下代碼中發(fā)生了什麼。
var ?person1= Person("Nicholas");
console.log(person1.instanceof Person);
console.log(name);
console.log(typeof person1);
當(dāng)Person不是被new調(diào)用時(shí),構(gòu)造函數(shù)中的this對(duì)象等於全局this對(duì)象,由於person構(gòu)造函數(shù)依靠new提供返回值,person1變量爲(wèi)undefined。沒有new,Person只不過時(shí)一個(gè)沒有返回語句的函數(shù)。對(duì)this.name的賦值實(shí)際上時(shí)創(chuàng)建來一個(gè)全局變量name來保存?zhèn)鬟f給Person的參數(shù)。第6章介紹的幾個(gè)對(duì)象模式中將包括對(duì)這一問題的解決辦法
注意;在嚴(yán)格模式下,當(dāng)你不通過new調(diào)用Person構(gòu)造函數(shù)時(shí)會(huì)出現(xiàn)錯(cuò)誤。這是因爲(wèi)嚴(yán)格模式並沒有爲(wèi)全局對(duì)象設(shè)置this。this保持爲(wèi)undefined,而當(dāng)你是試圖爲(wèi)undefined添加屬性時(shí)都會(huì)出錯(cuò)
構(gòu)造函數(shù)允許你給對(duì)象配置同樣的屬性,但是鉤爪函數(shù)並沒有消除冗餘臺(tái)嗎,在之前的例子中,每一個(gè)對(duì)象都有自己的sayName()方法。這意味著如果你有100個(gè)對(duì)象實(shí)例,你就有100個(gè)函數(shù)做相同的使其,只是使用的數(shù)據(jù)不同。如果所有的對(duì)象實(shí)例共享一個(gè)方法更加有效,該方法可以使用this.name訪問正確的數(shù)據(jù),這就是需要用到原型對(duì)象啦。
4.2 原型對(duì)象
可以把原型對(duì)象看成是對(duì)象的基類。幾乎所有的函數(shù)(除了一些內(nèi)建函數(shù))都有一個(gè)名爲(wèi)property的屬性,改屬性時(shí)一個(gè)原型對(duì)象用來創(chuàng)建新的對(duì)象實(shí)例。所有創(chuàng)建的對(duì)象實(shí)例共享該原型對(duì)象,且這些對(duì)象實(shí)例可以訪問原型對(duì)象的屬性。例如,hasOwnProperty()方法被定義在泛用對(duì)象Object的原型對(duì)象中,但卻可以被任何對(duì)象當(dāng)作自己的屬性訪問,如下例
var book={
title:"The Principles of Object-Oriented JavaScript"
};
console.log("title" in book);
console.log(book.hasOwnProperty("title"));
console.log("hasOwnProperty" in book);
console.log(book.hasOwnProperty("hasOwnProperty"));
console.log(Object.prototype.hasOwnProperty("hasOwnProperty"));
即時(shí)book中並沒有hasOwnProperty()這個(gè)方法的定義,仍然可以通過book.hasOwnProperty()訪問該方法。這是因爲(wèi)該方法的定義存在與Object.prototype中。in操作符對(duì)原型屬性和自有屬性都返回true。
鑑別一個(gè)原型對(duì)象 ?你可以用這樣一個(gè)函數(shù)去鑑別一個(gè)屬性是否是原型對(duì)象。
function hasPrototypeProperty(object,name){
return name in object &&! object.hasOwnProperty(name);
}
console.log(hasPrototypeProperty(book,"title"));
console.log(hasPrototypeProperty(book,"hasOwnProperty"));
4.2.1 [[Prototype]]屬性
一個(gè)對(duì)象實(shí)例通過內(nèi)部屬性[[Prototype]]跟蹤其原型對(duì)象。該屬性時(shí)一個(gè)指向該實(shí)例使用的原型對(duì)象的指針。當(dāng)你使用new創(chuàng)建一個(gè)新的對(duì)象的時(shí)候,構(gòu)造函數(shù)的原型對(duì)象會(huì)給該對(duì)象的[[Prototype]]屬性。[[Prototype]]屬性是讓多個(gè)對(duì)象實(shí)例引用同一個(gè)原型對(duì)象來減少重複代碼的。
你可以調(diào)用對(duì)象的Object.getPrototypeOf()方法讀取[[Prototype]]屬性的值。下例代碼檢查一個(gè)泛用空對(duì)象的[[Prototype]]屬性。
var object={};
var prototype=Object.getPrototypeOf(object);
console.log(prototype=== Object.prototype);// true
如上例,任何一個(gè)泛用對(duì)象,其[[Prototype]]屬性始終指向Object.prototype。
注意:大部分JavaScript引擎在所有對(duì)象上都支持一個(gè)名爲(wèi)_proto_的屬性,該屬性使你可以世界讀寫[[Prototype]]屬性。firefox,safari,chrome和node.js都支持該屬性,且EcmaScript6正在考慮將其加入到標(biāo)準(zhǔn)中。
你也可以用isPrototype()方法檢查某個(gè)對(duì)象是否時(shí)另一個(gè)對(duì)象的原型對(duì)象。該方法被包含在所有對(duì)象中。
var object={};
console.log(Object.prototype.isPrototypeOf(object)); //true
因爲(wèi)object時(shí)一個(gè)泛用對(duì)象,它的原型時(shí)Object.prototype。意味著本例中的isPrototypeOf()方法返回true。
當(dāng)讀取一個(gè)對(duì)象的屬性時(shí),javascript引擎首先在該對(duì)象的自有屬性中查找屬性的名字,如果找到則返回,如果自有屬性中不包含該名字,則javascript會(huì)搜索[[Prototype]]中的對(duì)象。如果找打則返回。如果找不到,則返回undefined。
下列先創(chuàng)建一個(gè)沒有自有屬性的對(duì)象。
var object={};
console.log(object.toString());
object.toString=function(){
return "[object Custom]";
};
console.log(object.toString());
delete object.toString;
console.log(object.toString());
delete object.toString;
console.log(object.toString());
本例最初的toString()方法來自於原型對(duì)象,默認(rèn)返回"[object Object]"如果你定義一個(gè)名叫toString的自有屬性,那麼每次調(diào)用該對(duì)象的toString()方法都會(huì)調(diào)用該自有屬性。自有屬性會(huì)覆蓋原型屬性。僅當(dāng)自有屬性被刪除時(shí),原型屬性纔會(huì)再以此被使用。delete操作符僅對(duì)自有屬性起作用,你無法闡述一個(gè)對(duì)象的原型屬性。還有就是無法給一個(gè)對(duì)的原型屬性賦值。
4.2.2 在構(gòu)造函數(shù)總使用原型對(duì)象
原型對(duì)象的共享機(jī)制使得它們成爲(wèi)一次性爲(wèi)所有對(duì)象定義方法的理想手段。因爲(wèi)一個(gè)方法對(duì)所有的對(duì)象實(shí)例做相同的使其,美麗有每個(gè)實(shí)例都要有一份自己的方法。
將方法放在原型對(duì)象中並用this訪問當(dāng)前實(shí)例時(shí)更有效的做法。下例展現(xiàn)了新Person構(gòu)造函數(shù)。
function Person(name){
this.name=name;
};
Person.prototype.sayName=function(){
console.log(this.name);
};
var person1=new Person("Nicholas");
var person2=new Person("Greg");
console.log(person1.name);
console.log(person2.name);
person1.sayName();
person2.sayName();
在這個(gè)版本的Person構(gòu)造函數(shù)中,sayName()被定義在原型對(duì)象上而不是構(gòu)造函數(shù)中。創(chuàng)建出的對(duì)象和本章之前的例子中創(chuàng)建的對(duì)象別無二致,只不過sayName()現(xiàn)在是一個(gè)原型屬性而不是自有屬性。在person1和person2調(diào)用sayName()時(shí),相對(duì)的this的值被分別賦在person1或person2.
也可以在原型對(duì)象上存儲(chǔ)其他類型的數(shù)據(jù),但在存儲(chǔ)引用值時(shí)需要注意。因爲(wèi)這些引用值會(huì)被多個(gè)實(shí)例共享,可能搭建不希望一個(gè)實(shí)例能夠改變另一個(gè)實(shí)例的值。下例顯示當(dāng)你不注意你的引用值的實(shí)際指向那裏時(shí)會(huì)發(fā)生的情況。
function Person(name){
this.name=name;
}
Person.prototype.sayName=function(){
console.log(this.name);
};
Person.prototype.favorites=[];
var person1=new Person("Nicholas");
var person2=new Person("Greg");
person1.favorites.push("pizza");
person2.favorites.push("quinoa");
console.log(person1.favorites);
console.log(person2.favorites);
favorites屬性被定義在原型對(duì)象上,意味著person1.favorites和person2.favorites指向同一個(gè)數(shù)組。你對(duì)任一Person對(duì)象的favorites插入的值都將成爲(wèi)原型對(duì)象上數(shù)據(jù)的元素。但這可能不是你期望的行爲(wèi),所以在原型對(duì)象上定義時(shí)你要非常小心。
雖然你可以在原型對(duì)象上一一添加屬性,但是很多開發(fā)者會(huì)使用一種更簡潔的方式:直接用一個(gè)對(duì)象字面形式替換原型對(duì)象。
如下:
function Person(name){
this.name=name;
};
Person.prototype={
sayName:function(){
console.log(this.name);
},
toString:function(){
return “[Person”+this.name+"]";
}
};
上段代碼在原型對(duì)象上定義了兩個(gè)訪拿廣發(fā),sayName()和toString()。這種定義的方式非常流行,因爲(wèi)這種方式不需要多次鍵入Person.prototype.但是有一個(gè)副作用需要注意。
var ?person1=new Person("Nicholas");
console.log(person1 instanceof Person);
console.log(person1.constructor ===Person);
console.log(person1.constructor ===Object);
使用對(duì)象字面形式改寫原型對(duì)象改變了構(gòu)造函數(shù)的屬性,因此現(xiàn)在指向Object而不是Person。這是因爲(wèi)原型對(duì)象具有一個(gè)constructor屬性,這是其他對(duì)象的實(shí)例沒有的。當(dāng)一個(gè)函數(shù)被創(chuàng)建時(shí),它的prototype屬性也被創(chuàng)建,且該原型對(duì)象的constructor屬性指向該函數(shù)。當(dāng)使用對(duì)字面形式改寫原型對(duì)象的Peroson.prototype時(shí),其constructor屬性將設(shè)置爲(wèi)泛用對(duì)象Object。爲(wèi)了避免這一點(diǎn)。需要在改寫原型對(duì)象時(shí)手動(dòng)重置其constructor屬性,如下例。
function Person(name){
this.name=name;
};
Person.prototype={
constructor:Person,
sayName:function(){
console.log(this.name);
},
toString:function(){
return "[Person"+this.name+" ]";
}
};
var person1=new Person("Nicholas");
var person2=new Person("Greg");
console.log(person1 instanceof Person);
console.log(person1.constructor === Person);
console.log(person1.constructor === Object);
console.log(person. instanceof Person);
console.log(person2.constructor === Person);
console.log(person2.constructor === Object);
本例顯示指定了原型對(duì)象的constructor屬性,爲(wèi)了不忘記賦值,最好把它設(shè)置爲(wèi)原型對(duì)象的第一屬性。
構(gòu)造函數(shù),原型對(duì)象和對(duì)象實(shí)例之間的關(guān)係最有趣的一個(gè)方面也許就是對(duì)象的實(shí)例和構(gòu)造函數(shù)之間沒有之間聯(lián)繫,不過對(duì)象實(shí)例和原型對(duì)象以及原型對(duì)象和構(gòu)造函數(shù)之間都有之間關(guān)係。這樣的關(guān)係意味著,如果打斷對(duì)象的實(shí)例和原型對(duì)之間的聯(lián)繫,那麼也將打斷對(duì)象和實(shí)例和其構(gòu)造函數(shù)的聯(lián)繫。
4.2.3 改變?cè)蛯?duì)象
給定類定的所有對(duì)象實(shí)例共享一個(gè)原型對(duì)象,所以你可以一次性擴(kuò)充所有對(duì)象實(shí)例。記住,[[Prototype]]屬性只是包含了一個(gè)指向原型對(duì)象的指針,任何對(duì)原型對(duì)象的改變都立即反映到所有引用它的對(duì)象實(shí)例上。這意味著你給原型對(duì)象添加的新成員都可以立即被所有已經(jīng)存在的對(duì)象實(shí)例使用,如下例
function Person(name){
this.name =name;
}
Person.prototyp={
constructor:Person,
sayName:function(){
console.log(this.name);
},
toString:function(){
return "[Person"+this.name+"]"};
}
var peson1=new Person("Nicholas");
var person2=new Person("Greg");
console.log("sayHi" in ?person1);
console.log("sayHi" in person2 );
Person.prototype.sayHi=function(){
console.log("Hi");
};
person1.sayHi();
person2.sayHi();
在這段代碼中,Person類型一開始只有兩個(gè)方法,sayName()和toString(),然後在創(chuàng)建兩個(gè)Person對(duì)象實(shí)例後給原型對(duì)象添加了一個(gè)sayHi(),對(duì)命名屬性的查找時(shí)在每次訪問屬性的時(shí)候發(fā)生的。所以可以做到無縫體驗(yàn)。
可以隨時(shí)改變?cè)蛯?duì)象的能力在封印對(duì)象和凍結(jié)對(duì)象上有一個(gè)十分有趣的後果。當(dāng)你在一個(gè)對(duì)象上使用Obejct.Seal()或Obejct.freeze()時(shí),完全是在操作對(duì)象的自有屬性,你無法添加自有屬性或改變凍結(jié)對(duì)象的自有屬性,但是仍然可以通過原型對(duì)象上添加屬性來擴(kuò)展這些對(duì)象的實(shí)例。如下例;
var person1=new Person("Nicholas");
var person2=new Person("Greg");
Object.freeze(person1);
Person.prototype.sayHi=function(){
console.log("Hi");
};
person1.sayHi();
person2.sayHi();
本例中有兩個(gè)Person的對(duì)象實(shí)例。Person1是 凍結(jié)對(duì)象而person2是普通對(duì)象,當(dāng)你在原型對(duì)象上添加sayHi()時(shí),person1和person2都獲得了這一新方法,這似乎不合person1的凍結(jié)狀態(tài)。其實(shí)[[Prototye]]屬性是對(duì)象實(shí)例的自有屬性,屬性本身被凍結(jié)。但其指向的值(原型對(duì)象)並沒有凍結(jié)。
注意:實(shí)際開發(fā)javascript時(shí),你不可能會(huì)頻繁地使用原型對(duì)象,但時(shí)理解對(duì)象實(shí)例以及其原型對(duì)象之間的關(guān)係是非常重要的,而像這樣的奇怪例子有助於你理解這些概念。
4.2.4 內(nèi)建對(duì)象的原型對(duì)象
到這裏,你可能會(huì)疑惑原型對(duì)象是否也允許你改版javascript引擎的標(biāo)準(zhǔn)內(nèi)建對(duì)象,答案是yes。所有內(nèi)建對(duì)象都有搞糟函數(shù),因此也都有原型對(duì)象給你去改變。例如,在所有數(shù)組上添加一個(gè)新的方法只需要簡單地修改Array.prototype即可。
Array.prototype.sum=function(){
return this.reduce(function(pervious,current){
return previous+current;
});
};
var number =[1,2,3,4,5,6];
var result=number.sum();
console.log(result);
這個(gè)例子在Array.prototype上創(chuàng)建了一個(gè)名爲(wèi)sum()的方法,該方法對(duì)該數(shù)組的所有元素求和並返回。numbers數(shù)組通過原型對(duì)象自動(dòng)擁有這個(gè)方法,在sum()內(nèi)部,this指向數(shù)組的對(duì)象實(shí)例numbers,於是該方法也可以自由使用數(shù)組的其他方法,比如reduce()。
你可能還記得字符串,數(shù)字和布爾類型都有內(nèi)建的原始封裝類型來幫助我們像使用普通對(duì)象一樣來使用它們,如果改變?cè)挤庋b類型的原始對(duì)象,你就可以給這些原始值添加更多的功能,如下例
String.prototype.capitalize=function(){
return this.charAt(0).toUpperCase()+this.substring(1);
};
var message ="hello world";
console.log(message.capitalize());
這段代碼爲(wèi)字符轉(zhuǎn)創(chuàng)建了一個(gè)名爲(wèi)capitalize()的方法,String類型是字符串的原始封裝類型。修改其原型對(duì)象意味著所有的字串都自動(dòng)獲得這些改動(dòng)。
注意:修改內(nèi)建對(duì)象來實(shí)驗(yàn)各種功能是既有好玩的事情,但在生產(chǎn)環(huán)境中這門做不是一個(gè)好主意,開發(fā)者們都期望一個(gè)內(nèi)建對(duì)象具有一定的方法並表現(xiàn)出一定的行爲(wèi),故意改變內(nèi)建對(duì)象會(huì)破壞這種期望導(dǎo)致其他開發(fā)者無法確定這些對(duì)象會(huì)如何工作。
4.3 總結(jié)
構(gòu)造函數(shù)就是用new操作符調(diào)用普通函數(shù),你可以隨時(shí)定義你自己的構(gòu)造函數(shù)來創(chuàng)建多個(gè)具有同樣屬性的對(duì)象。可以用instaceof 操作符或直接訪問constructor屬性來鑑別對(duì)象被那個(gè)構(gòu)造函數(shù)創(chuàng)建的。
每一個(gè)函數(shù)都具有prototype屬性,它定義了該構(gòu)造函數(shù)的所有對(duì)象的共享的屬性,通常,共享的方法和原始值屬性被定義在原型對(duì)象裏,而其他屬性都定義在構(gòu)造函數(shù)裏。constructor屬性實(shí)際上被定義在原型對(duì)象裏供所有對(duì)象實(shí)例共享。
原型對(duì)象被保存在對(duì)象的實(shí)例內(nèi)部的[[Prototype]]屬性中,這個(gè)屬性時(shí)一個(gè)引用而不是一個(gè)副本。由於javascript查找屬性的機(jī)制。你對(duì)原型對(duì)象的修改都立刻出現(xiàn)在所有對(duì)象的實(shí)例中。當(dāng)你試圖訪問一個(gè)對(duì)象的某個(gè)屬性時(shí),javascript首先在自有屬性中查找該屬性的名字,如果在自有屬性中沒有找到則查找原型屬性。這樣的機(jī)制意味著原型對(duì)象可以隨時(shí)改變而引用它的對(duì)象實(shí)例則立即反映出這些改變。
內(nèi)建對(duì)象也有可以被修改的原型對(duì)象。雖然不建議在生產(chǎn)環(huán)境中這麼做。但它們可以被用來實(shí)驗(yàn)或驗(yàn)證新功能。