原型链继承
- 原理:将子类的原型对象指向父类的实例
- 优点: 1.继承了父类原型上的方法 2.继承了父类原型的属性
- 缺点:1.无法像父类的构造函数传参 2.父类的引用对象会被所有子类的实例共享
function Father(name,age) {
this.name = name
this.age = age
this.test = 'zxx'
this.arr=[1,2,3]
}
Father.prototype.say= function(){
console.log(123)
}
function Son(name,age) {
}
//将子类的原型对象指向父类的实例
Son.prototype = new Father()
let son1 = new Son()
let son2 = new Son()
//父类的引用对象会被所有子类的实例共享
//因为其实所有的实例都是引用的一个父类子类
console.log(son1.arr === son2.arr)
构造函数继承
- 原理:在子类的构造函数中,显式绑定this到子类实例并调用
- 优点:1.实现了像父类构造函数传参 2.父类的引用对象被隔离开来了
- 缺点:1.无法继承父类原型上的方法和属性 2.每个实例都会有父类构造函数的副本
3.每调用一次子类的构造函数也会调用一次父类的构造函数
function Father(name,age) {
this.name = name;
this.age = age;
this.test = 'zxx';
this.arr = [1,2,3];
}
Father.prototype.say=function(){
console.log(123);
}
function Son(name,age) {
Father.call(this,name,age)
}
let son1 =new Son('test',20);
组合继承
- 结合原型式继承和构造函数继承
- 优点:几乎解决了上述的缺点
- 缺点:1.调用了2次父类构造函数 2.子类的原型对象会有父类的实例属性
function Father(name,age) {
this.name = name
this.age = age
this.test = 'zxx'
this.arr = [1,2,3]
}
//原型链继承
//因为prototype被替换了,得加上constructor属性
Son.prototype = new Father()
Son.prototype.constructor = Son
function Son(name,age) {
//构造函数继承
Father.call(this,name,age)
}
原型式继承
- 原理:在内部创造一个定义一个函数,并且把这个函数的原型对象执行传入的对象,最后返回一个新对象。
- 优点:1.不用创建一个新的构造函数
- 缺点:1.如果参数相同的话,实例会共享进行共享 2.不能对创造的新对象进行包装
function object(obj){
function F(){};
F.prototype = obj;
return new F();
}
寄生式继承
- 原理:对新对象进行一次封装
- 优点:1.扩展了新对象的属性和方法
function Factory(obj){
let car = object(obj)
car.sayHi = function(){
console.log('sayHi');
}
return car;
}
组合式寄生式继承
- 原理:1.用了寄生虫式继承+2.构造函数式继承
- 寄生虫式继承解决了Son的修正了组合式继承原型链被改变的问题,这时原型上不在有父类构造函数的实例属性了
function Father(){
this.name = name;
this.say = function(){
console.log('say');
}
}
Son.prototype = Object.create(Father.prototype);
Son.prototype.constructor = Son;
function Son(){
Father.call(this)
}
Object.create
- 其实内部就是原型式继承
- 注意当原型对象修改之后,要加上constructor属性
function Create(obj){
function F(){};
F.prototype = obj;
F.prototype.constructor = F;
return new F()
}