function Parent(){} // 定义父类构造器
function Children(){} // 定义子类构造器
let ChildPrototype = Children.prototype // 构造器原型
let ChildPrototypeProto = Children.prototype.__proto__ // 构造器原型的对象原型
// 方法一
ChildPrototypeProto = Parent.prototype // 父类构造器原型作为子类构造器原型(ChildPrototype)的对象原型(ChildPrototypeProto)
//方法二
ChildPrototype = Object.create(Parent.prototype) // Object.create返回一个对象,其__proto__指向传入的参数,也就实现返回的对象继承参数对象
//方法三
Object.setPrototypeOf(ChildPrototype, Parent.prototype) // 直接设置参数1的原型(__proto__)为参数2
复制代码
以上仅实现了原型之间的继承
function Parent() {} // 定义父构造函数
function Children() {} //定义子构造函数
// 定义父构造函数的静态方法
Parent.foo = function () {
console.log(this.name)
}
// 方法一
Children.__proto__ = Parent // 子构造函数的对象原型指向父构造函数,也就实现继承
// 方法二
Object.setPrototypeOf(Children, Parent) // 同原型继承
console.log(Children.foo) // function(){ console.log(this.name) } ,实现继承
复制代码
以上即为构造函数之间通过对象原型继承静态属性,注:函数也是对象
// 定义父构造函数
function Parent(name) {
this.name = name
}
//定义子构造函数
function Children(name,age) {
Parent.call(this,name) // 这里调用父构造器,实现实例属性继承
this.age = age
}
const obj = new Children('tom', 5)
console.log(obj) // {name: 'tom', age: 5} ,实现实例属性继承
复制代码
通过实例属性继承,可以把父构造器中默认生成的实例属性追加到子构造器实例化出来的对象上
综合以上继承,现在实现真正的继承
// 定义父构造函数,功能:初始化实例name属性
function Parent(name) {
'use strict'
this.name = name
}
// 定义父构造函数的静态方法,功能:设置调用对象的name属性
Parent.setName = function setName(obj, name) {
obj.name = name
}
// 定义父构造器原型(prototype)的方法,功能:获取调用对象的name属性
Parent.prototype.getName = function getName() {
return this.name
}
/*-----以上已定义父类的原型方法(获取name),父类静态方法(设置name),以及构造器默认初始化的属性name------*/
// 定义子构造函数,功能:初始化实例age属性,以及通过父构造器初始化实例name属性
function Children(name, age) {
'use strict'
Parent.call(this, name) // 调用父构造器,初始化name属性
this.age = age // 子构造器初始化age属性
}
// 定义子构造函数的静态方法,功能:设置调用对象的age属性
Children.setAge = function setAge(obj, age) {
obj.age = age
}
// 原型继承
// 设置Children.prototype['[[Prototype]]']= Parent.prototype,此处的'[[Prototype]]'与设置__proto__相同
Children.prototype = Object.create(Parent.prototype)
// 注意此处原型继承之后,不带有constructor属性,应该手动指明为Children
Object.defineProperty(Children.prototype, 'constructor', {
value: Children,
writable: true, // 可写
enumerable: false, // 不可枚举
configurable: true, // 可配置
})
//以上2句可以直接写成一句
/*
Children.prototype = Object.create(Parent.prototype, {
constructor: {
value: Children,
writable: true, // 可写
enumerable: false, // 不可枚举
configurable: true, // 可配置
}
})
*/
// 由于子构造器原型方法必须在继承之后再定义,否则会被继承覆盖
// 定义子构造器原型(prototype)的方法,功能:获取调用对象的age属性
Children.prototype.getAge = function getAge() {
return this.age
}
// 构造函数(继承静态属性)继承
// 设置Children.__proto__ = Parent,注意此处不能使用Children = Object.create(Parent),因为Object.create返回的是一个对象不能替换构造函数
Object.setPrototypeOf(Children, Parent)
// 测试父级
const obj = new Parent('tom') // 实例化父级实例
console.log(obj.getName()) // tom
Parent.setName(obj, 'jerry') // 通过父级静态方法设置name
console.log(obj.getName()) // jerry
console.log(obj instanceof Parent) // true
// 测试子级
const obj1 = new Children(null, 5) // 实例化子级实例
console.log(obj1.getAge()) // 5
Children.setAge(obj1, 8) // 通过子级静态方法设置age
console.log(obj1.getAge()) // 8
console.log(obj1 instanceof Parent) // true
console.log(obj1 instanceof Children) // true
// 完整测试继承
const test = new Children('tom', 5) // 实例化子级实例,name='tom',age=5
console.log(test.getName()) // tom
Parent.setName(test, 'jerry') // 通过父级静态方法设置name=jerry
console.log(test.getName()) // jerry
console.log(test.getAge()) // 5
Children.setAge(test, 8) // 通过子级静态方法设置age=8
console.log(test.getAge()) // 8
class P {
constructor(name) {
this.name = name
}
static setName(obj, name) {
obj.name = name
}
getName() {
return this.name
}
}
class C extends P {
constructor(name, age) {
super(name)
this.age = age
}
static setAge(obj, age) {
obj.age = age
}
getAge() {
return this.age
}
}
// 这里就不带测试了,可以自行验证,比对一下有什么区别
console.dir(Children)
console.dir(C)
复制代码
实现继承,需要对原型、构造器、实例属性都加以实现继承