美文网首页
__ptoto__和prototype

__ptoto__和prototype

作者: 雷神的铁粉 | 来源:发表于2019-01-14 17:54 被阅读0次

    1994年,网景公司(Netscape)发布了Navigator浏览器0.9版,但是刚开始的Js没有继承机制,更别提像同时期兴盛的C++和Java这样拥有面向对象的概念。在实际的开发过程中,工程师们发现没有继承机制很难解决一些问题,必须有一种机制能将所有的对象关联起来。Brendan Eich鉴于以上情况,但不想把Js设计得过为复杂,于是引入了new关键词 和 constructor构造函数来简化对象的设计,引入了prototype函数对象来包含所有实例对象的构造函数的属性和方法,引入了proto和原型链的概念解决继承的问题。

    介绍

    __proto__

    引用《JavaScript权威指南》的一段描述:

    Every JavaScript object has a second JavaScript object (or null ,
    but this is rare) associated with it. This second object is known as a prototype, and the first object inherits properties from the prototype.

    翻译出来就是每个JS对象一定对应一个原型对象,并从原型对象继承属性和方法。好啦,既然有这么一个原型对象,那么对象怎么和它对应的?

    对象__proto__属性的值就是它所对应的原型对象:

    var a = {x: 1};
    var b = new Object();
    a.__proto__ === Object.prototype // true
    b.__proto__ === Object.prototype // true
    one.toString === one.__proto__.toString // true
    

    上面的代码应该已经足够解释清楚__proto__了。好吧,显然还不够,或者说带来了新的问题:Object.prototype是什么?凭什么说onetwo的原型就是Object.prototype

    prototype

    首先来说说prototype属性,不像每个对象都有__proto__属性来标识自己所继承的原型,只有函数才有prototype属性。

    为什么只有函数才有prototype属性?ES规范就这么定的。

    开玩笑了,其实函数在JS中真的很特殊,是所谓的一等公民。JS不像其它面向对象的语言,它没有类(class,ES6引进了这个关键字,但更多是语法糖)的概念。JS通过函数来模拟类。

    当你创建函数时,JS会为这个函数自动添加prototype属性,值是空对象 值是一个有 constructor 属性的对象,不是空对象。而一旦你把这个函数当作构造函数(constructor)调用(即通过new关键字调用),那么JS就会帮你创建该构造函数的实例,实例继承构造函数prototype的所有属性和方法(实例通过设置自己的__proto__指向承构造函数的prototype来实现这种继承)。

    小结

    1.每个函数对象都有一个 prototype 属性,这个属性就是函数的原型对象。
    2.原型链是JavaScript实现继承的重要方式,原型链的形成是真正是靠proto 而非prototype
    3.原型链所形成的过程可以以下解释:

    arr ---> Array.prototype ---> Object.prototype ---> null
    

    js所说的原型链,就是层层向上查找,最后没有时就返回undefined,
    使用new创建一个的对象时,函数对应的prototype方法,数据的prototype方法的上一层(prototype.proto)就是object对象的prototype方法。直接的可以理解为:

    var 对象 = new 函数()
    对象.__proto__ === 函数.prototype
    

    而.__proto一层一层的指向就可以被称为原型链。
    由此也可以引出以下几个推论:

    // 推论
    var number = new Number()
    number.__proto__ = Number.prototype
    Number.__proto__ = Function.prototype // 因为 Number 是 Function 的实例
    
    var object = new Object()
    object.__proto__ = Object.prototype
    Object.__proto__ = Function.prototype // 因为 Object 是 Function 的实例
    
    var function = new Function()
    function.__proto__ = Function.prototype
    Function.__proto__ == Function.prototye // 因为 Function 是 Function 的实例!
    

    探讨

    我们知道JS是单继承的,Object.prototype是原型链的顶端,所有对象从它继承了包括toString等等方法和属性。

    Object本身是构造函数,继承了Function.prototype;Function也是对象,继承了Object.prototype。这里就有先有鸡和先有蛋的问题:

    Object instanceof Function // true
    Function instanceof Object // true
    

    什么情况下会出现鸡和蛋的问题呢?就是声明一个包含所有集合的集合啊!好了,你们知道这是罗素悖论,但并不妨碍PL中这样设计。

    那么具体到JS,ES规范是怎么说的?

    Function本身就是函数Function.__proto__是标准的内置对象Function.prototype

    Function.prototype.__proto__是标准的内置对象Object.prototype

    参考链接:
    1.JavaScript深入之从原型到原型链

    相关文章

      网友评论

          本文标题:__ptoto__和prototype

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