原型和原型链
每个实例对象都有属性__proto__,指向其构造函数的特殊对象prototype。特殊对象prototype即为原型。当查找实例对象的属性或方法时:
-
先从其本身上查找
-
如果没有则从对象的
__proto__指向的prototype上查找 -
如果该
prototype上仍没有,则查找其__proto__指向的prototype,直到找到或__proto__指向的为null
__proto__指向的为null时即查找到了Object.prototype上
new操作符
const instance = new Constructor(props)
let instance = {}
instance.setPrototype(Constructor.prototype) // obj.__proto__ = Constructor.prototype
const res = Constructor.call(instance, props)
instance = res instanceOf Object ? res : instance
上述两段代码等价,即说明了new创建实例对象的四个步骤:
- 创建空对象
instance - 将
instance的__proto__指向构造函数的prototype - 调用构造函数并将其
this指向instance - 如果构造函数返回的值为对象,则将
instance赋值为该对象 new创建实例的结果即为instance
ES5继承
09年12月ES5发布,15年6月ES6发布,15年后的ECMAScript统称为ES6
function SuperClass(props) {
this.props = props
}
SuperClass.method1 = function() {
return 'method1'
}
SuperClass.prototype.superMethod = function() {
return this.props
}
function SubClass(subProps, superProps) {
this.subProps = subProps
SuperClass.call(this, superProps)
}
Object.setPrototypeOf(SubClass.prototype, SuperClass.prototype)
// 继承 method1 这种写法的方法和属性,等同于静态方法和静态属性
Object.setPrototypeOf(SubClass, SuperClass)
SubClass.prototype.subMethod = function() {
return this.subProps
}
const subInstance = new SubClass(subProps, superProps)
继承的目的为代码和逻辑的复用。不同于其他语言中的继承,js实现代码复用的方式为借用父类的构造函数和将子类prototype对象的__proto__指向父类的prototype。
ES6继承
class SuperClass {
// 静态属性 和 静态方法也会被继承
static staticProp = 'staic prop'
static staticMethod() {
return 'static method'
}
// 私有属性 和 私有方法不会被继承
#privateProp = 'private prop'
#privateMethod() {
return 'private method'
}
constructor(props) {
// 虚基类
if(new.target === SuperClass) {
throw new Error('该类不能被实例化')
}
this.props = props
}
superMethod() {
return this.props
}
}
class SubClass extends SuperClass {
// 静态属性,静态方法
static count = 0
static inc() {
this.count++
}
// 私有属性,私有方法
#privateProperty = 'private'
#privateMethod() {
return 'private method'
}
// 构造函数
constructor(superProps, subProps) {
SubClass.inc()
super(superProps) // 调用super后才能使用this
this.subProps = subProps
}
subMethod() {
return this.subProps
}
// getter
get props() {
return this.subProps
}
// setter
set props(val) {
this.subProps = val
}
}
super在类内可以
ES6中的类的内部所有定义的方法,都是不可枚举的
ES6继承是ES5的语法糖