1. 程式人生 > >js中實現繼承的不同方式以及其缺點

js中實現繼承的不同方式以及其缺點

但是 scrip UC .proto 就是 圖片 問題 inf 引用

1.利用call和apply,借助構造函數

fucntion P(){
  this.name = "P";  
}
fucntion C1(){
  P.call(this);
}

  解釋一下,P.call(this)的意思,就是將P的上下文指向C的上下文。

  那麽,什麽是上下文呢,比如說,我有一把菜刀,可以用來殺豬,那麽這裏我就是菜刀的上下文。你沒有,但是有一天你也要去殺豬,怎麽辦,最簡單的方式就是向我借,而不是自己去買,向我借就是說菜刀的上下文被指給你了。

  call函數和apply都是用來指定上下文的,但是call後面可以傳遞多個參數,而apply只能用來傳遞一個參數(也可以多個,不過要寫成數組的形式)

技術分享圖片
技術分享圖片

  好,第一種方式解決了。但是第一種方法是有缺點的,就是子類只能繼承構造函數裏面的東西,而父類的原型函數上是繼承不到的。

2.借助原型鏈

fucntion P(){
  this.name = "P";  
}
fucntion C2(){
}
C2.prototype = new P();
var c2 = new C2();

最後一句話的意思,就是將P實例成一個實例對象,然後,將這個對象作為子類的原型對象。

這種方法使用了原型鏈,但是由於直接綁定了原型函數,導致了一些問題。

fucntion P(){
  this.name = "P";  
}
fucntion C2(){
}
C2.prototype = new P() 
var s1 = new C2();
var s2 = new C2();
//這裏,如果我們修改s1的東西
s1.name = "PPPP";
console.log(s2.name);//結果是 PPPP

原因是啥,因為s1和s2都是引用的同樣的原型對象,所以,當s1的值修改,實際上就是修改了原型對象的值,因此,s2的值也會修改。很明顯,這種方法是很不好的。

3.構造函數+原型鏈(組合方式)

fucntion P(){
  this.name = "P";  
}
fucntion C3(){
    P3.call(this);
}
C3.prototype = new P();//2
var c3 = new C3();//1

   將兩種方法的優點結合起來,這就是我們通常的方法。

實際上,這麽寫,有點小問題,實例化了兩次對象(代碼中表明了),浪費內存。

優化方式,直接在原型對象層面上進行就可以了,在//2的位置

C2.prototype = P.prototype

  ES6中的方法以後再看。

js中實現繼承的不同方式以及其缺點