aboutsummaryrefslogtreecommitdiff
path: root/files/zh-cn/web/javascript/reference/global_objects/object/proto/index.html
blob: d0ac7d3eb6798512e3ae88e687d4ef0dc533356e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
---
title: Object.prototype.__proto__
slug: Web/JavaScript/Reference/Global_Objects/Object/proto
tags:
  - ECMAScript 2015
  - JavaScript
  - Object
  - Property
  - Prototype
  - Reference
translation_of: Web/JavaScript/Reference/Global_Objects/Object/proto
---
<div>{{JSRef}}{{Deprecated_header}}</div>

<div class="warning">
<p><strong>警告:</strong> 通过现代浏览器的操作属性的便利性,可以改变一个对象的 <code>[[Prototype]]</code> 属性, 这种行为在每一个JavaScript引擎和浏览器中都是一个非常慢且影响性能的操作,使用这种方式来改变和继承属性是对性能影响非常严重的,并且性能消耗的时间也不是简单的花费在 <code>obj.__proto__ = ...</code> 语句上, 它还会影响到所有继承来自该 <code>[[Prototype]]</code> 的对象,如果你关心性能,你就不应该在一个对象中修改它的 [[Prototype]]。相反, 创建一个新的且可以继承 <code>[[Prototype]]</code> 的对象,推荐使用 {{jsxref("Object.create()")}}</p>
</div>

<div class="warning">
<p><strong>警告:</strong><code>Object.prototype.__proto__</code> 已被大多数浏览器厂商所支持的今天,其存在和确切行为仅在ECMAScript 2015规范中被标准化为传统功能,以确保Web浏览器的兼容性。为了更好的支持,建议只使用 {{jsxref("Object.getPrototypeOf()")}}</p>
</div>

<div>{{jsxref("Object.prototype")}} 的 <code>__proto__</code>  属性是一个访问器属性(一个getter函数和一个setter函数), 暴露了通过它访问的对象的内部<code>[[Prototype]]</code> (一个对象或 {{jsxref("Global_Objects/null", "null")}})。</div>

<div></div>

<p>使用<code>__proto__</code>是有争议的,也不鼓励使用它。因为它从来没有被包括在EcmaScript语言规范中,但是现代浏览器都实现了它。<code>__proto__</code>属性已在ECMAScript 6语言规范中标准化,用于确保Web浏览器的兼容性,因此它未来将被支持。它已被不推荐使用, 现在更推荐使用{{jsxref("Object.getPrototypeOf")}}/{{jsxref("Reflect.getPrototypeOf")}}{{jsxref("Object.setPrototypeOf")}}/{{jsxref("Reflect.setPrototypeOf")}}(尽管如此,设置对象的[[Prototype]]是一个缓慢的操作,如果性能是一个问题,应该避免)。</p>

<p>__proto__ 属性也可以在对象文字定义中使用对象[[Prototype]]来创建,作为{{jsxref("Object.create()")}} 的一个替代。 请参阅: <a href="/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer">object initializer / literal syntax</a>.</p>

<h2 id="语法">语法</h2>

<pre class="brush: js">let Circle = function () {};
let shape = {};
let circle = new Circle();

// 设置该对象的原型链引用
// 过时且不推荐使用的。这里只是举个例子,尽量不要在生产环境中这样做。
shape.__proto__ = circle;

// 判断该对象的原型链引用是否属于circle
console.log(shape.__proto__ === circle); // true
</pre>

<pre class="brush: js">let shape = function () {};
let p = {
    a: function () {
        console.log('aaa');
    }
};
shape.prototype.__proto__ = p;

let circle = new shape();
circle.a();//aaa
console.log(shape.prototype === circle.__proto__);//true

//或者
let shape = function () {};
var p = {
    a: function () {
        console.log('a');
    }
};

let circle = new shape();
circle.__proto__ = p;
circle.a(); //  a
console.log(shape.prototype === circle.__proto__);//false

//或者
function test() {}
test.prototype.myname = function () {
    console.log('myname');
}
let a = new test()
console.log(a.__proto__ === test.prototype);//true
a.myname();//myname

//或者
let fn = function () {};
fn.prototype.myname = function () {
    console.log('myname');
}

let obj = {
    __proto__: fn.prototype
};

obj.myname();//myname
</pre>

<p>注意:这是两个下划线,后面是五个字符的 “proto” ,后面再跟两个下划线。</p>

<h2 id="描述">描述</h2>

<p>__proto__的读取器(getter)暴露了一个对象的内部 <code>[[Prototype]]</code> 。对于使用对象字面量创建的对象,这个值是 {{jsxref("Object.prototype")}}。对于使用数组字面量创建的对象,这个值是 {{jsxref("Array.prototype")}}。对于functions,这个值是{{jsxref("Function.prototype")}}。对于使用 new fun 创建的对象,其中fun是由js提供的内建构造器函数之一({{jsxref("Array")}}, {{jsxref("Boolean")}}, {{jsxref("Date")}}, {{jsxref("Number")}}, {{jsxref("Object")}}, {{jsxref("String")}} 等等),这个值总是fun.prototype。对于用js定义的其他js构造器函数创建的对象,这个值就是该构造器函数的prototype属性。</p>

<p>__proto__ 的设置器(setter)允许对象的 <code>[[Prototype]]被变更。前提是这个对象必须通过</code> {{jsxref("Object.isExtensible()")}} 判断为是可扩展的,如果不可扩展,则会抛出一个 {{jsxref("Global_Objects/TypeError", "TypeError")}} 错误。要变更的值必须是一个object或{{jsxref("Global_Objects/null", "null")}},提供其它值将不起任何作用。</p>

<p>要理解原型如何被使用,请查看相关文章:<a href="/en-US/docs/Web/JavaScript/Guide/Inheritance_and_the_prototype_chain">Inheritance and the prototype chain</a></p>

<p>.__proto__属性是{{jsxref("Object.prototype")}} 一个简单的访问器属性,其中包含了get(获取)和set(设置)的方法,任何一个__proto__的存取属性都继承于{{jsxref("Object.prototype")}},但一个访问属性如果不是来源于{{jsxref("Object.prototype")}}就不拥有.__proto__属性,譬如一个元素设置了其他的.__proto__属性在{{jsxref("Object.prototype")}}之前,将会覆盖原有的{{jsxref("Object.prototype")}}</p>

<h2 id="规范">规范</h2>

<table class="standard-table">
 <tbody>
  <tr>
   <th scope="col">Specification</th>
   <th scope="col">Status</th>
   <th scope="col">Comment</th>
  </tr>
  <tr>
   <td>{{SpecName('ES6', '#sec-additional-properties-of-the-object.prototype-object', 'Object.prototype.__proto__')}}</td>
   <td>{{Spec2('ES6')}}</td>
   <td>Included in the (normative) annex for additional ECMAScript legacy features for Web browsers (note that the specification codifies what is already in implementations).</td>
  </tr>
  <tr>
   <td>{{SpecName('ESDraft', '#sec-additional-properties-of-the-object.prototype-object', 'Object.prototype.__proto__')}}</td>
   <td>{{Spec2('ESDraft')}}</td>
   <td></td>
  </tr>
 </tbody>
</table>

<h2 id="浏览器兼容情况">浏览器兼容情况</h2>

<p>{{Compat("javascript.builtins.Object.proto")}}</p>

<h2 id="兼容性注意事项">兼容性注意事项</h2>

<p>在 ECMAScript 2015(ES6)的规范要求中,支持<code>__proto__</code> 是各大Web浏览器厂商的要求(虽然符合规范),但其他环境下因为历史遗留的问题,也有可能被使用和支持。 </p>

<h2 id="更多请参考">更多请参考</h2>

<ul>
 <li>{{jsxref("Object.prototype.isPrototypeOf()")}}</li>
 <li>{{jsxref("Object.getPrototypeOf()")}}</li>
 <li>{{jsxref("Object.setPrototypeOf()")}}</li>
</ul>