JavaScript继承的六种方式
我觉得有些地方我可能理解的不是很到位,如果我下文有出现错误直接提出,谢谢~
另外可以看看这两篇文章:
https://www.cnblogs.com/humin/p/4556820.html
https://www.cnblogs.com/Grace-zyy/p/8206002.html
继承就是让子类拥有父类的资源
继承的意义
减少代码冗余
方便统一操作
弊端
耦合性比较强
继承方法
// 父类
function Person() {
this.name = 'cc';
this.pets = ['aa', 'bb'];
}
Person.prototype.run = function () {
console.log('跑');
};
1. 原型链继承
核心:将父类的实例作为子类的原型
// 子类
function Student() {
this.num = '111';
}
// 让新实例的原型等于父类的实例
Student.prototype = new Person();
var stu = new Student();
console.log(stu.num); // 111
stu.run(); // 跑
// 问题:类型问题
console.log(stu.constructor.name); //Person 对象类型改变
优化:修复constructor指针
// 子类
function Student() {
this.num = '111';
}
Student.prototype = new Person();
// 修复constructor指针即可
Student.prototype.constructor = Student;
var stu = new Student();
console.log(stu.num); // 111
stu.run(); // 跑
console.log(stu.pets); // ["aa", "bb"]
console.log(stu.constructor.name); // Student
// 问题:继承过来的实例属性, 如果是引用类型, 会被多个子类的实例共享
var stu1 = new Student();
stu.pets.push('dd');
console.log(stu.pets); // ["aa", "bb", "dd"]
console.log(stu1.pets); // ["aa", "bb", "dd"]
2. 借用构造函数继承
核心:在子类型构造函数的内部调用父类构造函数,通过使用call()和apply()方法可以在新创建的对象上执行构造函数。
// 子类
function Student() {
Person.call(this);
this.num = '111';
}
var stu = new Student();
console.log(stu.name); // 111
// 问题:没用到原型,只能继承父类的实例属性和方法,不能继承原型属性/方法
stu.run(); // 报错:stu.run is not a function
3. 组合继承
核心: 将原型链和借用构造函数的技术组合在一块,从而发挥两者之长的一种继承模式。(常用)
// 子类
function Student() {
Person.call(this);
this.num = '111';
}
Student.prototype = new Person();
Student.prototype.constructor = Student;
var stu = new Student();
var stu1 = new Student();
stu.pets.push('小花');
console.log(stu.pets); // ["aa", "bb", "小花"]
console.log(stu1.pets); // ["aa", "bb"]
// 问题:调用了两次父类构造函数(耗内存)
4. 原型式继承
核心:借助原型,然后基于已有的对象, 创建出新对象;同时不需要创建自定义类型
用一个函数包装一个对象,然后返回这个函数的调用,这个函数就变成了一个可以随意增添属性的实例或对象。object.create()就是这个原理。
// 原型式继承
function content(obj) {
function Temp() {}
Temp.prototype = obj;
return new Temp();
}
var p = new Person();
var stu1 = content(p);
console.log(stu1.name);
console.log(stu1.age);
5. 寄生式继承
核心:在原型式基础上增强这个对象。所谓增加, 就是指, 再次给这个对象增加一些属性或者方法
// 子类
function Student() {
this.num = '111';
}
function Temp() {}
Temp.prototype = new Person();
Student.prototype = new Temp();
Temp.constructor = Student;
var stu = new Student();
console.log(stu);
6. 寄生式组合继承
核心:通过借用函数来继承属性,通过原型链的混成形式来继承方法。(常用)
// 子类
function Student(num, name, pets) {
Person.call(this, name, pets);
this.num = num;
}
function Temp() {}
Temp.prototype = new Person();
Student.prototype = new Temp();
Temp.constructor = Student;
var stu = new Student('001', '张三', ['小花']);
var stu1 = new Student('002', '李四', ['小茂']);
console.log(stu);
console.log(stu1);