原型(prototype)
在JavaScript中,原型(prototype)也是一個對象,通過原型可以實現(xiàn)對象的屬性繼承,JavaScript的對象中都包含了一個prototype
內(nèi)部屬性染坯,這個屬性所對應(yīng)的就是該對象的原型羹应。
prototype
作為對象的內(nèi)部屬性掀鹅,是不能被直接訪問的散休。所以為了方便查看一個對象的原型,F(xiàn)irefox和Chrome中提供了 __ proto__ 這個非標(biāo)準(zhǔn)(不是所有瀏覽器都支持)的訪問器(ECMA引入了標(biāo)準(zhǔn)對象原型訪問器 Object.getPrototype(object))乐尊。在JavaScript的原型對象中戚丸,還包含了一個constructior
屬性,這個屬性對應(yīng)創(chuàng)建所有指向改原型的實例的構(gòu)造函數(shù)扔嵌。
原型(prototype)作用
通過構(gòu)造函數(shù)為實例對象定義屬性限府,雖然很方便,但是有一個缺點痢缎。同一個構(gòu)造函數(shù)的多個實例之間胁勺,無法共享屬性,從而造成對系統(tǒng)資源的浪費(fèi)独旷。
JavaScript 繼承機(jī)制的設(shè)計思想就是署穗,原型對象的所有屬性和方法,都能被實例對象共享嵌洼。也就是說案疲,如果屬性和方法定義在原型上,那么所有實例對象就能共享咱台,不僅節(jié)省了內(nèi)存络拌,還體現(xiàn)了實例對象之間的聯(lián)系俭驮。
JavaScript規(guī)定回溺,每個函數(shù)都有一個
prototype
屬性,指向一個對象混萝。
function f() {}
typeof f.prototype // "object"
上面代碼中遗遵,函數(shù)f默認(rèn)具有prototype屬性,指向一個對象逸嘀。
對于普通函數(shù)來說车要,該屬性基本無用。但是崭倘,對于構(gòu)造函數(shù)來說翼岁,生成實例的時候,該屬性會自動成為實例對象的原型司光。
function Animal(name){
this.name = name;
}
Animal.prototype.color = 'white';
var cat1 = new Animal('大貓')琅坡;
var cat2 = new Animal('二貓');
cat1.color // 'white'
cat2.color // 'white'
上面代碼中残家,構(gòu)造函數(shù)Animal的prototype屬性榆俺,就是實例對象cat1和cat2的原型對象。
原型對象上天驕一個color屬性,結(jié)果實例對象都共享了該屬性。
原型對象的屬性不是實例對象自身的屬性茴晋。只要修改原型對象陪捷,變動就立刻會體現(xiàn)在所有實例對象上。
Animal.prototype.color = 'yellow';
cat1.color // 'yellow'
cat2.color // 'yellow'
上面代碼中诺擅,原型對象的color屬性的值變?yōu)閥ellow市袖,兩個實例對象的color屬性立刻跟著變了。
這是因為實例對象其實沒有color屬性掀虎,都是讀取原型對象的color屬性凌盯。
也就是說,當(dāng)實例對象本身沒有某個屬性或方法的時候烹玉,它會到原型對象去尋找該屬性或方法驰怎。這就是原型對象的特殊之處。
如果實例對象自身就有某個屬性或方法二打,它就不會再去原型對象尋找這個屬性或方法县忌。
cat1.color = 'black';
cat1.color //'black'
cat2.color // 'yellow'
Animal.prototype.color //'yellow'
上面代碼中,實例對象cat1的color屬性改為black继效,就使得它不再去原型對象讀取color屬性症杏,后者的值依然為yellow。
原型對象的作用瑞信,就是定義所有實例對象共享的屬性和方法厉颤。這也是它被稱為原型對象的原因,而實例對象可以視作從原型對象衍生出來的子對象凡简。
原型鏈
原型鏈的基本思想是利用原型讓一個引用類型繼承另一個引用類型的屬性和方法逼友。因為每個對象和原型都有原型,對象的原型指向原型對象秤涩,而父的原型又指向父的父帜乞,這種原型層層連接起來的就構(gòu)成了原型鏈(prototype chain)。
- 構(gòu)造函數(shù)筐眷、原型和實例的關(guān)系:
每個構(gòu)造函數(shù)都有一個原型對象黎烈,原型對象包含一個指向構(gòu)造函數(shù)的指針(prototype),而實例則包含一個指向原型對象的內(nèi)部指針(__ proto __)匀谣。
如果一層層地上溯照棋,所有對象的原型最終都可以上溯到Object.prototype,即Object構(gòu)造函數(shù)的prototype屬性武翎。也就是說烈炭,所有對象都繼承了Object.prototype的屬性。這就是所有對象都有valueOf和toString方法的原因后频,因為這是從Object.prototype繼承的梳庆。
那么暖途,Object.prototype對象有沒有它的原型呢?回答是Object.prototype的原型是null膏执。null沒有任何屬性和方法驻售,也沒有自己的原型。因此更米,原型鏈的盡頭就是null欺栗。
注意,一級級向上征峦,在整個原型鏈上尋找某個屬性迟几,對性能是有影響的。所尋找的屬性在越上層的原型對象栏笆,對性能的影響越大类腮。如果尋找某個不存在的屬性,將會遍歷整個原型鏈蛉加。
_ proto_ 和 prototype的區(qū)別是蚜枢?
一句話:_ proto_是對象的屬性;prototype是函數(shù)的屬性
- 不能斷章取義针饥,_ proto_ 和 prototype只是兩個key而已
- 我們一般研究對象的__ proto__和函數(shù)的prototype
- 對象.__ proto__ === 某函數(shù).prototype
- 如果把函數(shù)看成對象厂抽,那么函數(shù).__ proto__ === Function.prototype
- 如果把 Function 看成對象,那么 Function.__ proto__ === Function.prototype
- Function.prototype._ proto_ == Object.prototype
文章著作權(quán)歸饑人谷_sunny和饑人谷所有丁眼,轉(zhuǎn)載須說明來源