關於javascript實現繼承的核心機制


一、繼承的概念:

  繼承的概念可以分為兩個層面,一是子類可以擁有父類的一部分或全部屬性或方法,二個子類還可以有自己的一些屬性和方法。

二、繼承實現的機制

  在javascript中實現繼承的核心機制就是 -- 原型鏈

  既然的這里提到原型鏈,就不得不說一下javascript中的原型鏈是怎么回事。

  一個構造函數由構造函數本身和構造函數的原型對象兩個部分組成(雙對象法則) ,也就是構造函數有一個隱藏的屬性__proto__,指向構造函數的原型對象。當構造函數被實例化時,把構造函數中的所有屬性和方法拷貝到實例當中,同時,這個__proto__屬性也會被拷貝,當訪問實例對象當中的屬性或方法時,會先從實例本身找,如果找到了,就會使用實例中的這個屬性或方法;如果沒有找到,就會通過__proto__屬性中保存的地址找到原型對象,再從原型對象里找這個屬性或方法。

  當給一個實例對象設置屬性值時,會在實例對象中找有沒有這個屬性,如果找到,就直接把值賦給這個屬性;如果沒有的話,不會再去原型對象中找該屬性,因為javascript語言是一種動態語言,這時會直接給這個實例對象添加一個新的屬性,即使原型對象中有這個屬性,也不會改變原型對象中的這個值。

  當實例對象中和原型對象中有一個同名的屬性和方法時,此時只能訪問到實例對象中的屬性或方法(屏蔽法則),如果一定要訪問,可以delete掉實例中的屬性或方法,或都直接加上__proto__屬性訪問。

  以上就是原型鏈的核心機制,屬性搜索機制。

  javascript語言在最初的時候並不是一門面向對象的語言,后期由於使用javascript語言的人越來截止多,再加上面向對象編程的種種好處,javascript利用原型鏈機制,間接的實現了繼承。

三、實現繼承的幾種方式

  1、借用構造函數實現繼承

 1 //定義一個父類構造函數
 2 function Person(name,age,gender) {
 3     this.name = name;
 4     this.age = age;
 5     this.gender = gender;
 6 }
 7 Person.prototype = {
 8     run: function() {
 9         console.log(this.name + " is running");
10     }
11 }
12 //定義子類構造函數
13 function Student (name,age,gender,id,grade) {
14     //使用apply方法借用父類構造函數,實現繼承
15     Person.apply(this,arguments);
16     this.id = id;
17     this.grade = grade;
18 }
19 Student.prototye = {}

  以上代碼通過使用apply方法借用父類構造函數實現繼承,這種方法有一個缺點就是只能繼承構造函數里的屬性或方法,無法繼承到原型對象里定義的方法。

  2、原型鏈繼承

 1 // 定義父類構造函數
 2 function Person(name,age,gender) {
 3     this.name = name;
 4     this.age = age;
 5     this.gender = gender;
 6 }
 7 //父類原型對象
 8 Person.prototype = {
 9     run: function() {
10         console.log(this.name + " is running");
11     }
12 }
13 //定義子類構造函數
14 function Student (name,age,gender,id,grade) {
15     this.id = id;
16     this.grade = grade;
17 }
18 //手動將子類構造函數,指向父類構造函數的一個實例,實現繼承 
19 Student.prototype = new Person();

  以上代碼通過讓子類的原型對象等於父類的一個實例,以實現繼承,這種方法可以完全繼承父類的全部方法和屬性,但是不能通過傳參的形式實例化對象,所有就有了第三種實現繼承的方式 ,組合繼承

3、組合繼承

  組合繼承是同時使用了上面兩種方法來實現繼承,代碼如下

 1  // 定義父類構造函數
 2 function Person(name,age,gender) {
 3     this.name = name;
 4     this.age = age;
 5     this.gender = gender;
 6 }
 7 //父類原型對象
 8 Person.prototype = {
 9     run: function() {
10         console.log(this.name + " is running");
11     }
12 }
13  //定義子類構造函數
14 function Student (name,age,gender,id,grade) {
15   //使用apply方法借用父類構造函數,實現繼承
16     Person.apply(this, arguments);
17     this.id = id;
18     this.grade = grade;
19 }
20  //手動將子類構造函數,指向父類構造函數的一個實例,實現繼承
21 Student.prototype = new Person();

  組合繼承完美實現了繼承父類的所有方法和屬性,此時如果再想給子類的原型對象添加一些方法的話,只能使用.語法的形式(或者使用[]),還有一個缺點是使用子類實例化對象時,會在實例對象和原型對象中重復定義父類構造函數中的屬性或方法。

 4、使用第三方框架實現繼承

  可以實現繼承的第三方框架有很多,實現方式也都大同小異,可以參照各框架的源碼或API,這里不再贅述。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM