Javascript實現物件導向繼承

751371041發表於2020-11-23

Javacript繼承實現

原型鏈

在這裡插入圖片描述

實現繼承

子類建構函式呼叫時同時呼叫父類建構函式,並將父類建構函式作用域的this指向子類建構函式的this

  <script>
        //子類建構函式呼叫父類建構函式的繼承實現方法
function Super(){   //父類建構函式
    this.val = 1;
    this.arr = [1];
}
function Sub(){ //子類建構函式
    // 子類公共變數
    Super.call(this);//完成繼承,改變作用域指向
}  
var sub1 = new Sub();  //子類例項如果想要繼承父類的公共變數,只需要讓構造子類例項時呼叫父類建構函式,並將this指向新物件就可以了
console.log(sub1);
    </script>
  1. 原型鏈繼承
    使用父類例項物件充當子類的原型物件屬性
 <script>
        function Super(){ 
    this.val = 1;
    this.arr = [1];
}
function Sub(){
    // 子類公共變數
}  
Sub.prototype = new Super();    // 核心:拿父類例項來充當子類原型物件
var sub1 = new Sub();
var sub2 = new Sub();
sub1.val = 2;
sub1.arr.push(2);
console.log(sub1.val);    // 2,改了
console.log(sub2.val);    // 1,沒改,只能改自己的
console.log(sub1.arr);    // 1, 2改變了陣列
console.log(sub2.arr);    // 1, 2  

*問題
(1)繼承到了修改後的 來源是一個物件Object 值型別資料指向同一個陣列物件,一改全改不好用,有侷限性
(2)不能通過子類建構函式例項化修改父類的成員變數—不能向父類例項物件傳參

補充:建構函式例項化傳參

//方便修改

2.借用父類建構函式實現繼承
優化:可以向父類建構函式傳參的問題
不用同一個物件指向

    <script>
        // 實現向父類建構函式的傳參問題
        function Super(val){   //可以傳參
    this.val = val;
    this.arr = [1];
    this.fun = function(){}
}
function Sub(val){
    
    // 用了不同陣列,也實現了同一物件的混淆性
    Super.call(this, val);   // 核心:借父類的建構函式來增強子類例項(把父類的例項屬性複製了一份給子類例項裝上了)
    //this指的是例項化出來的物件
    // 子類公共變數
}
var sub1 = new Sub(1);
var sub2 = new Sub(2);
sub1.arr.push(2);
console.log(sub1.val);    // 1
console.log(sub2.val);    // 2
console.log(sub1.arr);    // 1, 2   //子類物件型資料不再公用
console.log(sub2.arr);    // 1
alert(sub1.fun === sub2.fun);   // false
    </script>

存在的問題:
例項方法一對一冗餘
3.組合式繼承

最常用的

把例項函式都放在原型物件上
*考慮相容性的情況下

<script>
        // 考慮相容性
        function Super(val){ // 只在此處宣告基本屬性和引用屬性
    this.val = val;
    this.arr = [1];
}
//函式寫在原型物件上
Super.prototype.fun1 = function(){}; //  在此處宣告函式
Super.prototype.fun2 = function(){}; //  把例項函式都放在原型物件上
//其他原型物件上的方法
function Sub(val){
    Super.call(this,val);   // 核心,保留借用建構函式方式的優點,讓子類繼承父類的基本屬性和引用屬性
    // 子類公共變數
}
Sub.prototype = new Super();    // 核心,子類繼承父類函式,實現函式複用
var sub1 = new Sub(1);
var sub2 = new Sub(2);
console.log(sub1.fun1 === sub2.fun1);   // true   共用同一個函式
    </script>

*宣告函式啥都不發生,僅宣告
子類的屬性:自己的+原型鏈得來的 val,arr,fun1,fun2------查詢時候先找自己的再找原型鏈的
瑕疵:同樣屬性給兩份,浪費了記憶體

4.寄生組合式繼承
*解決記憶體浪費問題
完美但不常用

 <script>
        function beget(obj){ // 生孩子函式,返回一個將引數物件作為原型物件的函式的例項
    var F = function(){};
    F.prototype = obj;
    return new F();//物件的構造器
}
function Super(){ // 只在此處宣告基本屬性和引用屬性
    this.val = val;
    this.arr = [1];
}
Super.prototype.fun1 = function(){}; //  在此處宣告函式
function Sub(){
    Super.call(this);   // 核心,保留借用建構函式方式的優點,讓子類繼承父類的基本屬性和引用屬性
    // 獲取父類的成員變數
}
var proto = beget(Super.prototype); // 核心:用beget方法切掉了原型物件上多餘的那份父類例項屬性
proto.constructor = Sub;            // 核心:將子類建構函式賦予beget出的物件的constructor屬性
Sub.prototype = proto;              // 核心:將beget出的物件賦予子類建構函式的prototype屬性
var sub = new Sub();
console.log(sub.val);
console.log(sub.arr);
    </script>

!!! 轉載請註明出處

相關文章