aboutsummaryrefslogtreecommitdiff
path: root/files/zh-tw/web/javascript/reference/global_objects/object/proto/index.html
blob: ebb05d1e1d4bde3b8541fa11149d871d5f1c550b (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
---
title: Object.prototype.__proto__
slug: Web/JavaScript/Reference/Global_Objects/Object/proto
translation_of: Web/JavaScript/Reference/Global_Objects/Object/proto
---
<div class="notecard warning">
<p><strong>Warning:</strong> 基於現代Javascript引擎最佳化物件屬性存取的方法,改變一個物件的 <code>[[Prototype]]</code> 在任何瀏覽器或是Javascript引擎都是非常慢的操作?。改變繼承屬性對效能的影響微妙且深遠,不僅僅只是影響執行 <code>obj.__proto__ = ...</code> 的時間,而是會影響到所有有存取到被改變 <code>[[Prototype]]</code> 的物件的程式碼的執行時間。如果你在乎效能的話就應該避免改變一個物件的 <code>[[Prototype]]</code> 。反之,請用 {{jsxref("Object.create()")}} 來產生一個擁有 <code>[[Prototype]]</code> 的物件。</p>
</div>

<div class="notecard warning">
<p><strong>Warning:</strong> 雖然 <code>Object.prototype.__proto__</code> 在今日已經被絕大部分的瀏覽器所支援,其存在與確切的行為只有在 ECMAScript 2015 規範才被標準化成一個歷史功能來確保相容性。為了更好的支援,建議使用{{jsxref("Object.getPrototypeOf()")}}</p>
</div>

<div>{{JSRef}}</div>

<p>The <code>__proto__</code> property of {{jsxref("Object.prototype")}} is an accessor property (a getter function and a setter function) that exposes the internal <code>[[Prototype]]</code> (either an object or {{jsxref("Global_Objects/null", "null")}}) of the object through which it is accessed.</p>

<p>The use of <code>__proto__</code> is controversial, and has been discouraged. It was never originally included in the EcmaScript language spec, but modern browsers decided to implement it anyway. Only recently, the <code>__proto__</code> property has been standardized in the ECMAScript 2015 language specification for web browsers to ensure compatibility, so will be supported into the future. It is deprecated in favor of {{jsxref("Object.getPrototypeOf")}}/{{jsxref("Reflect.getPrototypeOf")}} and {{jsxref("Object.setPrototypeOf")}}/{{jsxref("Reflect.setPrototypeOf")}} (though still, setting the <code>[[Prototype]]</code> of an object is a slow operation that should be avoided if performance is a concern).</p>

<p>The <code>__proto__</code> property can also be used in an object literal definition to set the object <code>[[Prototype]]</code> on creation, as an alternative to {{jsxref("Object.create()")}}. See: <a href="/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer">object initializer / literal syntax</a>.</p>

<h2 id="Syntax">Syntax</h2>

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

// Set the object prototype.
// DEPRECATED. This is for example purposes only. DO NOT DO THIS in real code.
shape.__proto__ = circle;

// Get the object prototype
console.log(shape.__proto__ === circle); // true
</pre>

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

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

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

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

// or
function test() {};
test.prototype.myname = function () {
    console.log('myname');
};

var a = new test();
console.log(a.__proto__ === test.prototype); // true
a.myname(); // myname


// or
var fn = function () {};
fn.prototype.myname = function () {
    console.log('myname');
};

var obj = {
    __proto__: fn.prototype
};

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

<p>Note: that is two underscores, followed by the five characters "proto", followed by two more underscores.</p>

<h2 id="Description">Description</h2>

<p>The <code>__proto__</code> getter function exposes the value of the internal <code>[[Prototype]]</code> of an object. For objects created using an object literal, this value is {{jsxref("Object.prototype")}}. For objects created using array literals, this value is {{jsxref("Array.prototype")}}. For functions, this value is {{jsxref("Function.prototype")}}. For objects created using <code>new fun</code>, where <code>fun</code> is one of the built-in constructor functions provided by JavaScript ({{jsxref("Array")}}, {{jsxref("Boolean")}}, {{jsxref("Date")}}, {{jsxref("Number")}}, {{jsxref("Object")}}, {{jsxref("String")}}, and so on — including new constructors added as JavaScript evolves), this value is always <code>fun.prototype</code>. For objects created using <code>new fun</code>, where <code>fun</code> is a function defined in a script, this value is the value of <code>fun.prototype</code>. (That is, if the constructor didn't return an other object explicitly, or the <code>fun.prototype</code> has been reassigned since the instance was created).</p>

<p>The <code>__proto__</code> setter allows the <code>[[Prototype]]</code> of an object to be mutated. The object must be extensible according to {{jsxref("Object.isExtensible()")}}: if it is not, a {{jsxref("Global_Objects/TypeError", "TypeError")}} is thrown. The value provided must be an object or {{jsxref("Global_Objects/null", "null")}}. Providing any other value will do nothing.</p>

<p>To understand how prototypes are used for inheritance, see guide article <a href="/en-US/docs/Web/JavaScript/Guide/Inheritance_and_the_prototype_chain">Inheritance and the prototype chain</a>.</p>

<p>The <code>__proto__</code> property is a simple accessor property on {{jsxref("Object.prototype")}} consisting of a getter and setter function. A property access for <code>__proto__</code> that eventually consults {{jsxref("Object.prototype")}} will find this property, but an access that does not consult {{jsxref("Object.prototype")}} will not find it. If some other <code>__proto__</code> property is found before {{jsxref("Object.prototype")}} is consulted, that property will hide the one found on {{jsxref("Object.prototype")}}.</p>

<h2 id="Specifications">Specifications</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('ES2015', '#sec-additional-properties-of-the-object.prototype-object', 'Object.prototype.__proto__')}}</td>
   <td>{{Spec2('ES2015')}}</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="Browser_compatibility">Browser compatibility</h2>

<div>


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

<h2 id="Compatibility_notes">Compatibility notes</h2>

<p>While the ECMAScript 2015 specification dictates that support for <code>__proto__</code> is required <em>only</em> for web browsers (although being normative), other environments may support it as well for legacy usage.</p>

<h2 id="See_also">See also</h2>

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