原型鏈和繼承

2022-03-09 06:02:42 字數 3739 閱讀 4219

原型鏈:

它是繼承的主要方法,其基本思想是讓乙個引用型別繼承另外乙個引用型別的屬性和方法。

每個建構函式都一有乙個prototype屬性,它指向它的原型物件

原型物件包含了 該建構函式所建立的 所有例項 共享的 屬性和方法

假如讓乙個原型物件等於另外乙個型別的例項,那麼該物件的例項可以訪問另外一種原型的屬性和方法。從而形成原型鏈

當我們呼叫乙個物件的屬性和方法時,首先在該物件自身屬性查詢,如果不存在就去自己的原型物件裡找,如果還不存在,就向原型物件所關聯的另外的原型物件裡尋找。。如果有就返回,如果找到原型鏈的終點null時還沒有找到,就返回undefined。

object.prototype是所有物件的原型。

繼承共有6種方法

原型鏈繼承就是讓子型別的原型等於父型別的例項,這種方法無法向超型別傳遞引數並且存在超型別包含引用型別的屬性的問題,所以這種方法很少單獨使用。

還有一種就是建構函式繼承,就是在子型別當中使用call()來呼叫超型別的建構函式,這種方法解決了上述兩種問題,但是函式復用無從談起。

接下來是最常用的一種方法,組合使用原型鏈繼承和建構函式繼承,它綜合了上述兩種方法的優點,還解決了函式復用,引用型別屬性,傳遞引數的問題。

其基本思想就是,使用原型鏈繼承超型別的方法,使用建構函式繼承超型別的屬性。

這樣一來,既可以讓兩個子型別的不同例項擁有自己的屬性,又可以使用相同的方法了。

還有一種就是原型式繼承,這個繼承方法和object.create(obj)方法一樣,引數是所要繼承的原型,但是它只是對傳入的物件進行了淺賦值,所有引用型別的屬性被所有例項所共享,如果只想讓乙個物件和另外的物件保持型別相同的情況下可以使用。

1、原型鏈繼承:讓子類的原型等於父類的例項

function father()

this.lastname="li";

}function child()

child.prototype=new father();

var child=new child();

child.lastname; //"li"

缺點:包含引用型別值所帶來的問題:如果超型別包含引用型別值的屬性,子型別通過原型繼承後,子型別的例項都會共享這個包含引用型別值的屬性,如果在乙個例項中修改,就會反映到另外乙個例項上。

function father()

function child()

child.prototype=new father();

var c1=new child();

var c2=new child();

c1.colors //["red", "blue"]

c1.colors.push("yellow");

c1.colors //["red", "blue", "yellow"]

c2.colors //["red", "blue", "yellow"]

子類無法給父類傳遞引數。

鑑於此,很少單獨使用原型鏈繼承。

function father(firstname)

}function child(firstname)

var c1=new child("furong");

c1.sayname();// my name is lifurong

var c2=new child("rui");

c1.sayname();//my name is lirui

優點:在子型別建構函式中向超型別傳遞引數

缺點:因為方法都在建構函式內定義,函式復用無從談起。所以建構函式繼承也很少單獨使用

3、組合繼承:將原型鏈和借用建構函式組合起來,發揮兩者的長處。思路就是使用原型鏈實現對原型屬性和方法的繼承,通過建構函式例項對例項屬性的繼承。

這樣一來,又可以使兩個不同的子型別例項即分別擁有自己的屬性,又可以使用相同的方法了,

//超型別的屬性

function father(firstname)

//超型別的方法

father.prototype.sayname=function()

//通過建構函式繼承超型別的屬性

function child(firstname,age)

//通過原型鏈繼承超型別的方法

child.prototype=new father();

//子型別自己的方法

child.prototype.sayage=function()

var c1=new child("furong",24);

c1.sayname();// my name is lifurong

c1.sayage() // 24

var c2=new child("rui",18);

c2.sayname();//my name is lirui

c2.sayage() //18

4、原型式繼承

本質上講,object函式是對傳入的物件進行了淺複製:引用型別的屬性被所有例項共享

這個和object.create()方法一樣,這個方法接收兩個引數,第乙個引數是原型物件,第二個是為新物件定義的額外屬性。

function object(o);

f.prototype=o;

return new f();

}var father=

var c1=object(father);

c1.lastname;

c1.colors.push("yellow");

var c2=object(father);

c2.lastname;

c2.colors; //["red", "blue", "yellow"]

缺點:和原型鏈繼承一樣:包含引用型別值所帶來的問題:如果超型別包含引用型別值的屬性,子型別通過原型繼承後,子型別的例項都會共享這個包含引用型別值的屬性,如果在乙個例項中修改,就會反映到另外乙個例項上。

優點:如果只想讓乙個物件和另外乙個物件保持型別的情況下可以用。

5.寄生式繼承

寄生式繼承就是建立乙個僅用於封裝繼承過程的函式,該函式在內部用某種方式來增強物件

function createanother(original)

return obj;//返回這個物件

}var person=

var o1=createanother(person) //繼承person並且擁有自己的方法

object.keys(o1); //["sayhi"] 自有的屬性

缺點:函式復用問題。還有引用型別的屬性共享問題。

6.寄生組合式繼承

是組合繼承的改良版,組合繼承雖然是最常用的繼承模式,但它最大的問題是無論在什麼情況下,都會呼叫兩次超型別的建構函式,一次是建立子型別原型的時候,一次是在子型別建構函式內部。兩次呼叫造成的後果是,在呼叫子型別建構函式時,原型的屬性會被例項的屬性重寫。

寄生組合的基本思路是:用寄生式繼承來繼承超型別的原型,再將結果指定給子型別的原型

function inheritprototype(subtype,supertype)

//省略了subtype.prototype=new supertype()

優點:只呼叫了一次超型別的建構函式,因此避免了在子型別的原型上建立不必要的、多餘的屬性。而且原型鏈還能保持不變,因此能正常使用instanceof和isprototypeof()來檢測例項和原型的關係。

開發人員普遍認為寄生組合式繼承是繼承的最佳方式。

原型 原型鏈和繼承

看一段 就明白了function person nick,age person.prototype.sayname function var p1 newperson byron 20 var p2 newperson casper 25 p1.sayname byron p2.sayname ca...

原型 原型鏈 繼承

原型 是function物件的乙個屬性,它定義了建構函式 製造出的物件 的公共祖先。通過該建構函式產生的物件,可以繼承該原型的屬性和方法。原型也是物件 這定義有點模糊,用 解釋一下 我們在控制台中列印出了這個,首先son物件的建構函式是foo,但是我們的foo中什麼屬性都沒有,怎麼會出現乙個 pro...

原型 原型鏈 繼承

在 js 中,一切皆物件!下面就讓我們從建立物件開始,逐步學習js中的核心知識 原型,原型鏈,繼承等 1.字面量方式建立物件 var obj var obj1 2.使用 new object 的方式建立物件 var obj2 new object obj2.name 張三 obj2.age 13 o...