美文网首页
JavaScript-原型链

JavaScript-原型链

作者: qh0814 | 来源:发表于2019-03-15 22:26 被阅读0次

    1.prototype

    在讨论prototype之前先看一段代码:

    function Npc(hp){
    this.hp = hp
    this.die = function(){
        this.hp = 0
      } 
    }
    var npc1 = new Npc(100)  //Npc {hp: 100, die: ƒ}
    var npc2 = new Npc(90)  //Npc {hp: 90, die: ƒ}
    

    我们用构造函数创建了2个实例对象,两者都有相同的方法。但两者抽象出来实际上可以归类为同一类,可以想象当有较多对象时,这种方法无疑会浪费系统资源,因为每生成一个这类对象就会生成同样的方法。应用继承的方法可以解决这类问题。
    很多的语言都支持面向对象的思想,而继承则是面向对象的特性之一。c++和java引入了“类”的概念,但JavaScript却没有这一概念,JavaScript通过原型对象来实现继承。
    可以改写这段代码:

    function Npc(hp){
    this.hp = hp
    }
    Npc.prototype.die = function(){
        this.hp = 0
    }
    var npc1 = new Npc(100)
    npc1.hp // 100
    npc1.die()
    npc1.hp  // 0
    

    每个函数中都有prototype属性,该属性指向一个对象,在构造函数中,prototype指向的对象为生成的实例对象的原型,所有实例对象继承了原型中的所有属性和方法。重复的内容都放在这个原型中作为公有属性/方法,所以这样就不必在生成对象的时候各自生成同样的方法了,通过继承实例可以调用原型中的方法。
    简单小结一下:构造函数中prototype属性指向了各实例的原型,实例会继承原型中的内容。

    2. __ proto __

    JavaScript中,每个对象中都有__ proto __属性,该属性直接指向本对象的原型。从上面我们可以知道:函数中prototype指向实例的原型。那么我们可以得出下面的结论:

    npc1.__proto__ === Npc.prototype //true
    

    梳理一下它们的关系:
    1.首先npc1这个实例是由Npc这个构造函数生成
    2.代码中为构造函数的原型(prototype指向)添加了“die”的方法
    3.实例对象自动继承了原型对象(prototype指向的对象)的内容
    4.npc1的__ proto __属性指向它的原型,构造函数的prototype属性也指向原型,两个原型是同一个对象

    实际上,不仅仅是这种对象是通过原型来继承,这种模式同样适用于其他对象。
    String对象

    var str = new String()
    str.__proto__ === String.prototype //true
    

    Number对象

    var num = new Number()
    num.__proto__ === Number.prototype //true
    

    Object对象

    var obj = new Object()
    obj.__proto__ === Object.prototype //true
    

    上面3个例子中String()、Number()、Object()作为各自实例的构造函数
    到了这里可以得出推论:实例.__ proto __ === 构造函数.prototype,它们代表同一个对象,即实例的原型对象。
    同样,已知原型对象,可以通过constructor属性来查询构造函数:

    str.__proto__.constructor === String //true
    num.__proto__.constructor === Number //true
    obj.__proto__.constructor === Object //true
    

    小结:在局部的原型与实例对象以及构造函数之间,有如下关系


    局部对象之间的关系

    3.原型链

    了解了局部对象之间的关系后,那么什么是原型链呢?
    原型链,从字面意思来看是“原型组成的链”,或许你知道“食物链”是什么意思,我们可以参考其他术语来给原型链一个模糊的定义:原型链是各种对象之间通过某种关系连在一起的链。这些对象既可能是原型,也可能是实例对象。
    从结构上来说,原型链是上面总结的局部关系的集合,任何一个对象都有原型,从底端的实例对象开始,它的原型仍然有原型,既“.__proto __. __proto __.....”的关系。在JavaScript里,所有的原型都可以向上追溯到Object.prototype,Object.prototype是原型链的起点,但Object.prototype也是一个对象,它的__proto __属性是null,即:

    Object.prototype.__proto__ //null
    
    原型链

    在调用属性或方法时,会先在当前实例对象中寻找是否有该方法,如果没有则沿着原型链上找,到这就是为什么所有对象都有toString和valueOf这种方法的原因。

    值得注意的是,Function和Object既可以作为构造函数又是对象

    • Function作为对象,它的构造函数是Function
    Function.constructor === Function  //true
    Function.__proto__ === Function.prototype /*true  或者这么理解:
    Function作为函数,函数会继承Function的prototype*/
    Function instanceof Object //true
    
    • Object作为构造函数,同时Function.prototype作为对象也应该有原型
    Function.prototype.__proto__ === Object.prototype //true
    
    • Object作为函数,函数继承自Function的原型
    Object.__proto__ === Function.prototype //true
    
    • Object作为函数,函数继承自Function的原型,同时Function的prototype也是一个对象,Function原型对象会继承自Object.prototype,即Object的原型。
    Object.__proto__.__proto__ === Object.prototype  //true
    

    相关文章

      网友评论

          本文标题:JavaScript-原型链

          本文链接:https://www.haomeiwen.com/subject/ijvrmqtx.html