繼承,是面向對象的,通過繼承,我們更好的服用以前的代碼,提升開發的效率和縮短開發的周期
其實,繼承就是讓子類具有父類的各種方法和屬性,而不需要在子類中重新定義和父類一樣的方法和屬性。當然,在子類中是可以定義一些父類本身沒有的屬性和方法的。繼承在程式設計中并不難了解。
- 那麼在JavaScript中的繼承,有多少中方式呢?
- es6的extends關鍵字使用了哪一種繼承方式呢?
第一種繼承方式:原型鍊繼承
在原型鍊繼承裡涉及到構造函數、原型和執行個體;
構造函數都有一個原型對象,而原型對象又包含了一個指向構造函數的指針。
如下代碼:
function SuperType() {
this.name = "duxinyue"
this.property = "SuperType";
}
SuperType.prototype.getSupertyValue = function () {
return this.property;
}
function SubType() {
// this.name = "qingzhuyue"
this.subproperty = "SubType";
}
// 繼承SuperType
SubType.prototype = new SuperType();
SubType.prototype.getSubValue = function () {
return this.subproperty;
}
const instance = new SubType();
const instance1 = new SuperType();
instance1.name = "鍍鋅不得不"
console.log(instance.getSupertyValue()); // SuperType
console.log(instance.getSubValue());
console.log(instance.name);
console.log(instance1.name);
第二種方式:構造函數繼承(借助call)
function Parent1() {
this.name = "讀心悅";
}
Parent1.prototype.getName = function () {
return this.name;
}
function Child1() {
Parent1.call(this);
this.type = "child1";
}
const child1 = new Child1();
console.log(child1); // { name: '讀心悅', type: 'child1' }
console.log(child1.getName()) // child1.getName is not a function
在構造函數繼承中,child1繼承了Parent的那麼屬性。但是Parent原型對象上的方法卻沒辦法繼承。
第三種方式:組合繼承(原型繼承和構造函數繼承的組合)
function Parent(){
this.name = "duxinyue";
this.play = [1,2,3];
}
Parent.prototype.getName = function(){
return this.name;
}
function Child(){
Parent.call(this)
this.type = "child3"
}
Child.prototype = new Parent();
// 指向自己的構造函數
Child.prototype.constructor = Child;
// 構造函數繼承(借助call)
const c1 = new Child();
const c2 = new Child();
c1.play.push(5);
console.log("c1==",c1);
console.log("c2==",c2);
console.log(c1.getName())
console.log(c2.getName())
第四種方式:原型式繼承
Object.create(),接受兩個參數,第一個參數是作為新對象原型的對象,第二個參數是新對象定義額外的屬性的對象。
const parent = {
name:"讀心悅",
play:[1,2,3,4],
getName:function(){
return this.name;
}
};
console.log(parent.getName());
const p0 = Object.create(parent);
p0.name = "青竹悅";
p0.play.push(90);
console.log(p0.name);//青竹悅
console.log(p0.play);//[ 1, 2, 3, 4, 90 ]
const p1 = Object.create(parent);
console.log(p1.name);//讀心悅
console.log(p1.play);//[ 1, 2, 3, 4, 90 ]
console.log(p0.play === p1.play); // true
第五種方式:寄生式繼承
const parent1 = {
name:"duxinyue",
play:[1,2,3],
getName:function(){
return this.name;
}
}
function clone(original){
const clone = Object.create(original);
clone.getPlay = function(){
return this.play;
}
return clone;
}
const p2 = clone(parent1);
const p3 = clone(parent1);
p2.play.push(100)
console.log(p2.getName()); // duxinyue
console.log(p2.getPlay()); // [ 1, 2, 3, 100 ]
console.log(p3.play);//[ 1, 2, 3, 100 ]
寄生組合繼承
function clone(parent,child){
child.prototype = Object.create(parent.prototype);
child.prototype.constructor = child;
}
function Parent5(){
this.name = 'duxinyue';
this.play = [1,2,3];
}
Parent5.prototype.getName = function(){
return this.name;
}
function Child5(){
Parent5.call(this);
return type = "child5";
}
clone(Parent5,Child5);
Child5.prototype.getPlay = function(){
return this.play;
}
let person1 = new Child5();
let person2 = new Child5();
person2.name = "kkk"
console.log(person1);// { name: 'duxinyue', play: [ 1, 2, 3 ] }
console.log(person2); // { name: 'kkk', play: [ 1, 2, 3 ] }