javascript 原型式继承
1. javascript 类的继承的特点
javascript 类的继承的 3 个特点(如下),其中第 1 点是 javascript 特有。
- 父类重写公共属性(方法)影响子类属性(方法)。
- 子类可以自定义继承父类构造方法,扩展额外属性和方法。
- 相对java,能动态修改构函数的方法或属性(包括原型)
- 修改非原型链上的属性(方法),不影响其他构造函数(类)。修改原型链上属性(方法),会影响其他构造函数,即原型上的引用属性共享。
es5 和 es6 的类(构造函数)本质上没区别,只是es6在语法糖上方便。
2. es5 的继承
es5 继承最主要的原型式继承方法,对应实现继承的函数执行的js分为 4 个步骤:
- 创建一个中间的构造函数Fn,
Fn.prototype = Super.prototype
。 - 实例化 Fn 为
var fn = new Fn()
,将Child.prototype = fn
。 - 将
Child.prototype.constructor = Child
。 - 在
Child
构造函数中封装一个super
方法,来继承父类里的构造函数。
ps:当然步骤 1 和 2 可用 Object.create()
来替代。
代码如下:
// 继承
function _extends (Sup, Sub) {
var Fn = function () {}
Fn.prototype = Sup.prototype
var fn = new Fn()
Sub.prototype = fn
// Sub.prototype = Object.create(Sup.prototpye)
// Sub.prototype.constructor = Sub
}
// 设置非原型类上的实例属性的值
function _super (Sup, Sub) {
var args = []
if (arguments.length > 1) {
args = Array.prototype.slice.call(arguments, 2)
}
Sup.apply(Sub, args)
}
function Sup (name) {
this.name = name
this.address = {
city: '上海'
}
}
Sup.prototype.pet = {
name: '旺财'
}
function Sub (name) {
_super(Sup, this, name)
}
_extends(Sup, Sub)
var parent = new Sup('父亲')
var child = new Sub('孩子')
console.log('====> es5 start')
child.name = '女儿'
console.log('设置child.name=女儿')
console.log('child.name =', child.name) // 女儿
console.log('parent.name =', parent.name) // 父亲
parent.pet.name = '大黄'
console.log('设置parent.pet.name=大黄')
console.log('parent.pet.name', parent.pet.name) // 大黄
console.log('child.pet.name', child.pet.name) // 大黄,说明原型上的引用属性共享
parent.address.city = '北京'
console.log('设置parent.address.city=北京')
console.log('parent.address.city', parent.address.city) // 北京
console.log('child.address.city', child.address.city) // 上海
console.log('====> es5 end')
3. es6 继承示例
class Sup {
// 这里 pet 属性不是在原型链上
pet={
name: 'mack'
};
constructor (name) {
this.name = name
}
say () {
console.log(`my name is ${this.name} and my pet's name is ${this.pet.name}`)
}
changePetName (name) {
this.pet.name = name
}
}
/* eslint-disabled */
class Sub extends Sup {}
const parent = new Sup('父亲')
const son = new Sub('儿子')
console.log('====> es6 start')
console.log('parent', parent)
console.log('son', son)
// 修改父亲宠物的名字
parent.changePetName('jack')
console.log('设置parent.pet.name=jack')
parent.say() // jack
son.say() // mack
console.log('====> es6 end')
转载自:https://juejin.cn/post/6844903817897574414