原型与继承
关于js继承及其相关
小思考
Function.prototype
是空函数:先要知道为什么:
Function.prototype.__proto__ === Object.prototype
一切的始祖为
null
,null
创造了Object.prototype
。之后Object.prototype
创造了Function.prototype
。之后和函数相关的让Function.prototype
去干,而原型相关的由Object.prototype
自己干。如果函数还是对象那一套原型链,构造函数的原型链会不好处理。因此所有函数的原型都是
Function.prototype
,即空函数1
2
3
4
5String.__proto__
Object.__proto__
Number.__proto__
Function.__proto__
functionXX.__proto__而所有对象就是正常的原型链
Object.constructor
就是Function.constructor
,因此Object
与Function
互为对方的实例
组合继承:
借用构造函数实现实例属性继承
在子类构造函数中:
父构造函数.call(this, 传参)
1
2
3function SubType(){
Sup.apply(this, arguments)
}赋值父实例给子构造函数原型实现原型属性和方法继承
1
2SubType.prototype = new SuperType;
SubType.prototype.constructor=SubType;
寄生组合继承:
借用构造函数实现继承实例属性方法,同组合继承一样
封装继承过程函数的方法子类原型继承父类原型,相当于浅拷贝父类的原型对象,不必调用两次父构造函数,是引用类型最理想的继承方式。
避免组合继承调用两次构造函数
1
2
3
4
5
6
7function inherit (subClass, supClass){
//拷贝父类的原型
var pro = Object.create(supClass.prototype)
pro.constructor = subClass
subClass.prototype = pro
}
inherit(Sub, Sup)
es6的
extends
继承:1
2
3
4
5
6
7
8
9
10class Sub extends Sup {
constructor(){
super('子') //调用父类构造函数并传参
this.n = '儿子' //实例属性
}
sayN (){ //原型中的方法
console.log(this.n)
}
static sayNN(){} //静态方法,不能被实例调用,只能构造函数调用。切静态方法中的this指构造函数不是实例
}extends内部做了如下操作:
- 把子类构造函数(
Child
)的原型(__proto__
)指向了父类构造函数(Parent
),(寄生组合继承没有这一条,猜测因此extends继承实现继承父类的静态方法) - 把子类实例
child
的原型对象(Child.prototype
) 的原型(__proto__
)指向了父类构造函数Parent
的原型对象(Parent.prototype
)。 - 子类构造函数
Child
继承了父类构造函数Preant
的里的属性。使用super
调用的(ES5
则用call
或者apply
调用传参)。
- 把子类构造函数(
new Object()
、字面量{}
、Object.create()
创建对象的区别new Object()
和{}
创建的是Object
的实例,继承自内置对象Object
Object.create(obj)
,创建的对象的原型是obj
并继承自obj
new
操作符干了什么首先是创建实例对象{}
还继承了构造函数的原型
其次属性和方法被加入到 this 引用的对象中
并且新创建的对象由 this 所引用,最后隐式的返回 this
1
2
3
4
5
6
7
8
9//使用时第一个参数是构造函数,第二个参数是传给构造函数的参数
function myNew(fn, ...arg) {
//继承原型,create使用现有对象提供新创建对象的__proto__
const obj = Object.create(fn.prototype)
//继承实例方法对象
const rel = fn.apply(obj, args)
//上一步fn可能未返回实例对象
return rel instanceof Object ? rel : obj
}
- 本文作者: MR-QXJ
- 本文链接: https://mr-qxj.github.io/2020/10/21/语言/深入继承/
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!