• 《JavaScript 高级程序设计》学习总结六(4)


    引言:上一章我们提到过:继承采用原型链方式实现,而原型在实现属性共享上有优势也有缺点,所以原型链实现继承也是不可避免碰到这样的问题,第二个情况是:在创建子类型的实例时,不能向超类型的构造函数中传递参数。实际上, 应该说是没有办法在不影响所有对象实例的情况下,给超类型的构造函数传递参数。这一章节,我们针对继承实现的问题,我们总结学习几种实现继承的方法。

    1、借用构造函数

    在子类型构造函数的内部调用超类型构造函数。函数是在特定环境中执行代码的对象, 因此通过使用 apply()和 call()方法也可以在(将来)新创建的对象上执行构造函数,举个例子:

     1 function SuperType(){
     2  this.colors = ["red", "blue", "green"];
     3 }
     4 function SubType(){
     5  //继承了 SuperType
     6  SuperType.call(this);
     7 }
     8 var instance1 = new SubType();
     9 instance1.colors.push("black");
    10 alert(instance1.colors); //"red,blue,green,black"
    11 var instance2 = new SubType();
    12 alert(instance2.colors); //"red,blue,green" 

    代码中加下划线的那一行代码“借调”了超类型的构造函数。通过使用 call()方法(或 apply()方法 也可以),我们实际上是在(未来将要)新创建的 SubType 实例的环境下调用了 SuperType 构造函数。 这样一来,就会在新 SubType 对象上执行 SuperType()函数中定义的所有对象初始化代码。结果, SubType 的每个实例就都会具有自己的 colors 属性的副本了。

    相对于原型链而言,借用构造函数有一个很大的优势:

    1传递参数:即可以在子类型构造函数中向超类型构造函 数传递参数。

    function SuperType(name){
     this.name = name;
    }
    function SubType(){
     //继承了 SuperType,同时还传递了参数
     SuperType.call(this, "Nicholas");
    
     //实例属性
     this.age = 29;
    }
    var instance = new SubType();
    alert(instance.name); //"Nicholas";
    alert(instance.age); //29 

    如果仅仅是借用构造函数,那么也将无法避免构造函数模式存在的问题——方法都在构造函数中定 义,因此函数复用就无从谈起了。而且,在超类型的原型中定义的方法,对子类型而言也是不可见的,结 果所有类型都只能使用构造函数模式。考虑到这些问题,借用构造函数的技术也是很少单独使用的。

    组合继承 组合继承(combination inheritance),

    有时候也叫做伪经典继承,指的是将原型链和借用构造函数的 技术组合到一块,从而发挥二者之长的一种继承模式。其背后的思路是使用原型链实现对原型属性和方 法的继承,而通过借用构造函数来实现对实例属性的继承。这样,既通过在原型上定义方法实现了函数 复用,又能够保证每个实例都有它自己的属性

    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;
    }
    //继承方法
    SubType.prototype = new SuperType();
    SubType.prototype.constructor = SubType;
    SubType.prototype.sayAge = function(){
     alert(this.age);
    };
    var instance1 = new SubType("Nicholas", 29);
    instance1.colors.push("black");
    alert(instance1.colors); //"red,blue,green,black"
    instance1.sayName(); //"Nicholas";
    instance1.sayAge(); //29
    var instance2 = new SubType("Greg", 27);
    alert(instance2.colors); //"red,blue,green"
    instance2.sayName(); //"Greg";
    instance2.sayAge(); //27 

      在这个例子中,SuperType 构造函数定义了两个属性:name 和 colors。SuperType 的原型定义 了一个方法 sayName()。SubType 构造函数在调用 SuperType 构造函数时传入了 name 参数,紧接着 又定义了它自己的属性 age。然后,将 SuperType 的实例赋值给 SubType 的原型,然后又在该新原型 上定义了方法 sayAge()。这样一来,就可以让两个不同的 SubType 实例既分别拥有自己属性——包 括 colors 属性,又可以使用相同的方法了。 组合继承避免了原型链和借用构造函数的缺陷,融合了它们的优点,成为 JavaScript 中最常用的继 承模式。而且,instanceof 和 isPrototypeOf()也能够用于识别基于组合继承创建的对象。

    原型式继承:

    寄生式继承

    寄生组合式继承

    -----------------------------------------------------------------------本章留坑---------------------------------------------------------

  • 相关阅读:
    如何向尝试登录Windows 10的用户展示提示信息
    如何在Windows 10上创建和设置虚拟硬盘
    处理器虚拟化——VMX
    处理器虚拟化——基本数据结构
    DP
    Heap与Stack的区别
    获得内核模块 通过DriverSection
    软件管理器
    获取电脑软件信息 和 浏览器信息
    字符串之间的转换
  • 原文地址:https://www.cnblogs.com/wxhhts/p/9482059.html
Copyright © 2020-2023  润新知