原型鏈做爲實現繼承的主要方法,其基本思路是利用原型讓一個引用類型繼承另外一個引用類型的屬性和方法, 構造函數,原型和實例之間的關係經過一張圖來解釋一下,須要詳細瞭解的能夠看一下個人另一篇文章javascript
原型鏈繼承的基本模式以下:git
function Parent() { this.name = "heyushuo"; } Parent.prototype.sayParentName = function() { console.log(this.name); }; function Child() { this.name = "kebi"; } //1.此時把Child的原型重寫了,換成了Parent的實例 //2.換句話說,原來存在Parent的實例中的屬性和方法,如今也存在Child.prototype中了 Child.prototype = new Parent(); //3.在繼承了Parent實例中的屬性和方法後基礎上,又添加了屬於本身的一個新方法(這裏兩個名字同樣會覆蓋) Child.prototype.sayChildName = function() { console.log(this.name); }; var Person = new Child(); console.log(Person); //因此如今Person指向Child的原型,Child的原型指向Parent的原型(由於Child的原型對象等於了Parent的實例,這個實例指向Parent的原型)
經過以下圖打印的 Person 看一下他們的關係: 這裏特別須要注意的是 Person.constructor 如今指向的是 Parent,由於 Child.prototype 中的 constructor 被重寫了 能夠經過以下代碼改變 constructor 的指向github
//改變 constructor 的指向 Child.prototype.constructor = Child;
1. instanceof (實例對象是不是構造函數函數的實例)函數
console.log(Person instanceof Child); //true console.log(Person instanceof Parent); //true console.log(Person instanceof Object); //true //因爲原型鏈的關係,能夠說Person是他們三個中任何一個類型的實例
2.isPrototypeOf(Person) 只要原型鏈中出現過的原型,均可以說是該原型鏈派生的實例的原型(能夠理解爲是不是實例的原型) Object.prototype.isPrototypeOf(Person) //true Parent.prototype.isPrototypeOf(Person) //true Child.prototype.isPrototypeOf(Person) //truethis
再給 Child 添加新的方法的時候,必定要在原型繼承父元素後添加,這樣能夠防止本身定義的方法,會和繼承來的方法名字相同,致使 Child 本身定的方法被覆蓋prototype
1.實例共享引用類型3d
雖然原型鏈繼承很強大, 可是存在一個問題, 最主要的問題是包含引用類型值的原型, 由於包含引用類型值的原型屬性會被全部的實例共享, 而在經過原型來實現繼承的時候, 原型實際變成了另一個函數的實例(這裏邊就有可能存在引用類型)code
經過一個例子看一下對象
function Parent() { this.newArr = ["heyushuo", "kebi"]; } function Child() { this.name = "kebi"; } Child.prototype = new Parent(); var Person1 = new Child(); Person1.newArr.push("kuli"); console.log(Person1.newArr); // ["heyushuo","kebi","kuli"] var Person2 = new Child(); console.log(Person2.newArr); // ["heyushuo","kebi","kuli"]
2.在建立 Child 的子類的時候,沒法像繼承元素傳遞參數