js的继承与其他语言不大一样,继承的目的是让子类的实例同时具备父类实例私有的属性和公有的方法。
1.原型继承
what:子类的原型等于父类的一个实例
特点:父类中私有和公有的属性和方法最后都变成子类实例公有的。和其他语言不同的是:原型继承不会把父类的属性方法“”拷贝”给子类,而是指向型的,即让子类的__proto__基于原型链查找到自己定义的属性和方法。
如果这样修改 children.proto=xxx,能实现子类改写原有父类一个实例的内容,对子类的其他实例有影响,但是对父类没有影响,ie678不允许使用原型链。
如果这样修改 children. _proto __.proto __=xxx,直接改变父类的原型,这样不仅改变子类原型及其实例,也会影响其他父类的实例。
因为可以随意修改原型链会影响到父类,所以这不是一个好的继承的办法。
2.call继承
在子类构造函数中,把父类当做普通函数执行,然后使用call把父类中this改变,让父类中的this变成子类,相当于让子类继承父类的私有属性。这种继承是拷贝型。
function Parent() {
this.x = 100 //this是window
}
Parent.prototype.getx = function() {
return this.x
}
function Child() {
Parent();
Parent.call(this) //this 是Child的实例
this.y = 200
}
Child.prototype.gety = function() {
return this.y
}
let c1=new Child()
console.log(c1);
缺点:只能继承父类的私有的属性和方法,不能继承父类公共的。
3.组合型继承—call继承+另类原型继承
call继承父类实例私有的属性,继承父类公共的方法。
//本来Child.prototype.__proto__要指向object.prototype,但是现在强制指向Parent.prototype
Child.prototype.__proto__ = Parent.prototype
但是ie不让用原型链,那就只能想其他办法啦。
首先Object.create(obj)会创建一个空对象,这个对象的原型链指向obj,然后利用这个来实现子类实例继承父类原型上公有的方法。
let obj={
plan:"study"
}
Object.create(obj)
console.log(obj);
Object.create(null)//写null就相当于阻止了原型链,就没有这个属性了
可以看到{}的原型链指向Object。
function Parent() {
this.x = 100 //this是window
}
Parent.prototype.getx = function() {
return this.x
}
function Child() {
Parent();
Parent.call(this) //this 是Child的实例
this.y = 200
}
//Child.prototype.__proto__ = Parent.prototype ie678不给你用__proto__
Child.prototype = Object.create(Parent.prototype)
Child.prototype.constuctor = Child//记得加constuctor
Child.prototype.gety = function() {
return this.y
}
let c1 = new Child()
console.log(c1);
ES6中的继承
比较简单,看代码就能明白,记住机理最重要。
class Parent {
constructor() {
this.x = 100
}
getx = function() {
return this.x
}
}
//extends类似于组合继承
class child extends class Parent {
constructor() {
super()//类似于之前的call继承,必须写super,
//super(100,200)相当于把parent里面的constructor执行,传递100和200
this.y = 200
}
gety() {
return this.y
}
}