- JS中并不存在类,class只是语法糖,本质还是函数
- 类的内部定义的所有方法都是不可枚举的
- ES6的class类必须使用new命令操作,而ES5的构造函数不用new也可执行
- ES6的class类不存在变量提升,必须先定义才能实例化,而ES5实例化可以写在构造函数之前
- ES5的继承实际上是先创建实例对象this,然后将父类的方法添加在this上,而ES6的继承是先将父类实例对象的属性和方法加到this上(即先调用super方法),然后调用子类构造函数修改this
常见的继承方式:
-
原型链继承:超类的一个实例作为子类的原型
Sub.prototype =new Super() // 注意这里new Super()生成的超类对象并没有constructor属性,故需添加上 Sub.prototype.constructor = Sub // 所有子类的实例的原型都共享一个超类实例的属性和方法
-
组合继承:利用构造函数和原型链组合
function SubType(name, age) { // 继承属性 SuperType.call(this, name); this.age = age; } // 继承方法 SubType.prototype = new SuperType(); SubType.prototype.constructor = SubType; // 子类中借调父类构造函数,父类中定义的属性会在每个实例中有一份副本, // 调用两次超类型的构造函数,创建的每个实例中都要屏蔽超类型对象的所有实例属性
-
原型式继承:创建一个临时构造函数,借助已有对象作为临时构造函数的原型,并在此基础上实例化对象
function object(o){ function F(){} F.prototype = o; return new F(); } // 原型的引用类型属性会在各实例之间共享
-
寄生式继承:在原型式继承得到的对象基础上在内部增强对象
function createAnother(original) { var clone = object(original); clone.sayHi = function() { alert("hi"); }; return clone; } // 寄生式继承为对象添加函数时函数不能复用,效率低
-
寄生组合式继承
function object(o) { function F(){} F.prototype = o; return new F(); } function inheritPrototype(superType, subType) { // 1. 创建超类型原型的副本。 // 2. 为创建的副本添加constructor属性,弥补因重写原型而失去的默认的constructor属性 // 3. 将新创建的对象(即副本)赋值给子类型的原型 var prototype = object(superType.prototype); prototype.constructor = subType; subType.prototype = prototype; } function SuperType(name) { this.name = name; this.colors = ["red", "blue", "green"]; } SuperType.prototype.sayName = function() { alert(this.name); }; function SubType(name, age) { SuperType.call(this, name); this.age = age; } inheritPrototype(SuperType, SubType); // 这一句,替代了组合继承中的SubType.prototype = new SuperType() // 通过借用构造函数来继承属性;通过原型链来继承方法。不必为了指定子类型的原型而调用超类型的构造函数