图来源于:http://www.cnblogs.com/smoothLily/p/4745856.html

个人的理解:

1. 所有对象都有 __proto__属性,返回该对象的原型对象。例如f1由语句var f1 = new Foo()生成,那么f1.__proto__就是由构造函数Foo生成的原型对象Foo.prototype.

f1.__proto__ === Foo.prototype; //true

2. 所有函数具有prototype属性,这是一个指针,指向函数所生成对象的原型对象。Foo.prototype就是由 new Foo()函数所生成的这一类对象的原型,原型是可以被修改的:

function Foo(){};
var f1 = new Foo();
Foo.prototype.name = "emily";
f1.name; // "emily"

如上代码所示,先生成对象f1,然后修改其对象原型,给它增加了一个name属性。f1因此也有了name属性。

3. 但是函数也是一种对象,因此它也有__proto__属性,即也有其原型对象。对于函数(对象)Foo来说:

Foo.__proto__ === Function.prototype; // true

Function.prototype就是由new Function()所生成的这一类对象的原型。

函数(对象)Foo的原型正是由Function函数所生成的原型。

4. JavaScript的内置函数如Function, Object, Array, Date等,都既是构造函数,又是对象,因此他们都有prototype和__proto__属性。

不同的是prototype指向的是其本身作为构造函数作用时所生成的对象的原型对象

而__proto__属性是返回其本身作为对象的原型对象

Function.__proto__ === Function.prototype; //true
Array.__proto__ === Function.prototype; //true
Date.__proto__ === Function.prototype; //true
Object.__proto__ === Function.prototype; //true
Foo.__proto__ === Function.prototype; //true

5. 如上所示,所有(构造函数)对象的原型对象都是Function.prototype,这也是一个对象,在console中查看该对象,发现它返回的是一个空函数:

Function.prototype.toString(); // 返回"function () {}"

那么这个对象有没有原型对象呢,它的__proto__返回什么呢?

Function.prototype.__proto__ === Object.prototype; // true

所以

Function.__proto__.__proto__ === Object.prototype; // true

Array.__proto__.__proto__ === Object.prototype; // true
Date.__proto__.__proto__ === Object.prototype; // true
Object.__proto__.__proto__ === Object.prototype; // true
Foo.__proto__.__proto__ === Object.prototype; // true

6. Object.prototype也是一个对象,因此其__proto__属性返回:

Object.prototype.__proto__; // null

因此

Function.__proto__.__proto__.__proto__; // null
Array.__proto__.__proto__.__proto__; // null
Date.__proto__.__proto__.__proto__; // null
Object.__proto__.__proto__.__proto__; // null
Foo.__proto__.__proto__.__proto__; // null
f1.__proto__.__proto__.__proto__; // null

任何对象向上回溯最终都会到null。

7. 关于原型对象的constructor属性:每个函数对象都有名为“prototype”的属性,用于引用原型对象。此原型对象又有名为“constructor”的属性,它反过来引用函数本身。这是一种循环引用

Foo.prototype.constructor === Foo; //true

总结:理解这个概念的关键点就在于,__proto__是对象的属性,是用来向上查找其原型对象的。

而prototype是函数的属性,其作用指向该构造函数所生成对象的原型。

此外在stackoverflow上对这个问题的回答很有意思:

__proto__ is the actual object that is used in the lookup chain to resolve methods, etc.

prototype is the object that is used to build __proto__ when you create an object with new:

(new Foo).__proto__ === Foo.prototype; // 函数调用prototype属性用来构造对象原型

(new Foo).prototype === undefined; // 对象没有prototype属性
 

JavaScript: __proto__和prototype的更多相关文章

  1. JavaScript - __proto__和prototype,原形

    参考 https://stackoverflow.com/questions/9959727/proto-vs-prototype-in-javascript 区别 构造函数中的prototype创建 ...

  2. JavaScript中__proto__与prototype的关系

    一.所有构造器/函数的__proto__都指向Function.prototype,它是一个空函数(Empty function) 1 2 3 4 5 6 7 8 9 Number.__proto__ ...

  3. 15条规则解析JavaScript对象布局(__proto__、prototype、constructor)

    大家都说JavaScript的属性多,记不过来,各种结构复杂不易了解.确实JS是一门入门快提高难的语言,但是也有其他办法可以辅助记忆.下面就来讨论一下JS的一大难点-对象布局,究竟设计JS这门语言的人 ...

  4. javascript--15条规则解析JavaScript对象布局(__proto__、prototype、constructor)

    大家都说JavaScript的属性多,记不过来,各种结构复杂不易了解.确实JS是一门入门快提高难的语言,但是也有其他办法可以辅助记忆.下面就来讨论一下JS的一大难点-对象布局,究竟设计JS这门语言的人 ...

  5. 对于JavaScript对象的prototype和__proto__的理解

    一.Object和Function的关系: 刚学JavaScript的时候,看书上说JavaScript中万物皆对象,而javascript中的其他对象都是从Object继承而来,包括内置对象.瞬间觉 ...

  6. Javascript中的__proto__、prototype、constructor

    今天重温了下Javacript,给大家带来一篇Javascript博文,相信对于Javacript有一定了解的人都听过prototype原型这个概念,今天我们深度的分析下prototype与__pro ...

  7. JavaScript中的prototype和__proto__细致解析

    最近在学js,体会了一点点它的灵活性.对于初学者的我,总是被它的灵活感到晕头转向,最近发现了一点东西想与大家分享. JavaScript中的prototype和_proto_: 我们先了解一点js中的 ...

  8. JavaScript:Function/Object/prototype/__proto__

    console.log(Object.__proto__===Function.prototype); //true console.log(Object.prototype.__proto__); ...

  9. javascript中构造器(函数)的__proto__与prototype初探

    背景:最近没什么需求,快要闲出屁了,所以重温了一下js的原型,结果大有收获,且偶然看到Snandy大神的<JavaScript中__proto__与prototype的关系> 这篇文章,感 ...

随机推荐

  1. cms-友情链接实现静态化

    service: package com.open1111.service.impl; import java.util.List; import javax.servlet.ServletConte ...

  2. VMware-Ubuntu16.04LTS-安装ssh

    1,检查是否安装ssh 2,安装ssh

  3. 修改CAS实现控制某个用户在定义的时间内登录次数

    思想: 在数据库增加字段  1.登录次数 2.登录失败时间(类型TimeStamp) 当一个用户进来认证的时候当登录失败的时候更新登录次数 和最后登录失败的时间. 主要是在登录成功或者失败的时候判断时 ...

  4. UVA Mega Man's Mission(状压dp)

    把消灭了那些机器人作为状态S,预处理出状态S下可以消灭的机器人,转移统计方案.方案数最多16!,要用64bit保存方案. #include<bits/stdc++.h> using nam ...

  5. python_73_pickle序列化(接72)

    # json(为字符串形式)用于不同语言之间的数据交互,只适用于简单的数据交互,字典之类可以,函数就不行了,如下例 ''' import json def say(name):print('Hi!', ...

  6. C#的接口基础教程之六 接口转换

    C#中不仅支持.Net 平台,而且支持COM平台.为了支持 COM和.Net,C# 包含一种称为属性的独特语言特性.一个属性实际上就是一个 C# 类,它通过修饰源代码来提供元信息.属性使 C# 能够支 ...

  7. MyElipes遇到 source not found解决方案

    在用Myeclipse 或者是eclipse进行开发时候经常遇到这个问题. File class editor  source not found问题.原因很简单,就是因为这是一个源码包,相应的没有编 ...

  8. JavaScript 日期权威指南

    简介 JavaScript通过强大的对象为我们提供日期处理功能:日期. 本文确实_不是_谈论 Moment.js ,我认为它是处理日期的最佳库,你应该在处理日期时几乎总是使用它. Date对象 Dat ...

  9. 三 python并发编程之多线程-理论

    一 什么是线程 在传统操作系统中,每个进程有一个地址空间,而且默认就有一个控制线程 线程顾名思义,就是一条流水线工作的过程,一条流水线必须属于一个车间,一个车间的工作过程是一个进程 车间负责把资源整合 ...

  10. vue.js 二 路由懒加载

    当项目小的时候,我没考虑要去找这个得解决方案,也幸好现在几乎能迁移的项目都整合在了一个vue的项目里面 才发现编译后的vendor.js变得异常的大,而且几乎在项目每一个页面都需要加载这一个js,项目 ...