博客
关于我
JavaScript原型链
阅读量:621 次
发布时间:2019-03-13

本文共 3707 字,大约阅读时间需要 12 分钟。

原型链是ECMAScript实现继承的核心机制,它通过让一个引用类型继承另一个引用类型的属性和方法来工作。基本思想是让原型对象指向另一个类型的实例,从而使继承的类型能够共享超类型的属性和方法。

一个典型的例子是通过替换子类型的原型来实现继承的方式:

function SuperType() {    this.property = true;}SuperType.prototype.getSuperValue = function() {    return this.property;};function SubType() {    this.subproperty = false;}SubType.prototype = new SuperType(); // 替换子类型的原型SubType.prototype.getSubValue = function() {    return this.subproperty;};var instance = new SubType();alert(instance.getSuperValue()); // 找到的结果是正确的

在这种情况下,SubType 类型继承了 SuperType 类型的所有属性和方法。需要注意的是,这种实现方式没有使用 SubType 的默认原型,而是手动替换了一个 SuperType 实例作为其原型。这样一来,每个 SubType 实例都共享同一个 SuperType 实例的属性和方法。

在原型链的查找过程中,当一个对象属性或方法不存在时,引擎会依次检查:

  • 实例本身
  • 子类型的原型
  • 超类型的原型
  • 当原型链末端(Object 原型)时停止
  • 所有引用类型都默认继承了 Object,这种继承同样是通过原型链实现的。要确保在重写或添加方法时,原型链不会被破坏。例如,替换原型对象后,子类型的方法和属性应该放在替换之后进行定义:

    function SuperType() {    this.property = true;}SuperType.prototype.getSuperValue = function() {    return this.property;};function SubType() {    this.subproperty = false;}SubType.prototype = new SuperType(); // 替换子类型的原型// 方法重写SubType.prototype.getSuperValue = function() {    return false;};// 添加新方法SubType.prototype.getSubValue = function() {    return this.subproperty;};

    然而,要小心处理原型对象的替换。如果在替换原型后使用对象字面量添加新方法,会导致原型链断裂,子类型实例就和超类型失去了关系:

    function SuperType() {    this.property = true;}SuperType.prototype.getSuperValue = function() {    return this.property;};function SubType() {    this.subproperty = false;}SubType.prototype = new SuperType(); // 替换子类型的原型// 错误的替换方式SubType.prototype = {    getSubValue: function() {        return this.subproperty;    }    // 其他额外方法};var instance = new SubType();alert(instance.getSuperValue()); // Error!

    这是因为 SubType.prototype 现在是一个字面量对象,而不是 SuperType 实例。为了避免原型链断裂,原型对象的替换必须谨慎进行。

    在原型链模式中存在以下问题:

  • 原型对象的属性会被所有实例共享,这也是为什么实例的构造函数中通常不应直接定义属性,而是在原型对象上定义的原因。
  • 在创建子类型实例时,不能像超类型的构造函数中传递参数,这在实际应用中很少单独使用原型链继承。
  • 为了解决这些问题,可以使用借用构造函数的方式,让子类型的构造函数内部调用超类型的构造函数:

    function SuperType(name) {    this.name = name;    this.colors = ["red", "green", "yellow"];}function SubType(name, age) {    // 借用超类型的构造函数    SuperType.call(this, name);    this.age = age;}var instance = new SubType("Alice", 23);alert(instance.name); // "Alice"

    这种方式的优点是:

  • 子类型的构造函数可以传递参数给超类型构造函数。
  • 子类型实例可以继承超类型原型链中的所有属性和方法。
  • 然而,借用构造函数的缺点是:

  • 方法不会被在实例中复用,因为函数在原型链中已经存在。
  • 导致所有类型都只能使用构造函数模式,无法使用原型链方式。
  • 最常用的继承模式是组合继承,它结合了原型链和借用构造函数的优点:

    function SuperType(name) {    this.name = name;    this.colors = ["red", "green", "yellow"];}SuperType.prototype.sayName = function() {    alert(this.name);};function SubType(name, age) {    // 借用超类型的构造函数    SuperType.call(this, name);    this.age = age;    // 原型链方式继承方法    SubType.prototype = new SuperType();}SubType.prototype.sayAge = function() {    alert(this.age);};var instance1 = new SubType("Alice", 23);instance1.colors.push("black"); // ["red", "green", "yellow", "black"]

    这样,子类型实例既有自己的实例属性,又可以使用超类型原型链中的共享属性和方法。这也是为什么许多现代JavaScript框架会选择组合继承作为默认的继承方式。

    此外,ECMAScript 5引入了原型式继承的规范化方法 Object.create(),可以通过指定原型对象和属性对象来实现:

    var person = {    name: "Alice",    friends: ["Shellby", "Court", "Van"]};var anotherPerson = Object.create(person);anotherPerson.name = "Rob";anotherPerson.friends.push("Room");

    Object.create() 最大的优势是实现完全的原型式继承,而没有依赖构造函数。

    最后,寄生式继承则是一种更高级的技术,它与工厂模式类似,通过创建一个函数来封装继承过程:

    function createAnother(original) {    var clone = Object(original);    clone.sayHi = function() {        alert("HI");    };    return clone;}var person = { name: "Alice", friends: ["Shelby"] };var anotherPerson = createAnother(person);anotherPerson.sayHi(); // "HI"

    这种模式适合处理不直接涉及构造函数的情况。最终,通过结合原型链和借用构造函数的优点,寄生组合式继承成为了JavaScript中最优的继承方式。它通过原型链实现共享属性和方法,通过借用构造函数实现实例特有的属性,同时避免构造函数的重复调用。

    原型链和组合继承模式是JavaScript中最常用的继承方式。这些模式在实际开发中通过instanceofisPrototypeOf()等方法进行验证。选择恰当的继承模式对于确保代码优化和维护具有重要意义。

    转载地址:http://vayoz.baihongyu.com/

    你可能感兴趣的文章
    Objective-C实现LongestIncreasingSubsequence最长递增子序列算法(附完整源码)
    查看>>
    Objective-C实现LRU 缓存算法(附完整源码)
    查看>>
    Objective-C实现lstm prediction预测算法(附完整源码)
    查看>>
    Objective-C实现Luhn (Mod 10)Algorithm算法(附完整源码)
    查看>>
    Objective-C实现max subarray sum最大子数组和算法(附完整源码)
    查看>>
    Objective-C实现MaximumSubarray最大子阵列(动态规划解决方案)算法(附完整源码)
    查看>>
    Objective-C实现max_heap最大堆算法(附完整源码)
    查看>>
    Objective-C实现md5算法(附完整源码)
    查看>>
    Objective-C实现memoization优化技术算法(附完整源码)
    查看>>
    Objective-C实现memset函数功能(附完整源码)
    查看>>
    Objective-C实现merge insertion sort合并插入排序算法(附完整源码)
    查看>>
    Objective-C实现merge sort归并排序算法(附完整源码)
    查看>>
    Objective-C实现mergesort归并排序算法(附完整源码)
    查看>>
    Objective-C实现miller rabin米勒-拉宾素性检验算法(附完整源码)
    查看>>
    Objective-C实现Miller-Rabin素性测试程序(附完整源码)
    查看>>
    Objective-C实现Miller-Rabin素性测试程序(附完整源码)
    查看>>
    Objective-C实现MinhashLSH算法(附完整源码)
    查看>>
    Objective-C实现MinHeap最小堆算法(附完整源码)
    查看>>
    Objective-C实现multilayer perceptron classifier多层感知器分类器算法(附完整源码)
    查看>>
    Objective-C实现n body simulationn体模拟算法(附完整源码)
    查看>>