JavaScript繼承的六種方式

JavaScript繼承的六種方式

我覺得有些地方我可能理解的不是很到位,如果我下文有出現錯誤直接提出,謝謝~

另外可以看看這兩篇文章:

https://www.cnblogs.com/humin/p/4556820.html

https://www.cnblogs.com/Grace-zyy/p/8206002.html

繼承就是讓子類擁有父類的資源

繼承的意義

​ 減少代碼冗餘

​ 方便統一操作

​ 弊端

​ 耦合性比較強

繼承方法

	// 父類    
	function Person() {
       this.name = 'cc';
       this.pets = ['aa', 'bb'];
    }

    Person.prototype.run = function () {
        console.log('跑');
    };

1. 原型鏈繼承

核心:將父類的實例作爲子類的原型

    // 子類        
    function Student() {
        this.num = '111';
    }
	// 讓新實例的原型等於父類的實例
    Student.prototype = new Person();

    var stu = new Student();
    console.log(stu.num); // 111
    stu.run(); // 跑

	// 問題:類型問題
	console.log(stu.constructor.name); //Person  對象類型改變

優化:修復constructor指針

    // 子類        
    function Student() {
       this.num = '111';
    }

    Student.prototype = new Person();
    // 修復constructor指針即可
    Student.prototype.constructor = Student;

    var stu = new Student();
    console.log(stu.num);   // 111
    stu.run(); 				// 跑
    console.log(stu.pets);  // ["aa", "bb"]
    console.log(stu.constructor.name);  // Student

	// 問題:繼承過來的實例屬性, 如果是引用類型, 會被多個子類的實例共享
	var stu1 = new Student();
    stu.pets.push('dd');
    console.log(stu.pets);		// ["aa", "bb", "dd"]
    console.log(stu1.pets);		// ["aa", "bb", "dd"]

2. 借用構造函數繼承

核心:在子類型構造函數的內部調用父類構造函數,通過使用call()和apply()方法可以在新創建的對象上執行構造函數。

    // 子類        
    function Student() {
       Person.call(this);
       this.num = '111';
    }
	var stu = new Student();
    console.log(stu.name);   // 111

	// 問題:沒用到原型,只能繼承父類的實例屬性和方法,不能繼承原型屬性/方法
    stu.run(); 				// 報錯:stu.run is not a function

3. 組合繼承

核心: 將原型鏈和借用構造函數的技術組合在一塊,從而發揮兩者之長的一種繼承模式。(常用)

    // 子類        
    function Student() {
       Person.call(this);
       this.num = '111';
    }

    Student.prototype = new Person();
    Student.prototype.constructor = Student;

    var stu = new Student();
    var stu1 = new Student();
    stu.pets.push('小花');
    console.log(stu.pets); 		// ["aa", "bb", "小花"]
    console.log(stu1.pets); 	// ["aa", "bb"]

	// 問題:調用了兩次父類構造函數(耗內存)

4. 原型式繼承

核心:藉助原型,然後基於已有的對象, 創建出新對象;同時不需要創建自定義類型

用一個函數包裝一個對象,然後返回這個函數的調用,這個函數就變成了一個可以隨意增添屬性的實例或對象。object.create()就是這個原理。

// 原型式繼承
function content(obj) {
    function Temp() {}
    Temp.prototype = obj;
    return new Temp();
}
var p = new Person();
var stu1 = content(p);
console.log(stu1.name);
console.log(stu1.age);

5. 寄生式繼承

核心:在原型式基礎上增強這個對象。所謂增加, 就是指, 再次給這個對象增加一些屬性或者方法

    // 子類        
    function Student() {
       this.num = '111';
    }

    function Temp() {}
    Temp.prototype = new Person();
    Student.prototype = new Temp();
    Temp.constructor = Student;

    var stu = new Student();
    console.log(stu);

6. 寄生式組合繼承

核心:通過借用函數來繼承屬性,通過原型鏈的混成形式來繼承方法。(常用)

    // 子類
	function Student(num, name, pets) {
        Person.call(this, name, pets);
        this.num = num;
    }

    function Temp() {}
    Temp.prototype = new Person();
    Student.prototype = new Temp();
    Temp.constructor = Student;

	var stu = new Student('001', '張三', ['小花']);
    var stu1 = new Student('002', '李四', ['小茂']);
    console.log(stu);
    console.log(stu1);
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章