JavaScript如何实现继承
- 借助call来进行继承
下面展示一些 内联代码片
。
function Parent(name, age) {
this.name = name;
this.age= age;
this.arr = [1, 2, 3]
this.howold= function () {
console.log(`我${this.age}岁了!`)
}
}
Parent.prototype.run = function () {//原型对象上的方法
console.log('I can run fast')
}
function Child(name, age color) {
Parent.call(this, name, size)
this.color = color
}
let child= new Child('小明', 18, '白色')
console.log(child.name)
console.log(child.arr)
child.howold()//我18岁了!
child.run()//报错 无此方法
通过call方法改变this指向的方式可以继承父构造函数的属性值和方法, 但是继承不到父类原型上面的方法
- (结合1)借助原型链实现原型对象上的继承
同样以上面为例
function Child(name, age color) {
Parent.call(this, name, size)
this.color = color
}
Child.prototype = new Parent()
let child= new Child('小明', 18, '白色')
console.log(child.name)
child.howold()//我18岁了!
child.run()//I can run fast
这样便实现对父构造函数原型对象上方法与属性的继承(这就是组合继承)
- 组合继承优化
以上组合继承还存在一点问题,就是我们在继承的过程中Parent()构造函数会多执行一次,我们不应该让他执行,解决方法就是直接将构造函数原型赋值给子构造函数。
function Child(name, age color) {
Parent.call(this, name, size)
this.color = color
}
Child.prototype = Parent.prototype
let child= new Child('小明', 18, '白色')
console.log(child.name)
child.howold()//我18岁了!
child.run()//I can run fast
这样看似没有问题,但其实我们直接改变了子构造函数的原型对象同时,也将原型对象的constructor属性直接指向是父类的构造函数 这是不对的
console.log(Child.prototype.constructor)// Parent()
- 组合继承最终版
进一步优化是 要改变子构造函数原型对象上的constructor属性
或许我们可以直接这样改变将此时的子类 Child.prototype.constructor = Child
但是直接这样修改 也会修改掉父类Parent中的constructor属性 这是不好的
所以我们要通过 子类.prototype=Object.create(父类.prototype)来继承
Object.create会根据现有的对象来提供新创建的对象的__proto__,即做了一层隔离的保护
再进行 子类.prototype.constructor = 子类构造函数的赋值
function Child(name, age color) {
Parent.call(this, name, size)
this.color = color
}
//Child.prototype = Parent.prototype
Child.prototype =Object.create(Parent.prototype)
Child.prototype.constructor = Child
let child= new Child('小明', 18, '白色')
console.log(child.name)
child.howold()//我18岁了!
child.run()//I can run fast
console.log(Child.prototype.constructor)// Child()
总结
在使用构造函数进行继承的过程中,首先要考虑继承父类本身属性方法的同时还要考虑其原型链上的方法,而在原型链继承的方法中也要考虑到直接改变子类原型对象带来的问题,便是子类原型对象上的constructor指向问题。
所以采用这种借助call和原型链继承的组合继承是实现JavaScript继承的一种方式