js中ES5的继承
js的前期是没有类的这种说法,更不用说是继承了,于是创建出了很多继承的方式,经历很多个版本,实现了类似继承的方法。
3种有问题的继承方式
1.原型式继承
function Box(v){ //父类Box的创建
this.v=v;
console.log(v);
}
Box.prototype.run=function(){ //Box原型方法的创建
}
Box.prototype.a=10;
function Ball(v){ //子类的创建
}
Ball.prototype=new Box(); //原型式继承 就是父类的实例化赋值到子类的原型上
Object.defineProperty(Ball.prototype,"constructor",{ //没有constructor,只能自己创建
value:Ball
})
var c=new Ball(3); //但是constructor还是不能像ES6一样
console.log(c);
2.组合继承(原型继承和冒充继承)
function Box(v){
this.v=v;
console.log(v);
}
Box.prototype.run=function(){
}
Box.prototype.a=10;
function Ball(v){
//这是冒充继承(改变父类this指向)
Box.call(this,v); //为了解决constructor不能正常工作 把Box的this指向改为Ball(子类)的,但是new Ball的时候,Box的constructor可以正常工作,new Box还是不能解决
}
Ball.prototype=new Box();
Object.defineProperty(Ball.prototype,"constructor",{
value:Ball
})
var c=new Ball(3);
console.log(c);
完全实现继承的方式
- 寄生式继承(原型继承,冒充继承,中间函数)
function Box(v){
this.v=v;
console.log(v);
}
Box.prototype.run=function(){
}
Box.prototype.a=10;
function F(){ //中间类(函数)
}
F.prototype=Box.prototype; (父类的原型赋值给中间函数的原型上)
function Ball(v){
Box.call(this,v);
}
Ball.prototype=new F(); //中间函数的实例赋值给子类原型
Object.defineProperty(Ball.prototype,"constructor",{
value:Ball
})
var c=new Ball(3);
console.log(c)
寄生式继承的封装
Function.prototype.extend = function (superClass) { //参数是父类
function F() { } //中间函数
F.prototype = superClass.prototype;
var proto = this.prototype; //子类的原型 原因:后面的new F会覆盖原来的属性,所以提前拿出来
this.prototype = new F(); //中间类的实例赋值给子类原型
var names = Object.getOwnPropertyNames(proto); //获取子类原型上的所有方法和属性名
for (var i = 0; i < names.length; i++) { //遍历原来的属性名,new F()后,重新弄上去
var desc = Object.getOwnPropertyDescriptor(proto, names[i]);
Object.defineProperty(this.prototype, names[i], desc);
}
Object.defineProperty(this.prototype, "constructor", {
value: this,
});
this.prototype.superClass = superClass;
if (superClass.prototype.constructor !== superClass) {
Object.defineProperty(superClass.prototype, "constructor", {
value: superClass,
});
}
};
//继承组件的使用
function Box(v) {
this.v = v;
console.log(v);
}
Box.prototype.run = function () {
console.log("a");
};
Box.prototype.a = 10;
function Ball(v) { constructor中的super
this.superClass.apply(this,arguments);
}
Ball.prototype.play=function(){
}
Ball.extend(Box);
Ball.prototype.run=function(){ 子类方法中继承父类的这个方法 相当于ES6中的super.run();
this.superClass.prototype.run.apply(this,arguments);
console.log("b");
}
var c=new Ball(5);
console.log(c);
c.run();