1、繼承的概念:javascript
繼承的概念能夠分爲兩個層面,一是子類能夠擁有父類的一部分或所有屬性或方法,二個子類還能夠有本身的一些屬性和方法。java
2、繼承實現的機制編程
在javascript中實現繼承的核心機制就是 -- 原型鏈app
既然的這裏提到原型鏈,就不得不說一下javascript中的原型鏈是怎麼回事。框架
一個構造函數由構造函數自己和構造函數的原型對象兩個部分組成(雙對象法則) ,也就是構造函數有一個隱藏的屬性__proto__,指向構造函數的原型對象。當構造函數被實例化時,把構造函數中的全部屬性和方法拷貝到實例當中,同時,這個__proto__屬性也會被拷貝,當訪問實例對象當中的屬性或方法時,會先從實例自己找,若是找到了,就會使用實例中的這個屬性或方法;若是沒有找到,就會經過__proto__屬性中保存的地址找到原型對象,再從原型對象裏找這個屬性或方法。函數
當給一個實例對象設置屬性值時,會在實例對象中找有沒有這個屬性,若是找到,就直接把值賦給這個屬性;若是沒有的話,不會再去原型對象中找該屬性,由於javascript語言是一種動態語言,這時會直接給這個實例對象添加一個新的屬性,即便原型對象中有這個屬性,也不會改變原型對象中的這個值。this
當實例對象中和原型對象中有一個同名的屬性和方法時,此時只能訪問到實例對象中的屬性或方法(屏蔽法則),若是必定要訪問,能夠delete掉實例中的屬性或方法,或都直接加上__proto__屬性訪問。spa
以上就是原型鏈的核心機制,屬性搜索機制。prototype
javascript語言在最初的時候並非一門面向對象的語言,後期因爲使用javascript語言的人越來截止多,再加上面向對象編程的種種好處,javascript利用原型鏈機制,間接的實現了繼承。code
3、實現繼承的幾種方式
一、借用構造函數實現繼承
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方法借用父類構造函數實現繼承,這種方法有一個缺點就是隻能繼承構造函數裏的屬性或方法,沒法繼承到原型對象裏定義的方法。
二、原型鏈繼承
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();
以上代碼經過讓子類的原型對象等於父類的一個實例,以實現繼承,這種方法能夠徹底繼承父類的所有方法和屬性,可是不能經過傳參的形式實例化對象,全部就有了第三種實現繼承的方式 ,組合繼承
三、組合繼承
組合繼承是同時使用了上面兩種方法來實現繼承,代碼以下
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();
組合繼承完美實現了繼承父類的全部方法和屬性,此時若是再想給子類的原型對象添加一些方法的話,只能使用.語法的形式(或者使用[]),還有一個缺點是使用子類實例化對象時,會在實例對象和原型對象中重複定義父類構造函數中的屬性或方法。
四、使用第三方框架實現繼承
能夠實現繼承的第三方框架有不少,實現方式也都大同小異,能夠參照各框架的源碼或API,這裏再也不贅述。