原型链继承
父构造函数
function Father(name,age){
this.name=name,
this.age=age,
this.arr=[1,2,3]
}
Fa.prototype.say= function (){
console.log(this.age,this.name);
}
子构造函数
function Son(){
}
Son.prototype = new Father('爸爸',88) //把 Fa的构造函数挂到Son的原型链上
let son1 =new Son()
let son2 =new Son()
console.log(son1.name); //爸爸
console.log(son2.name); //爸爸
console.log(son2.say()); //88 "爸爸"
son1.arr.push('4')
console.log(son1.arr); // [1, 2, 3, "4"]
console.log(son2.arr); // [1, 2, 3, "4"]
// 因为数组是引用类型 son1 改了arr里边的值 那son2的arr也会跟着变
优点:书写简单
缺点:
- 每个通过
new Son()
实例化的对象都会共享 Son构造函数的prototype,如果Son构造函数的prototype里边有一个变量是引用类型 那么一个实例化对象更改了他 另一个实例化对象的值也会改变 - 无法在子构造函数里传值 感觉子构造函数像个僵尸
构造函数继承
function Father(name,age){
this.name=name,
this.age=age,
this.arr=[1,2,3]
}
function Son(name,age){
Fa.call(this,name,age) // 通过call 改变this指向 call会立即执行函数
相当于把 父函数里边的内容写到这里来了
}
let s1 =new Son('s1',18)
let s2 =new Son('s2',19)
s1.arr.push('4')
console.log(s1.name); //s1
console.log(s2.name); //s2
console.log(s1.arr); //[1, 2, 3, "4"]
console.log(s2.arr); // [1, 2, 3]
优点:解决了原型链继承中构造函数引用类型共享的问题,同时可以向构造函数传参
缺点:无法继承父构造函数原型上的方法
组合继承
把原型和构造函数结合在一起 就是组合继承
function Father(name,age){
this.name=name,
this.age=age,
this.arr=[1,2,3]
}
Father.prototype.say= function (){
console.log(this.age,this.name);
}
function Son(name,age){
Father.call(this,name,age)
}
Son.prototype=new Father('爸爸',88) 会覆盖Son原型
需要重新设置子类的constructo --> Son.prototype.constructor=Son
优点:解决了原型链和构造函数的继承问题
缺点: 父类构造函数被调用了两次 浪费内存
寄生组合继承
function Father(name,age){
this.name=name,
this.age=age,
this.arr=[1,2,3]
}
Father.prototype.say= function (){
console.log(this.age,this.name);
}
function Son(name,age){
Father.call(this,name,age)
}
Son.prototype=Object.create(Father.prototype);
Object.create()可以理解为复制了一份父类的原型对象
这样父构造函数更改了prototype也不会影响到子构造函数
优点: ↑↑↑↑
缺点: 好像也没啥
Es6 class继承
父类
class F{
// 构造器
constructor(name,number) {
this.name = name;
this.number = number;
}
sayHi() {
console.log(`姓名 ${this.name}, 学号 ${this.number}`)
// console.log('姓名 ' + this.name + ' , 学号' + this.number)
}
}
子类通过extends继承父类
class S extends F{
constructor(name,number,major) {
super(name,number) //必须要写super() 否则会报错
原理我也不懂嘿嘿 等我继续学习回来补
如果这里不写 constructor 就不用写super()
this.major = major
}
}
let s =new S('as',8,1)
console.log(s); //S {name: "as", number: 8, major: 1}
看了别人的文章自己写的 很随便 自己理解也不是很深刻 如果有不对的地方请指正或者有啥要补充的