一、prototype
1、prototype屬性的作用
JavaScript的每個(gè)對(duì)象都繼承“原型”(prototype)對(duì)象上的所有屬性和方法唁影。只有null除外,它沒(méi)有自己的原型對(duì)象掂名。
構(gòu)造函數(shù)生成實(shí)例對(duì)象時(shí)据沈,會(huì)自動(dòng)為實(shí)例對(duì)象分配原型對(duì)象。每一個(gè)構(gòu)造函數(shù)都有一個(gè)prototype屬性饺蔑,這個(gè)屬性就是實(shí)例對(duì)象的原型對(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對(duì)象,就是實(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"
如果實(shí)例對(duì)象自身就有某個(gè)屬性或方法,它就不會(huì)再去原型對(duì)象尋找這個(gè)屬性或方法雳窟。
cat1.color = 'black';
cat2.color // 'yellow'
Animal.prototype.color // "yellow";
總結(jié):原型對(duì)象的作用尊浪,就是定義所有實(shí)例對(duì)象共享的屬性和方法;
實(shí)例對(duì)象可以視作從原型對(duì)象衍生出來(lái)的子對(duì)象
2封救、原型鏈
對(duì)象的屬性和方法拇涤,有可能是定義在自身,也有可能是定義在它的原型對(duì)象誉结。由于原型本身也是對(duì)象鹅士,又有自己的原型,所以形成了一條原型鏈(prototype chain)惩坑。所有對(duì)象的原型最終都可以上溯到Object.prototype掉盅,即Object構(gòu)造函數(shù)的prototype屬性指向的那個(gè)對(duì)象。
Object.getPrototypeOf(Object.prototype)
//null
//上面代碼表示以舒,Object.prototype對(duì)象的原型是null趾痘,
//由于null沒(méi)有任何屬性,所以原型鏈到此為止蔓钟。
//如果對(duì)象自身和它的原型永票,都定義了一個(gè)同名屬性,那么優(yōu)先讀取對(duì)象自身的屬性,這叫做“覆蓋”
//“原型鏈”的作用是侣集,讀取對(duì)象的某個(gè)屬性時(shí)键俱,JavaScript引擎先尋找對(duì)象本身的屬性,
//如果找不到世分,就到它的原型去找方妖,如果還是找不到,就到原型的原型去找罚攀。
//如果直到最頂層的Object.prototype還是找不到,則返回undefined雌澄。
//如果尋找某個(gè)不存在的屬性斋泄,將會(huì)遍歷整個(gè)原型鏈。
3镐牺、constructor屬性
prototype對(duì)象有一個(gè)constructor屬性炫掐,默認(rèn)指向prototype對(duì)象所在的構(gòu)造函數(shù)。
function P() {}
var p = new P();
p.constructor// function P() {}
p.constructor === P.prototype.constructor// true
p.hasOwnProperty('constructor')// false
constructor屬性的作用睬涧,是分辨原型對(duì)象到底屬于哪個(gè)構(gòu)造函數(shù)募胃。
function Super() {}
function Sub() {
Sub.superclass.constructor.call(this);
}
Sub.superclass = new Super();
//Super和Sub都是構(gòu)造函數(shù),在Sub內(nèi)部的this上調(diào)用Super畦浓,就會(huì)形成Sub繼承Super的效果
下例中痹束,a是A的實(shí)例。修改了A.prototype以后讶请,constructor屬性的指向就變了祷嘶,導(dǎo)致instanceof運(yùn)算符失真。
function A() {}
var a = new A();
a instanceof A // true
function B() {}
A.prototype = B.prototype;
a instanceof A // false
所以夺溢,修改原型對(duì)象時(shí)论巍,一般要同時(shí)校正constructor屬性的指向。
C.prototype.method1 = function (...) { ... };
//只在原型對(duì)象上添加方法风响,這樣可以保證instanceof運(yùn)算符不會(huì)失真嘉汰。
通過(guò)name屬性,可以從實(shí)例得到構(gòu)造函數(shù)的名稱
function Foo() {}
var f = new Foo();
f.constructor.name // "Foo"