1. 程式人生 > >JavaScript之原型鏈繼承&注意點和缺點

JavaScript之原型鏈繼承&注意點和缺點

原型鏈繼承

原型鏈作為實現繼承的主要方法,其基本思路是利用原型讓一個引用型別繼承另一個引用型別的屬性和方法, 建構函式,原型和例項之間的關係通過一張圖來解釋一下,需要詳細瞭解的可以看一下我的另外一篇文章

JavaScirpt 之原型&原型物件和原型鏈

原型鏈繼承的基本模式如下:

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 的指向

//改變 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) //true

三.需要注意的問題

再給 Child 新增新的方法的時候,一定要在原型繼承父元素後新增,這樣可以防止自己定義的方法,會和繼承來的方法名字相同,導致 Child 自己定的方法被覆蓋

四.原型鏈繼承的問題

1.例項共享引用型別

雖然原型鏈繼承很強大, 但是存在一個問題, 最主要的問題是包含引用型別值的原型, 因為包含引用型別值的原型屬性會被所有的例項共享, 而在通過原型來實現繼承的時候, 原型實際變成了另外一個函式的例項(這裡邊就有可能存在引用型別)

通過一個例子看一下

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 的子類的時候,無法像繼承元素傳遞引數

總結:因為有如上兩個問題,實踐中很少會單獨使用原型鏈繼承