原型(prototype)
在JavaScript中苍凛,原型(prototype)也是一個(gè)對(duì)象椿胯,通過原型可以實(shí)現(xiàn)對(duì)象的屬性繼承宏赘,JavaScript的對(duì)象中都包含了一個(gè)prototype
內(nèi)部屬性,這個(gè)屬性所對(duì)應(yīng)的就是該對(duì)象的原型话侧。
prototype
作為對(duì)象的內(nèi)部屬性佛析,是不能被直接訪問的益老。所以為了方便查看一個(gè)對(duì)象的原型,F(xiàn)irefox和Chrome中提供了 __ proto__ 這個(gè)非標(biāo)準(zhǔn)(不是所有瀏覽器都支持)的訪問器(ECMA引入了標(biāo)準(zhǔn)對(duì)象原型訪問器 Object.getPrototype(object))寸莫。在JavaScript的原型對(duì)象中捺萌,還包含了一個(gè)constructior
屬性,這個(gè)屬性對(duì)應(yīng)創(chuàng)建所有指向改原型的實(shí)例的構(gòu)造函數(shù)储狭。
原型(prototype)作用
通過構(gòu)造函數(shù)為實(shí)例對(duì)象定義屬性互婿,雖然很方便捣郊,但是有一個(gè)缺點(diǎn)。同一個(gè)構(gòu)造函數(shù)的多個(gè)實(shí)例之間慈参,無法共享屬性呛牲,從而造成對(duì)系統(tǒng)資源的浪費(fèi)。
JavaScript 繼承機(jī)制的設(shè)計(jì)思想就是驮配,原型對(duì)象的所有屬性和方法娘扩,都能被實(shí)例對(duì)象共享。也就是說壮锻,如果屬性和方法定義在原型上琐旁,那么所有實(shí)例對(duì)象就能共享,不僅節(jié)省了內(nèi)存猜绣,還體現(xiàn)了實(shí)例對(duì)象之間的聯(lián)系灰殴。
JavaScript規(guī)定,每個(gè)函數(shù)都有一個(gè)
prototype
屬性掰邢,指向一個(gè)對(duì)象牺陶。
function f() {}
typeof f.prototype // "object"
上面代碼中,函數(shù)f默認(rèn)具有prototype屬性辣之,指向一個(gè)對(duì)象掰伸。
對(duì)于普通函數(shù)來說,該屬性基本無用怀估。但是狮鸭,對(duì)于構(gòu)造函數(shù)來說,生成實(shí)例的時(shí)候多搀,該屬性會(huì)自動(dòng)成為實(shí)例對(duì)象的原型歧蕉。
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屬性,就是實(shí)例對(duì)象cat1和cat2的原型對(duì)象麻削。
原型對(duì)象上天驕一個(gè)color屬性,結(jié)果實(shí)例對(duì)象都共享了該屬性。
原型對(duì)象的屬性不是實(shí)例對(duì)象自身的屬性春弥。只要修改原型對(duì)象呛哟,變動(dòng)就立刻會(huì)體現(xiàn)在所有實(shí)例對(duì)象上。
Animal.prototype.color = 'yellow';
cat1.color // 'yellow'
cat2.color // 'yellow'
上面代碼中匿沛,原型對(duì)象的color屬性的值變?yōu)閥ellow扫责,兩個(gè)實(shí)例對(duì)象的color屬性立刻跟著變了。
這是因?yàn)閷?shí)例對(duì)象其實(shí)沒有color屬性逃呼,都是讀取原型對(duì)象的color屬性鳖孤。
也就是說者娱,當(dāng)實(shí)例對(duì)象本身沒有某個(gè)屬性或方法的時(shí)候,它會(huì)到原型對(duì)象去尋找該屬性或方法苏揣。這就是原型對(duì)象的特殊之處黄鳍。
如果實(shí)例對(duì)象自身就有某個(gè)屬性或方法,它就不會(huì)再去原型對(duì)象尋找這個(gè)屬性或方法平匈。
cat1.color = 'black';
cat1.color //'black'
cat2.color // 'yellow'
Animal.prototype.color //'yellow'
上面代碼中框沟,實(shí)例對(duì)象cat1的color屬性改為black,就使得它不再去原型對(duì)象讀取color屬性增炭,后者的值依然為yellow忍燥。
原型對(duì)象的作用,就是定義所有實(shí)例對(duì)象共享的屬性和方法隙姿。這也是它被稱為原型對(duì)象的原因梅垄,而實(shí)例對(duì)象可以視作從原型對(duì)象衍生出來的子對(duì)象。
原型鏈
原型鏈的基本思想是利用原型讓一個(gè)引用類型繼承另一個(gè)引用類型的屬性和方法输玷。因?yàn)槊總€(gè)對(duì)象和原型都有原型哎甲,對(duì)象的原型指向原型對(duì)象,而父的原型又指向父的父饲嗽,這種原型層層連接起來的就構(gòu)成了原型鏈(prototype chain)炭玫。
- 構(gòu)造函數(shù)、原型和實(shí)例的關(guān)系:
每個(gè)構(gòu)造函數(shù)都有一個(gè)原型對(duì)象貌虾,原型對(duì)象包含一個(gè)指向構(gòu)造函數(shù)的指針(prototype)吞加,而實(shí)例則包含一個(gè)指向原型對(duì)象的內(nèi)部指針(__ proto __)。
如果一層層地上溯尽狠,所有對(duì)象的原型最終都可以上溯到Object.prototype衔憨,即Object構(gòu)造函數(shù)的prototype屬性。也就是說袄膏,所有對(duì)象都繼承了Object.prototype的屬性践图。這就是所有對(duì)象都有valueOf和toString方法的原因,因?yàn)檫@是從Object.prototype繼承的沉馆。
那么码党,Object.prototype對(duì)象有沒有它的原型呢?回答是Object.prototype的原型是null斥黑。null沒有任何屬性和方法揖盘,也沒有自己的原型。因此锌奴,原型鏈的盡頭就是null兽狭。
注意,一級(jí)級(jí)向上,在整個(gè)原型鏈上尋找某個(gè)屬性箕慧,對(duì)性能是有影響的服球。所尋找的屬性在越上層的原型對(duì)象,對(duì)性能的影響越大颠焦。如果尋找某個(gè)不存在的屬性斩熊,將會(huì)遍歷整個(gè)原型鏈。
_ proto_ 和 prototype的區(qū)別是蒸健?
一句話:_ proto_是對(duì)象的屬性座享;prototype是函數(shù)的屬性
- 不能斷章取義,_ proto_ 和 prototype只是兩個(gè)key而已
- 我們一般研究對(duì)象的__ proto__和函數(shù)的prototype
- 對(duì)象.__ proto__ === 某函數(shù).prototype
- 如果把函數(shù)看成對(duì)象似忧,那么函數(shù).__ proto__ === Function.prototype
- 如果把 Function 看成對(duì)象渣叛,那么 Function.__ proto__ === Function.prototype
- Function.prototype._ proto_ == Object.prototype
轉(zhuǎn)載自:http://www.reibang.com/p/a9d8dbc755b3
作者:饑人谷_sunny