Object.prototype.__proto__, [[prototype]] 和 prototype
Object.prototype.__proto__ , [[prototype]] 和 prototype
Object.prototype.__proto__ 是什么?
__proto__是一个访问器属性, 用于访问对象的原型[[prototype]](见以下模拟的getter和setter方法, 不一定完全与规范一致, 仅供参考)get Object.prototype.__proto__get __proto__() {
// Let O be ? ToObject(this value).
if(this === void(0) || this === null) {
throw TypeError(`Cannot read property '__proto__' of ${this}`);
}
let O = Object(this); // this !== null 或 undefined 时, Return ! ToObject(value);
// Return ? O.[[GetPrototypeOf]]().
return Object.getPrototypeOf(O);
}
set Object.prototype.__proto__set __proto__(proto) {
// Let O be ? RequireObjectCoercible(this value).
if(this === void(0) || this === null) {
throw TypeError(`Cannot set property '__proto__' of ${this}`);
}
let O = this; // this !== null 或 undefined 时, return argument;
// If Type(proto) is neither Object nor Null, return undefined.
if (typeof proto !== 'object') { // typeof null === 'object'
return;
}
// If Type(O) is not Object, return undefined.
if (typeof O !== 'object') { // O !== null 或 undefined
return;
}
// Let status be ? O.[[SetPrototypeOf]](proto).
// If status is false, throw a TypeError exception.
// Return undefined.
Object.setPrototypeOf(O, proto);
return;
}
通过它可以访问到对象的
[[prototype]], 也即对象的原型[[prototype]]的值是该对象的原型或null(对于 Object.prototype 对象而言, 其没有原型, 返回null:Object.prototype.__proto__; // null)
[[prototype]] 和 prototype 的关系
举个例子 (一定要举起来啊!):
class Person {
    constrctor(name, age) {
        this.name = name;
    }
}
let p1 = new Person('ayu');
// 对于实例 p1 来说, 它的原型 [[prototype]] 是 Person 对象的 prototype 属性值. 也即实例 p1 的原型是 Person.prototype
Object.getPrototypeOf(p1) === Person.prototype;  // true
// 顺便再说下 constructor
// 实例由原型中的 constructor 属性值构造, 也即实例 p1 由 Person (Object.getPrototypeOf(p).constructor) 构造
Object.getPrototypeOf(p1).constructor === Person;  // true
p1.constructor === Person;  // true
// 实例与 constructor 的关系为 n : 1, 因此每个实例的构造器均指向 Person
let p2 = new Person('ayu2');
p1.constructor === p2.constructor;  // true
// 任何函数都是由 Function 构造的, 比如 Object, Person 等, 比较特殊的是: Function.constructor === Function
Person.constructor === Function;  // true
Function.constructor === Function;  // true
// 再来说下原型链
// Function.protype 是任何函数的原型, 比如 Object, Person 等, 比较特殊的是 Object.getPrototypeOf(Function) === Function.prototype
Object.getPrototypeOf(Person) === Function.prototype;  // true
Object.getPrototypeOf(Function) === Function.prototype;  // true
// 最后, 任何原型的原型最终都追溯到 Object.prototype 或 null. 这形成了一个链式结构, 它被叫做原型链
Object.getPrototypeOf(Person.prototype) === Object.prototype;  // true
Object.getPrototypeOf(Object.getPrototypeOf(Person)) === Object.prototype;  // true
Object.getPrototypeOf(Function.prototype) === Object.prototype;  // true
Object.getPrototypeOf(Object.getPrototypeOf(Object)) === Object.prototype;  // true
Object.getPrototypeOf(Object.prototype) === null;  // true
综上, [[prototype]] 表示了一个实例的原型 (prototype 属性的值表示了其实例的原型对象), 对象与对象之间通过 [[prototype]] 关联了起来, 形成了一个链式结构 --- 原型链. 如果没把例子举起来, 是我不会讲故事, 请点这里)看图理解.
为什么不推荐使用它?
- 虽然所有现代浏览器都实现了该访问器属性. ES6 (ECMA2015) 及之后的标准也暂时包含了它, 它的存在只是为了确保规范与浏览器兼容
 - 操作 
[[prototype]]属性 (只要该属性变更了), 各个浏览器引擎针对prototype相关的优化会失效, 这就导致访问原型上的属性很慢 
如果不得不使用呢?
推荐使用
Object.getPrototypeOf()方法代替Object.prototype.__proto__虽然原型只是对象,但它们由 JavaScript 引擎专门处理,以优化在原型上查找方法的性能表现。把你的原型放在一旁!或者,如果你确实需要修改原型,请在其他代码运行之前执行此操作,这样至少不会让引擎所做的优化付诸东流。
JavaScript 中谁不能访问到 Object.prototype.__proto__?
- 原型链上没有 
Object.prototype对象的对象, 均不能访问- 比如使用 
Object.create(null)创建的对象或我们变更了其原型的对象obj.__proto__ = null, 该类对象不能访问Object.prototype.__proto__(但我们可以通过Object.getPrototypeOf(obj)访问其原型:Object.getPrototypeOf(Object.create(null)); // null) 
 - 比如使用 
 - 没有原型的原始值
- 一般来说, 
null,undefined,number,string,boolean,symbol,bigint这些基本数据类型的 (原始) 值没有原型 (Object.getPrototypeOf(null); // TypeError: Cannot convert undefined or null to object, 原始值不可能有原型), 所以其无法访问到Object.prototype.__proto__. 但鉴于除了null,undefined以外的基本数据类型值在运算时会自动装箱 autoboxing 为对应的包装对象, 所以只有null和undefined不能访问到Object.prototype.__proto__ 
 - 一般来说, 
 
Object.prototype.__proto__ 的值是 null, 然后呢?
众所周知, Object.prototype.__proto__ 的值是 null, 通常来说也是一个对象的原型链终点, 它表示了 Object.prototype 对象没有原型. 附一张图 (图片来源于这里):

这张图说明了 JavaScript 的继承 (委托): new Foobar --- __proto__ ---> Foobar.prototype --- __proto__ ---> Object.prototype --- __proto__ ---> null.
(用《你不知道的JavaScript》里的话来说: 继承意味着复制操作,然而 JavaScript 默认并不会复制对象的属性,相反,JavaScript 只是在两个对象之间创建一个关联,这样,一个对象就可以通过委托访问另一个对象的属性和函数,所以与其叫继承,委托的说法反而更准确些.)
Object.prototype.__proto__, [[prototype]] 和 prototype的更多相关文章
- Javascript中Function,Object,Prototypes,__proto__等概念详解
		
http://anykoro.sinaapp.com/2012/01/31/javascript%E4%B8%ADfunctionobjectprototypes__proto__%E7%AD%89% ...
 - JavaScript:Function/Object/prototype/__proto__
		
console.log(Object.__proto__===Function.prototype); //true console.log(Object.prototype.__proto__); ...
 - Object & prototype & __proto__ All In One
		
Object & prototype & proto All In One js 原型,原型链,原型对象 const obj ={}; // {} const obj = new Ob ...
 - js & object & prototype & __proto__ & prototype chain
		
js & object & prototype & proto & prototype chain constructor prototype === instance ...
 - 关于 JavaScript prototype __proto__ 一点总结
		
http://www.cnblogs.com/wbin91/p/5265163.html 先上代码 function(y) Foo{ this.y = y;} Foo.prototype.x = 10 ...
 - javascript prototype __proto__区别
		
An Object's __proto__ property references the same object as its internal [[Prototype]] (often refer ...
 - Javascript Prototype __proto__ constructor 三者的关系
		
JavaScript三大毒瘤 --- this,原型链,作用域 在我等菜鸟一步一步升级中的过程中,这三个概念总是困扰这我们(可能只有我吧,我比较蠢).这三个东西往往都很绕,今天我就来分享一下我对原型. ...
 - 深入理解JavaScript原型:prototype,__proto__和constructor
		
JavaScript语言的原型是前端开发者必须掌握的要点之一,但在使用原型时往往只关注了语法,其深层的原理并未理解透彻.本文结合笔者开发工作中遇到的问题详细讲解JavaScript原型的几个关键概念, ...
 - 基础知识点 关于 prototype  __proto__
		
基础知识点 关于 prototype __proto__ 供js新手参考 JavaScript 的一些基础知识点: 在 JavaScript 中,所有对象 o 都拥有一个隐藏的原型对象(在 Fire ...
 
随机推荐
- Web优化躬行记(1)——CSS
			
Web优化的对象包括页面性能.用户体验.开发效率.代码优化.网络延迟等,本系列会列举出众多常用的优化技巧,每个技巧都可深入分析,在此只做抛砖引玉. 本系列优化内容提炼于<前端面试宝典>.& ...
 - 微信小程序 springboot nginx 做图片存储 上传 浏览
			
微信小程序前端-springboot后端-nginx图片存储 前言 本人小白一名,这是第一次学习微信小程序,特此做个记录. 首先准备nginx做图片存储 选择一个地址存放图片 #我的地址 [root@ ...
 - django-rest-framework-源码解析004-三大验证(认证/权限/限流)
			
三大验证模块概述 在DRF的APIView重写的dispatch方法中, self.initial(request, *args, **kwargs) 这句话就是执行三大验证的逻辑, 点进去可以看到 ...
 - C#程序员装机必备软件及软件地址
			
装机必备 Visio2010 下载 http://gd.ddooo.com/visio2010_12530.rar Office 安装包 http://xz.cncrk.com:8080/soft/k ...
 - MySQL组复制MGR(一)-- 技术概述
			
(一)复制技术的发展 MySQL的复制技术主要经历了异步主从复制,半同步复制,组复制(Group Replication)3个阶段. (1)传统的异步主从复制 传统的MySQL提供了一种简单的主从复制 ...
 - 一个使用android相机的例子,二维码必须用相机
			
https://blog.csdn.net/feiduclear_up/article/details/51968975
 - 【扩展推荐】Intervention/image 图片处理
			
Intervention/image 是为 Laravel 定制的图片处理工具, 它提供了一套易于表达的方式来创建.编辑图片. 一.环境要求 二.安装及配置 下载地址:https://packagis ...
 - shell脚本报错:-bash: xxx: /bin/sh^M: bad interpreter: No such file or directory
			
今天执行一个shell脚本,然后在执行的时候报错,脚本内容很简单,仅供测试: #!/bin/sh echo "test shell " 具体报错信息如下 [root@localho ...
 - 使用Spring Validation优雅地校验参数
			
写得好的没我写得全,写得全的没我写得好 引言 不知道大家平时的业务开发过程中 controller 层的参数校验都是怎么写的?是否也存在下面这样的直接判断? public String add(Use ...
 - 定义 WSGI 接口
			
# WSGI服务器调用 def application(environ,start_response): start_response('200 OK',[('Content-Type','text/ ...