javascript继承的几种方法
继承是面向对象编程中很重要的概念,在其它面向对象的语言中大都很简单,例如java中有关键词extends来实现
javascript语言在ES6也新增了extends关键词可以实现继承,用法与java其实大同小异:
class Animal { constructor(props) { this.name = props.name } eat(){ console.log(`${this.name} 要吃东西`) } } class Dog extends Animal { constructor(props) { //调用实现父类的构造函数 super(props); this.type = props.type } run(){ console.log(`${this.name}要跑了`) } } const xiaobao = new Dog({name:"xiaobao"}) console.log(xiaobao.eat(),xiaobao.run())
如果不用class 和extends关键词呢?
要实现继承,那么首先要定义一个被继承的父类:
function Animal(name){ this.type = "Animal" this.array = [1,2,3] } Animal.prototype.eat = function(type){ console.log(this.name +"喜欢吃"+type) }
1.构造函数
利用call/apply方法改变函数上下文实现继承,这种办法有很明显的缺点:不能继承父类的原型的属性或方法
function Dog(name){ Animal.call(this) this.type = "dog" this.name = name } var xb = new Dog("小宝") xb.type // dog xb.array // [1,2,3] xb.eat('骨头') // Uncaught TypeError: (intermediate value).eat is not a function
2.原型链
使子类原型对象指向父类的实例以实现继承,缺点是会共用原型,不能多继承,当有多个实例时数据会共通,这当然不是我们想要的。
function Dog(name){ this.type="dog" this.name = name } Dog.prototype = new Animal() var xb = new Dog("小宝") var dd = new Dog("点点") xb.array // [1,2,3] dd.array // [1,2,3] xb.array.push(4) xb.array // [1,2,3,4] dd.array // [1,2,3,4]
3.组合继承
调用父类构造函数,再使子类原型对象指向父类的实例,缺点是会调用两次父类构造函数
function Dog(name){ Animal.call(this) this.type="dog" this.name = name } Dog.prototype = new Parent3()
4.组合继承--优化版
将子类的原型指向父类的原型的对象(将父类的原型用Object.create()处理下,将子父的构造函数隔离开,没有这一步将会造成父类的构造函数被覆盖),再修复constructer,将子类构造函数赋给子类的原型的构造函数。
function Dog(name){ Animal.call(this) this.type="dog" this.name = name } Dog.prototype = Animal.prototype Dog.prototype = Object.create(Animal.prototype) Dog.prototype.constructor = Dog
后面两种方式推荐使用,没有什么明显的缺点。