有些对象会有方法(函数),如果把这些方法都放在构造函数中声明就会导致内存的浪费。下例中p1和p2都有say,但占据不同内存。
function Person() {
this.say = function() {
console.log("你好");
}
}
var p1 = new Person();//p1是对象 person是构造函数
var p2 = new Person();
console.log(p1.say === p2.say); // false
让一个对象可以访问到另一个对象中的属性和方法,这种方式称之为继承。8种继承方式
-
原型链继承
子类的原型指向了父类的实例,子类就可以调用其父类原型对象上的私有属性和公有方法。
Child.prototype = new Parent();
ps 子类定义新方法会覆盖原方法
缺点:
无法实现多继承
引用类型的值会被实例共享
子类型无法给超类型传递参数 -
借用构造函数继承(对象冒充)
function Child(name) {
Parent.call(this, name);
this.age = 24
}
把 Parent 里面的 this 相关属性和方法赋值到新的实例上,而不是赋值到 Child 上面。
缺点
不能继承超类原型上的属性和方法
无法实现函数复用,由于 call 有多个父类实例的副本,性能损耗。
原型链丢失
- 组合模式继承
是将原型链继承和借用构造函数继承的技术组合到一块
function Child(name){
Parent.call(this, name);
this.age = 24
}
Child.prototype = new Parent('父类')
- 共享原型继承
这种方式下子类和父类共享一个原型
Child.prototype = Parent.prototype;
缺点
只能继承父类原型属性方法,不能继承构造函数属性方法
与原型链继承一样,存在引用类型问题
- 原型式继承
这种继承方式普遍用于基于当前已有对象创建新对象 - 寄生式继承
寄生式继承是原型式继承的加强版,缺点和原型式继承一样 - 寄生组合式继承
- class 继承
ES6 中,通过 class 关键字来定义类,子类可以通过 extends 继承父类