JS面试题5——JS继承有哪些方式
1. ES6
子类构造方法中必须调用super方法,且只有在调用了super()之后才能使用this。
因为子类的this对象是继承父类的this对象,然后对其加工,而super方法表示的是父类的构造函数,用来新建父类的this对象。
/* 此时的Child上只有name属性,没有age属性 */
<script>
// 父
class Parent{constructor(){this.age = 18;}
}
// 子
class Child{constructor(){this.name = '张三';}
}
let o1 = new Child();
console.log(o1, o1.name, o1.age); // 打印出:Child {name: '张三'} '张三' undefined
</script>
/* 此时的Child上既有name属性,又有age属性 */
<script>
// 父
class Parent{constructor(){this.age = 18;}
}
// 子
class Child extends Parent{constructor(){super();this.name = '张三';}
}
let o1 = new Child();
console.log(o1, o1.name, o1.age); // 打印出:Child {age: 18, name: '张三'} '张三' 18
</script>
2. 原型链继承
优点:写法方便简洁,容易理解
缺点:对象实例共享所有继承的属性和方法,无法向父类构造函数传参
<script>
// 父
function Parent() {this.age = 20;
}
// 子
function Child() {this.name = '李四';
}
Child.prototype = new Parent()
let o1 = new Child();
console.log(o1, o1.name, o1.age); // 打印出:Child {name: '李四'} '李四' 20
</script>
3. 借用构造函数继承
优点:解决了原型链继承中不能传参的问题以及父类的原型共享的问题
缺点:方法都在构造函数中定义,无法实现函数复用;在父类的原型中定义的方法,对子类而言是不可见的,结果所有类型都只能使用构造函数模式。
<script>
// 父
function Parent(){this.age = 22;
}
// 子
function Child(){this.name = 'xiongxinyu';Parent.call(this); // 改变this指向
}
let o3 = new Child();
console.log(o3,o3.name,o3.age); // 打印出:Child {name: 'xiongxinyu', age: 22} 'xiongxinyu' 22
</script>
4. 组合式继承
优点: 解决了原型链继承和借用构造函数继承造成的影响
缺点:无论在什么情况下,都会调用两次父类构造函数(一次是在创建子类原型的时候,一次是在子类构造函数内部)
<script>
// 父
function Parent(){this.age = '24'
}
// 子
function Child(){Parent.call(this)this.name = 'y'
}
Child.prototype = new Parent();
var o4 = new Child();
console.log(o4,o4.name,o4.age); // 打印出:Child {age: '24', name: 'y'} 'y' '24'
</script>