美文网首页前端攻城狮前端,数据库学习javascript
最详尽的 JS 原型与原型链终极详解,没有「可能是」。(二)

最详尽的 JS 原型与原型链终极详解,没有「可能是」。(二)

作者: Yi罐可乐 | 来源:发表于2016-08-20 17:13 被阅读22695次

    第三篇已更新,点击进入

    四. __proto__

    JS 在创建对象(不论是普通对象还是函数对象)的时候,都有一个叫做__proto__ 的内置属性,用于指向创建它的构造函数的原型对象。
    对象 person1 有一个 __proto__属性,创建它的构造函数是 Person,构造函数的原型对象是 Person.prototype ,所以:
    person1.__proto__ == Person.prototype

    请看下图:


    《JavaScript 高级程序设计》的图 6-1

    根据上面这个连接图,我们能得到:

    Person.prototype.constructor == Person;
    person1.__proto__ == Person.prototype;
    person1.constructor == Person;
    

    不过,要明确的真正重要的一点就是,这个连接存在于实例(person1)与构造函数(Person)的原型对象(Person.prototype)之间,而不是存在于实例(person1)与构造函数(Person)之间。

    注意:因为绝大部分浏览器都支持__proto__属性,所以它才被加入了 ES6 里(ES5 部分浏览器也支持,但还不是标准)。

    五. 构造器

    熟悉 Javascript 的童鞋都知道,我们可以这样创建一个对象:
    var obj = {}
    它等同于下面这样:
    var obj = new Object()

    obj 是构造函数(Object)的一个实例。所以:
    obj.constructor === Object
    obj.__proto__ === Object.prototype

    新对象 obj 是使用 new 操作符后跟一个构造函数来创建的。构造函数(Object)本身就是一个函数(就是上面说的函数对象),它和上面的构造函数 Person 差不多。只不过该函数是出于创建新对象的目的而定义的。所以不要被 Object 吓倒。


    同理,可以创建对象的构造器不仅仅有 Object,也可以是 Array,Date,Function等。
    所以我们也可以构造函数来创建 Array、 Date、Function

    var b = new Array();
    b.constructor === Array;
    b.__proto__ === Array.prototype;
    
    var c = new Date(); 
    c.constructor === Date;
    c.__proto__ === Date.prototype;
    
    var d = new Function();
    d.constructor === Function;
    d.__proto__ === Function.prototype;
    

    这些构造器都是函数对象:

    函数对象

    六. 原型链

    小测试来检验一下你理解的怎么样:

    1. person1.__proto__ 是什么?
    2. Person.__proto__ 是什么?
    3. Person.prototype.__proto__ 是什么?
    4. Object.__proto__ 是什么?
    5. Object.prototype__proto__ 是什么?

    答案:
    第一题:
    因为 person1.__proto__ === person1 的构造函数.prototype
    因为 person1的构造函数 === Person
    所以 person1.__proto__ === Person.prototype

    第二题:
    因为 Person.__proto__ === Person的构造函数.prototype
    因为 Person的构造函数 === Function
    所以 Person.__proto__ === Function.prototype

    第三题:
    Person.prototype 是一个普通对象,我们无需关注它有哪些属性,只要记住它是一个普通对象。
    因为一个普通对象的构造函数 === Object
    所以 Person.prototype.__proto__ === Object.prototype

    第四题,参照第二题,因为 Person 和 Object 一样都是构造函数

    第五题:
    Object.prototype 对象也有proto属性,但它比较特殊,为 null 。因为 null 处于原型链的顶端,这个只能记住。
    Object.prototype.__proto__ === null

    好了,如果以上你都能明白,那就可以继续深入学习第三篇教程了:
    第三篇,点击进入

    相关文章

      网友评论

      • f079090ddf78:我觉得Object.prototype.__proto__ === null的原因大概是这样的:
        因为 Object.prototype 是个对象
        并且对象的__proto__又指向其构造函数的原型(Object.prototype)
        所以会有如下奇怪的等式: Object.prototype.__proto__ === Object.prototype
        估计这种逻辑上的死循环很难解释了吧(我瞎猜的)
      • 逍遥鱼_eea6:lz大人,在上一讲,您明确了如下:
        原型对象(Person.prototype)是 构造函数(Person)的一个实例。
        var A = new Person();
        Person.prototype = A;

        但是这一讲开头就“person1.__proto__ == Person.prototype”
        实际上A和person1都是Person的实例吧,那么岂不是person1.__proto__ = person1了。
        f079090ddf78:Person.prototype是Person的实例,person1也是Person的实例,但是这两个实例不是同一个哦,所以Person.prototype !== person1 => person1.__proto__ !== person1
      • affbfcc13f7a:厉害了,兄弟
      • d5d7626e55b6:不过,要明确的真正重要的一点就是,这个连接存在于实例(person1)与构造函数(Person)的原型对象(Person.prototype)之间,而不是存在于实例(person1)与构造函数(Person)之间。

        原型链的形成是真正是靠__proto__ 而非prototype
        得出这个连接即__proto__
        Function.prototype,就是他自己,自己指向自己,没有意义。
        JS一直强调万物皆对象,函数对象也是对象,给他认个祖宗,指向Object.prototype。Object.prototype.__proto__ === null,保证原型链能够正常结束。
      • f590688d8fa0:楼主你好,我也对第3题感到困惑,能否烦请给一下解答。按文章意思,Person.prototype是Person的一个实例,那Person.prototype的constructor应该还是Person吧,那Person.prototype._proto_不还是Person.prototype了吗?虽然感觉怪怪的,但是我确实是这样理解的,能否烦请楼主指出理解错误的地方在哪?非常感谢!
        萧喆浩:@Yi罐可乐 同样不是很理解,楼主第一篇不是说:“那 Person.prototype 为什么有 constructor 属性??同理, Person.prototype (你把它想象成 A) 也是Person 的实例”吗? 麻烦楼主能不能再详细解释一下
        Yi罐可乐:「Person.prototype是Person的一个实例」这句是错误的。请再看下第一篇文章。
      • 梦醒了_4d69:感觉看的不是很明白,暂时理解不了吧。
      • 闯关者:第三篇还没看 。。。。我有个疑问 是不是所有构造函数(除了Object外)
        typeof 构造函数名.prototype.__ptoto__ 都是'object' ?
        但是 typeof Object 是 'function'
        闯关者:哦 我错了 我把 普通对象和函数对象搞混了
      • 多啦斯基周:关于第三题我有一个疑问,Person.prototype的构造函数不应该是Person自己吗?
        Person.prototype.constructor === Person; // true
        那 Person.prototype.__proto__不就应该是 Person.prototype的构造函数的prototype,也就是Person.prototype
        为什么会是Obejct.prototype呢
        Yi罐可乐:@多啦斯基周 你手边有《JS高级程序设计》这本书吗?没有的话可以买个二手的,不贵,我建议你结合这本书,再理解一下
        多啦斯基周:@Yi罐可乐 文中提到的“Person.prototype 是一个普通对象,我们无需关注它有哪些属性,只要记住它是一个普通对象。因为一个普通对象的构造函数 === Object”这个我理解,可是同时,为什么“”Person.prototype.constructor === Person; // true这不就说明Person.prototype应该是Person吗?
        我觉得好像哪不对,又找不到
        Yi罐可乐:@多啦斯基周 再想想
      • Young杨宇航:写的非常好
      • b9dfc4079317:之前一直模模糊糊, 看mdn讲的很模糊,没有形成系统的感觉,果然还是条理逻辑清晰,更易理解。忍不住点颗赞...
      • Allen_3918:写的很全,也很清晰。看完后豁然开朗了。谢谢!
      • pokemonjs:另外还有一点不太懂忘指教,
        文中写到
        var obj = {}
        它等同于下面这样:
        var obj = new Object()
        那么这个obj应该是一个普通对象(非函数对象)对么?所以说这个obj是不是也就没有prototype属性了?谢谢!
        WOTK:第五题想不通啊,望解答:
        1、原型对象是普通对象
        2、普通对象的构造 === Object
        3、对象的_proto_属性指向其构造方法的原型对象
        conclusion:Object.prototype._proto_ === Object.prototype
        答案却是: Object.prototype._proto_ === null
        pokemonjs: @Yi罐可乐 感谢大佬百忙之中抽空解答,其实我困惑更大的是前面一条问题,望指点!谢谢。
        Yi罐可乐:这个 obj 是一个普通对象,没错。
        你记住这句:每个对象都有 __proto__ 属性,但只有函数对象才有 prototype
        在教程一里写的有
      • pokemonjs:感谢楼主的分享,有一题没看懂,第三题,Person.prototype[的构造函数] === Object
        这一句没太理解,按照上文函数对象的prototype指向这个函数的一个实例,例如person1.prototype===new Person()也就是说Person.prototype是一个Person的实例,Person的实例的构造函数应该是Person啊?为啥会是Object呢?求解,谢谢哈。
        Yi罐可乐:当时有一些笔误,现在已改正,耽误你的理解了,不好意思。
      • 小米小米2:看看我写的原型链吧,可能会对大家有帮助
        http://www.0313.name/2017/01/23/prototype2.html
        shouting__:大神膜拜,不过单词拼的不敢恭维
        Yi罐可乐:@小米小米2 :+1:
      • 16b549f602ed:Object.prototype__proto__ 是什么?

        上面漏写一个点
        Yi罐可乐:@weihome 已改正
        weihome:第三题有疑问,原型对象的构造函数不是原型对象所在的函数么
        这句话是否有错误:Person.prototype[的构造函数] === Person
        Yi罐可乐: @fazero 谢谢指出!
      • 16b549f602ed:第二题:
        因为 Person.__proto__ === person1[的构造函数].prototype

        这里写错了吧
        Yi罐可乐:第二题笔误写错了,不过大家应该都能发现这么明显的错误,嘿嘿
      • 2049a2f18231:本来就很容易懂的概念,为什么都写的这么绕口。
      • 15d9cc2fdd4d: :joy: 基础太差,有点吃力
        森林迷了鹿_a9e9:兄dei , 你还在吗
        15d9cc2fdd4d:@Yi罐可乐 谢谢楼主无私分享和鼓励 :pray:
        Yi罐可乐: @Allen丶艾佛森 有个印象,等JS熟悉了,回过头在看,肯定会豁然开朗!
      • 5e0aebe855eb:先收藏
      • 剽悍一小兔:写得很详细,学习了
        Yi罐可乐:@剽悍一小兔 谢谢,第三篇已更新,欢迎来看看~
        准备好好再整理下同步到 GitHub 上,以后如果有更新也会同步到上去
        https://github.com/zaxlct/javascript-tutorial 嘿嘿。

      本文标题:最详尽的 JS 原型与原型链终极详解,没有「可能是」。(二)

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