經典面試題 js繼承方式上

2021-09-29 01:12:47 字數 3832 閱讀 6528

js不是傳統的物件導向語言,那麼他是怎麼實現繼承的呢?由於js是基於原型鏈實現的物件導向,所以js主要通過原型鏈查詢來實現繼承,主要有兩大類實現方式,分為基於建構函式的繼承,以及非建構函式的繼承。

由於篇幅較長,所以把文章分為上下篇,今天先講解上半部分。

現在有兩個類即建構函式,乙個是動物類

function

animal()

乙個是貓類

function

cat(name, color)

怎樣才能使"貓"繼承"動物"的特性呢?

一、 建構函式繫結

function

cat(name, color)   

var cat1 = new cat("大毛", "黃色");  

alert(cat1.species);

//動物

二、 prototype模式

第二種方法更常見,使用prototype屬性。

如果"貓"的prototype物件,指向乙個animal的例項,那麼所有"貓"的例項,就能繼承animal了。

cat.prototype = new

animal();  

cat.prototype.constructor =cat;  

var cat1 = new cat("大毛", "黃色");  

alert(cat1.species);

//動物

**的第一行,我們將cat的prototype物件指向乙個animal的例項。

它相當於完全刪除了prototype 物件原先的值,然後賦予乙個新值。但是,第二行又是什麼意思呢?

原來,任何乙個prototype物件都有乙個constructor屬性,指向它的建構函式。如果沒有"cat.prototype = new animal();"這一行,cat.prototype.constructor是指向cat的;加了這一行以後,cat.prototype.constructor指向animal。

更重要的是,每乙個例項也有乙個constructor屬性,預設呼叫prototype物件的constructor屬性。

因此,在執行"cat.prototype = new animal();"這一行之後,cat1.constructor也指向animal!

這顯然會導致繼承鏈的紊亂(cat1明明是用建構函式cat生成的),因此我們必須手動糾正,將cat.prototype物件的constructor值改為cat。這就是第二行的意思。

這是很重要的一點,程式設計時務必要遵守。下文都遵循這一點,即如果替換了prototype物件,

那麼,下一步必然是為新的prototype物件加上constructor屬性,並將這個屬性指回原來的建構函式。

三、 直接繼承prototype

第三種方法是對第二種方法的改進。由於animal物件中,不變的屬性都可以直接寫入animal.prototype。所以,我們也可以讓cat()跳過 animal(),直接繼承animal.prototype。

現在,我們先將animal物件改寫:

function

animal() {}  

animal.prototype.species = "動物";

然後,將cat的prototype物件,然後指向animal的prototype物件,這樣就完成了繼承。

cat.prototype =animal.prototype;  

cat.prototype.constructor =cat;  

var cat1 = new cat("大毛", "黃色");  

alert(cat1.species);

//動物

與前一種方法相比,這樣做的優點是效率比較高(不用執行和建立animal的例項了),比較省記憶體。缺點是 cat.prototype和animal.prototype現在指向了同乙個物件,那麼任何對cat.prototype的修改,都會反映到animal.prototype。

所以,上面這一段**其實是有問題的。請看第二行

cat.prototype.constructor = cat;

這一句實際上把animal.prototype物件的constructor屬性也改掉了!

alert(animal.prototype.constructor); //

cat

四、 利用空物件作為中介

由於"直接繼承prototype"存在上述的缺點,所以就有第四種方法,利用乙個空物件作為中介。

var f = function

() {};  

f.prototype =animal.prototype;  

cat.prototype = new

f();  

cat.prototype.constructor = cat;

f是空物件,所以幾乎不佔記憶體。這時,修改cat的prototype物件,就不會影響到animal的prototype物件。

alert(animal.prototype.constructor); //

animal

我們將上面的方法,封裝成乙個函式,便於使用。

function

extend(child, parent) ;    

f.prototype =parent.prototype;    

child.prototype = new

f();    

child.prototype.constructor =child;    

child.uber =parent.prototype;  

}

使用的時候,方法如下

extend(cat, animal);  

var cat1 = new cat("大毛", "黃色");  

alert(cat1.species);

//動物

這個extend函式,就是yui庫如何實現繼承的方法。

另外,說明一點,函式體最後一行

child.uber = parent.prototype;

意思是為子物件設乙個uber屬性,這個屬性直接指向父物件的prototype屬性。(uber是乙個德語詞,意思是"向上"、"上一層"。)這等於在子物件上開啟一條通道,可以直接呼叫父物件的方法。這一行放在這裡,只是為了實現繼承的完備性,純屬備用性質。

五、 拷貝繼承

上面是採用prototype物件,實現繼承。我們也可以換一種思路,純粹採用"拷貝"方法實現繼承。簡單說,如果把父物件的所有屬性和方法,拷貝進子物件,不也能夠實現繼承嗎?這樣我們就有了第五種方法。

首先,還是把animal的所有不變屬性,都放到它的prototype物件上。

function

animal() {}  

animal.prototype.species = "動物";

然後,再寫乙個函式,實現屬性拷貝的目的。

function

extend2(child, parent)     

c.uber =p;  

}

這個函式的作用,就是將父物件的prototype物件中的屬性,一一拷貝給child物件的prototype物件。

使用的時候,這樣寫:

extend2(cat, animal);  

var cat1 = new cat("大毛", "黃色");  

alert(cat1.species);

//動物

js面試題 js的繼承

js是門靈活的語言,實現一種功能往往有多種做法,ecmascript沒有明確的繼承機制,而是通過模仿實現的,根據js語言的本身的特性,js實現繼承有以下通用的幾種方式 1.使用物件冒充實現繼承 該種實現方式可以實現多繼承 實現原理 讓父類的建構函式成為子類的方法,然後呼叫該子類的方法,通過this關...

整理 js經典小面試題

var str abcoefoxyozzopp var index str.indexof o 宣告變數,並且進行第一次查詢 var sum 記錄位置 var i 0 記錄次數 while index 1 console.log sum,i 處 var str abcoefoxyozzopp var...

經典面試題

1.以下三條輸出語句分別輸出什麼?char str1 abc char str2 abc const char str3 abc const char str4 abc const char str5 abc const char str6 abc cout boolalpha str1 str2 ...