在理解原型鏈之前坷襟,首先要知道構(gòu)造函數(shù)、實例廓奕、原型三者是什么,以及之間的關(guān)系桌粉。
構(gòu)造函數(shù)
function Person() {}
實例
var person = new Person();
構(gòu)造函數(shù): 和普通函數(shù)沒什么區(qū)別衙四,不過構(gòu)造函數(shù)的首寫字母始終都是大寫的,
這是區(qū)別于普通函數(shù)传蹈,它是專門用來創(chuàng)建對象存在的。
實例:就是new一個構(gòu)造函數(shù)宴胧。
原型:是一個對象,屬性和方法是共享的恕齐,即共有的瞬逊。
多個實例可以共享里面的屬性和方法。
構(gòu)造函數(shù)确镊、原型、實例這三者有著什么微妙關(guān)系呢蕾域?
1. 構(gòu)造函數(shù)的prototype指向 原型方法的constructor
Person.prototype ===? { constructor: Person }
2.原型的constructor指向構(gòu)造函數(shù)
Person.prototype.constructor ===? Person
3. 實例的__proto__指針指向 原型對象
person.___proto__ === { constructor: Person }
了解了這些基本的,我們就可以來理解什么是原型鏈了巨缘?
先看看書上的描述:
EACMScript中描述了原型鏈的概念采呐,并將原型鏈作為實現(xiàn)繼承的主要方法。
其基本思想是:利用原型讓一個引用類型繼承另一個引用類型的屬性和方法斧吐。
簡單的回顧一下:原型和實例的關(guān)系:
每個構(gòu)造函數(shù)都有一個原型對象仲器,原型對象都包含一個指向構(gòu)造函數(shù)的指針仰冠,
而實例包含一個指向原型對象的內(nèi)部指針。
那么我們讓原型對象等于另一個類型的實例沪停,結(jié)果會怎樣呢?
顯然此時的原型對象將包含一個指向另一個原型的指針众辨,
相應(yīng)地,另一個原型也包含一個指向另一個構(gòu)造函數(shù)的指針鹃彻。
假如另一個原型又是另一個類型的實例妻献,那么上述的關(guān)系依然成立,
如此層層遞進育拨,就構(gòu)成了實例與原型的鏈條。這就是所謂原型鏈的基本概念熬丧。
上面這段話是書上原文,我覺得沒有比書上寫的更簡單害捕、通俗易懂了。
下面是一個例子
父類構(gòu)造函數(shù)Person
function Person() {
? ? this.name = '小仙女';
}
構(gòu)造函數(shù)的原型方法
Person.prototype.sayName = function(){
? ? return this.name;
}
子類構(gòu)造函數(shù)
function Son() {
}
子類構(gòu)造函數(shù)的原型
在這里把父類的實例賦給了子類的原型上尝盼,從而實現(xiàn)了繼承佑菩,從而可以共享父類的屬性和方法。
Son.prototype = new Person();
//子類構(gòu)造函數(shù)的實例
var son1 = new Son();
//子類共享父類的屬性
console.log(son1.name); //小仙女
//子類共享父類的方法
console.log('son1.sayName()',son1.sayName()); //小仙女
```
上面代碼定義了兩個類型:父類(Perosn)和子類(Son)倘待。
父類有一個屬性name疮跑。原型上有一個sayName()方法凸舵。
在這里子類Son繼承了父類的方法和屬性失尖,為什么呢渐苏?
因為下面這行代碼:
Son.prototype = new Person()
子類父類的實例賦給了Son的原型菇夸,因此Son的原型相當(dāng)于重寫。以前Son的原型本來沒有屬性和方法庄新,
現(xiàn)在都有了(繼承了父類的屬性和方法)。因此son1.name是'小仙女'械蹋。還有調(diào)用son1.sayName打印的也是'小仙女'。
實現(xiàn)的本質(zhì)是:重寫原型對象哗戈,代之以一個新類型的實例。