一张图看透JavaScript原型关系!!

原创 老姚 随笔 我也来说说系列 2932阅读 2017-05-14 18:02:04 举报

原型关系图

问:函数岂不是拥有两个原型?
答:是的,函数有两个原型proto和prototype。
因为函数是对象,而对象就有原型,其原型就是proto。函数是Function的实例,所以此原型就是Function.prototype。
而函数的prototype,不是给自己用的,而是给自己实例用的。

问:到底是构造函数有原型,还是实例有原型?
答:关键是这个“有”字怎么解释。说白了,就是拥有权和使用权的区分。平常我们说话时,并不仔细区分二者。
就像我们经常会说,“你的公司在哪里?”,但我们都知道,公司并不是你的,是属于董事会的,你只是在那上班罢了。
又比如,你有辆跑车,但你从来不开它,却给你的亲朋好友开。你有拥有权,但没使用权。相反,你的好友虽没有拥有权,但有使用权。
从一般语义上来说,构造函数拥有原型,放在自身prototype上,但不是给自身用的,而是给它的实例用的。
从JS的语义上来说,实例对象拥有原型,其内部属性[[prototype]](即proto指向)指向构造器的prototype。
另外一点,拥有权是独占的,而使用权是共享的。
因此某一个构造函数的不同实例的原型是同一个。

问:原型链的终点是什么?
答:Object.prototype。它是个对象,它的原型是null。

问:函数都是Function的实例,而Function也是函数,它是谁的实例?
答:它是自身的实例。所以它的proto与自身的prototype是同一个东西。而且是个函数,此函数不再有prototype,但是作为对象,它的proto是Object.prototype。这是系统内置好的。
Function是Function自身的实例,对此,很多人都会感觉不可思议。不过想想另外一个不可思议的事情就理解了。它是:
我们竟然可以用大脑来指挥自己的大脑如何思考!

问:Object.proto和Object.prototype是什么关系?
答:后者是前者的原型。因为Object是函数,是Function的实例,因此Object.proto就是Function.prototype,所以后者是前者的原型。

评论 ( 17 )
最新评论
folat 14F 2017-10-12 18:05:05 17F

好的,谢谢解答

老姚 15F 2017-09-22 19:01:39 16F

谢谢支持

dqleo 2017-09-22 15:57:44 15F

我是来点赞的

老姚 13F 2017-09-15 05:31:01 14F

《你不知道的javascript》讲的挺细的。另外也不妨看一下我的原型本质系列,觉得大致得很说清楚了。

folat 12F 2017-09-14 16:46:04 13F

有点懵,是不是因为对象是通过构造函数来创建的所以才有了这层关系?如果是字面量的方式定义对象是不是就没有了

老姚 11F 2017-09-14 16:25:21 12F

文中也强调了一下,函数有两个原型。一个是prototype,一个是proto
你说的“Array.prototype是直接指向Object.prototype”这是没问题的。
我说的“Array.proto是Function.prototype”也是没问题的。
我说的Array的原型是Function.prototype,是指第二种语境下的意义。
是说Array是个函数,函数又是个对象,对象就该有原型吧,那么它的原型是什么呢?

folat 10F 2017-09-14 16:07:28 11F

MDN上的一段:

var o = {a: 1};

// o这个对象继承了Object.prototype上面的所有属性
// 所以可以这样使用 o.hasOwnProperty('a').
// hasOwnProperty 是Object.prototype的自身属性。
// Object.prototype的原型为null。
// 原型链如下:
// o ---> Object.prototype ---> null

var a = ["yo", "whadup", "?"];

// 数组都继承于Array.prototype
// (indexOf, forEach等方法都是从它继承而来).
// 原型链如下:
// a ---> Array.prototype ---> Object.prototype ---> null

function f(){
return 2;
}

// 函数都继承于Function.prototype
// (call, bind等方法都是从它继承而来):
// f ---> Function.prototype ---> Object.prototype ---> null

老姚 9F 2017-09-14 15:38:48 10F

A的原型是B,是说A.proto 是B。而不是指A的prototype。。。

folat 2017-09-14 15:26:49 9F

Array.prototype是直接指向Object.prototype,不经过Function.prototype的吧,其他类型的对象也是(除了Function本身)

老姚 7F 2017-05-23 18:41:40 8F

多看书,以上观点可能来自于《必然》、《批评性思维》。要忘记观点的出处,只有做到这点,才算内心真正认可,那才是自己的。谁说过类似的话,从谁那得到又何妨。这是nlp复制超越术,一切唯我所用,练就化功大法,练就自己的写轮眼。

729278592 4F 2017-05-23 17:32:59 7F

姚老哲学贼强 --在哪抄的

老姚 5F 2017-05-22 18:40:48 6F

此说法没毛病,一般书上也都是这么说的。

Lin_Grady 2017-05-22 18:04:02 5F

老觉得回答怪怪的,最近也在研究这方面的东西,从另一个说法解释一下吧.
簡單說構造函數、原型和實例的關係:每個構造函數都有一個原型對象,原型對象都包含一個指向構造函數的指針,而實例都包含一個指向原型對象的內部指針。

老姚 3F 2017-05-19 12:47:09 4F

表达观点,但不献身。你这一句平常的话让我想了很多。
1.分享是必然,因为信息的本质就是为了复制。
2.每个分享者,都有自己的局限,分享的东西可大可小。有时也会出错,但我相信当事人最起码认为当下分享是对的。
3.至于无私,是做不到的,我写东西本质还是让自己更好的学习。共赢始终是最好的,没达到也无妨,最起码自己有收获的。这让我想起了阮一峰,他把es6一书开源,一种共赢。
4.最应该感谢的是读者,因为注意力是稀缺的资源,你写的东西,人家点进来看两眼,都是对注意力的消费。更何况,有人认真读,并提出疑问呢。某种程度就是对作者的帮助。
5.观点错误怎么办?见到作者说错了,还是要质疑的,哪怕跟自己的理解不一样也要质疑一下,弄不好修正了自己的看法
6.观点不是人,只是个所有品,只是个工具。可以修正,可以舍弃,可以强化,也可以任人太挑战。这是《批判性思维》的一个核心价值观。

aaawhz 2017-05-19 10:15:46 3F

感谢楼主无私献身的精神

老姚 1F 2017-05-18 10:01:33 2F

我们可以看看阮一峰是怎么说的。
http://es6.ruanyifeng.com/#docs/object#__proto__属性

melongz 2017-05-17 23:40:34 1F

proto是原型链,并不是原型,但是proto === 构造函数的原型prototype