JS继承的四种方式
封装:低耦合,高内聚,将实现功能的某一部分代码进行函数封装
多态:重载和重写
重载:方法名相同,形参个数或类型不同 (js中不存在真正意义上的重 载,js中重载指的是在同一个方法中,根据形参的不同,实现不同的效果)
重写: 在类的继承中,子类可以重写父类中的方法
继承:子类继承父类中的属性和方法 (目的是让子类中的实例调取父类中的属性和 方法)
1.原型继承
目的:让父类中的属性和方法在子类实例的原型链上
child.prototype=new Partent(); //让子类的原型指向父类的实例
child.prototype.constructor=child //保证原型重定向的完整性
特点:1.不像其他语言中的继承一样(其他语言一般是拷贝继承,也就是子类继承父类,会把父类中的属性和方法拷贝一份到子类中,供子类的实例调取使用),它是把父类的原型放到子类的原型链上,子类的实例想要调用这些方法,是基于–proto–原型链查找机制完成的
2.子类可以重写父类中的方法,这样会导致父类其他实例受影响
3.父类中私有或者公有的属性和方法都会变为子类的公有属性和方法
function Father(x){
this.x = x;
}
Father.prototype.getX = function(){
console.log(this.x)
}
function Child(y){
this.y = y;
}
Child.prototype = new Father(200)
Child.prototype.constructor= Child
Child.prototype.getY = function(){
console.log(this.y)
}
let son = new Child(100)
console.log(son.y);//100
son.getY();//100
son.getX();//200
2.call继承
在Child方法中把Father当做普通函数执行,让Father中的this指向Child的实例,相当于给Child的实例设置了很多私有的属性或方法
特点:1.只能继承父类的私有属性或方法(因为是将Father当做普通农函数执行,和其原型上的属性和方法没有关系)
2.父类私有的属性和方法变为子类私有的属性和方法
function Father(x){
this.x = x;
}
Father.prototype.getX = function(){
console.log(this.x)
}
function Child(y){
Father.call(this,200) //==>等同于son.x=200
this.y = y;
}
Child.prototype.getY = function(){
console.log(this.y)
}
let son = new Child(100)
console.log(son.y);//100
console.log(son.x)// 200
3.寄生组合继承
寄生组合继承 = call继承+ 类似原生继承
特点:父类私有的和公有的属性和方法分别是子类实例公有的和私有的属性和方法(推荐)
function Father(x){
this.x = x;
}
Father.prototype.getX = function(){
console.log(this.x)
}
function Child(y){
Father.call(this,200) //==>等同于son.x=200
this.y = y;
}
//Object.create(obj):创建一个空对象,让空对象的--proto——指向obj,不同于原型继承的是,空对象中的公有属性和方法不会像原型继承一样影响父类的实例
Child.prototype = Object.create(A.prototype)
Child.prototype.constructor = Child
Child.prototype.getY = function(){
console.log(this.y)
}
let son = new Child(100)
console.log(son.y);//100
console.log(son.x)// 200
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YhLLmwGD-1594626885941)(C:%5CUsers%5Chuangli%5CAppData%5CRoaming%5CTypora%5Ctypora-user-images%5Cimage-20200628204836375.png)]
补充:重写一个Object.create()方法
let obj={name:'zhangsan',age:'14'}
Object.create = function(obj){
function Fn(){}//fn的私有属性和方法为空,Fn的实例会指向fn.prototype也就是obj
Fn.prototype = obj
return new Fn()// fn的实例会指向obj这个对象
}
4.class类继承(es6)
//Father()不能直接执行,因为再es6中类不能被当做一个普通函数执行,因此子类实例不能通过call来实现继承,同时也不能通过重定向原型指向Child.prototype=Object.create(Father.prototype)来继承
class类继承 class Child extends Father //父类公有的变为子类公有的
class Father{
constructor(x){
this.x = x
}
getX(){
console.log(this.x)
}
}
class Child extends Father{
constructor(y){ //子类只要继承父类,可以不写constructor,但如果写了constructor就一定要写super()
super(200); //=>Father.call(this,200)把父类当做普通方法执行,给方法传递参数,让方法中的this是子类中的实例
this.y=y
}
getY(){
console.log(this.y)
}
}
let son = new Child(100)
console.log(son)