原型链继承
- function SuperType(){this.property = true;}
- SuperType.prototype.getSuperValue = function(){
- return this.property;
- };
- function SubType(){
- this.subproperty = false;
- }
- // 继承了 SuperType
- SubType.prototype = new SuperType();
- var subType = new SubType();
- console.log(subType.getSuperValue()); // 继承了 SuperType 的 getSuperValue 方法, 打印 true
缺点
如果 SuperType 存在一个引用类型的属性, 而 SubType 的原型对象变为 SuperType 的一个实例, 这样每个 SubType 的实例都会共用这个引用类型的属性, 不同的 SubType 实例对该属性的操作都将会在其它 SubType 实例中体现出来, 这跟每个实例拥有自己的属性是违背的.
- function SuperType(){
- this.colors = ["red", "blue", "green"];
- }
- function SubType(){
- }
- // 继承了 SuperType
- SubType.prototype = new SuperType();
- var subType1 = new SubType();
- subType1.colors.push("black"); // subType1 修改 colors
- console.log(subType1.colors); // "red,blue,green,black"
- var subType2 = new SubType();
- console.log(subType2.colors); // "red,blue,green,black",subType2 的 colors 值为 subType1 修改之后的值
在创建子类型 (SubType) 的实例时, 不能向超类型 (SuperType) 的构造函数中传递参数. 实际上, 应该说是没有办法在不影响所有对象实例 (原因如缺点 1) 的情况下, 给超类型的构造函数传递参数.
借用构造函数继承
- function SuperType(){
- this.colors = ["red", "blue", "green"];
- }
- function SubType(){
- // 继承了 SuperType
- SuperType.call(this); // 通过 apply() 或 call() 执行 SuperType 的构造函数
- }
- var instance1 = new SubType();
- instance1.colors.push("black");
- alert(instance1.colors); // "red,blue,green,black"
- var instance2 = new SubType();
- alert(instance2.colors); // "red,blue,green"
该方法解决了 原型链继承 的引用型属性共享的问题.
还有可以在子类型构造函数中向超类型构造函数传递参数, 如下例子:
- function SuperType(name){
- this.name = name;
- }
- function SubType(){
- // 继承 SuperType, 并传递参数
- SuperType.call(this, "Nicholas");
- // 实例属性
- this.age = 29;
- }
- var subType = new SubType();
- console.log(subType.name); //"Nicholas";
- console.log(subType.age); //29
缺点
方法都在构造函数中定义, 因此函数复用就无从谈起了. 而且, 在超类型的原型中定义的方法, 对子类型而言也是不可见的, 结果所有类型都只能使用构造函数模式.
原型链 / 构造函数组合继承
- function SuperType(name){
- this.name = name;
- this.colors = ["red", "blue", "green"];
- }
- SuperType.prototype.sayName = function(){
- console.log(this.name);
- };
- function SubType(name, age){
- // 执行 SuperType 的构造函数, 继承 SuperType 的属性
- SuperType.call(this, name);
- this.age = age;
- }
- // 将 SuperType 的实例赋给 SubType 的原型对象, 这样 SubType 可继承 SuperType 原型中的方法
- SubType.prototype = new SuperType();
- SubType.prototype.sayAge = function(){
- console.log(this.age);
- };
- var subType1 = new SubType("Nicholas", 29);
- subType1.colors.push("black");
- console.log(subType1.colors); // "red,blue,green,black"
- subType1.sayName(); // "Nicholas";
- subType1.sayAge(); // 29
- var subType2 = new SubType("Greg", 27);
- console.log(subType2.colors); // "red,blue,green"
- subType2.sayName(); // "Greg";
- subType2.sayAge(); // 27
缺点
无论什么情况, 都会调用两次超类型构造函数, 一次是在创建子类型原型的时候, 一次是在执行子类型构造函数的时候. 这样一个 SubType 实例会包含两组 SuperType 的属性, 一组在 SubType 实例上, 一组在 SubType 原型中.
原型式继承
该方法基于已有的对象创建新对象, 同时还不必因此创建自定义类型.
- var person = {
- name: "Nicholas",
- friends: ["Shelby", "Court", "Van"]
- };
- var anotherPerson = Object.create(person); // 使用 person 作为新对象 (anotherPerson) 的原型
- anotherPerson.name = "Greg";
- anotherPerson.friends.push("Rob");
- var yetAnotherPerson = Object.create(person);
- yetAnotherPerson.name = "Linda";
- yetAnotherPerson.friends.push("Barbie");
- console.log(person.friends); // "Shelby,Court,Van,Rob,Barbie"
寄生式继承
该方法创建一个仅用于封装继承过程的函数, 该函数在内部以某种方式来增强对象, 最后再像真地是它做了所有工作一样返回对象.
- function creatAnother(original) {
- var clone = Object.create(original); // 创建一个新对象
- clone.sayHi = function() { // 以某种方式来增强这个对象
- console.log("hi");
- }
- return clone; // 返回该对象
- }
- // 使用示例
- var person = {
- name: "Nicholas",
- friends: ["Shelby", "Court", "Van"]
- };
- var anotherPerson = creatAnother(person);
- anotherPerson.sayHi(); // "hi"
寄生 / 原型链 / 构造函数组合继承
该方法解决原型链 / 构造函数组合继承调用两次超类型构造函数的问题.
通过借用构造函数来继承属性, 通过原型链的混成形式来继承方法. 其背后的基本思路是: 不必为了指定子类型的原型而调用超类型的构造函数, 我们所需要的无非就是超类型原型的一个副本而已. 本质上, 就是使用寄生式继承来继承超类型的原型, 然后再将结果指定给子类型的原型.
- function object(o){
- function F(){}
- F.prototype = o;
- return new F();
- }
- function inheritPrototype(subType, superType){
- var prototype = object(superType.prototype); // 根据超类型原型创建新对象
- prototype.constructor = subType; // 将新对象的 constructor 设置为子类型
- subType.prototype = prototype; // 将新对象赋给子类型的原型
- }
- function SuperType(name){
- this.name = name;
- this.colors = ["red", "blue", "green"];
- }
- SuperType.prototype.sayName = function(){
- console.log(this.name);
- };
- function SubType(name, age){
- SuperType.call(this, name);
- this.age = age;
- }
- inheritPrototype(SubType, SuperType);
- SubType.prototype.sayAge = function(){
- console.log(this.age);
- };
- var subType1 = new SubType("Nicholas", 29);
- subType1.colors.push("black");
- console.log(subType1.colors); // "red,blue,green,black"
- subType1.sayName(); // "Nicholas";
- subType1.sayAge(); // 29
- var subType2 = new SubType("Greg", 27);
- alert(subType2.colors); // "red,blue,green"
- subType2.sayName(); // "Greg";
- subType2.sayAge(); // 27
参考资料:JavaScript 高级程序设计(第 3 版)第 6.3 节 继承
来源: https://www.cnblogs.com/laixiangran/p/9017161.html