aboutsummaryrefslogtreecommitdiff
path: root/files/zh-tw/web/javascript/reference/global_objects/object/create/index.html
blob: b58f9173cd0b7a69cea383522219149e3f40be88 (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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
---
title: Object.create()
slug: Web/JavaScript/Reference/Global_Objects/Object/create
translation_of: Web/JavaScript/Reference/Global_Objects/Object/create
---
<div>{{JSRef}}</div>

<p><code><strong>Object.create()</strong></code> 指定其原型物件與屬性,創建一個新物件。</p>

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

<pre class="syntaxbox">Object.create(<var>proto</var>[, <var>propertiesObject</var>])</pre>

<h3 id="參數">參數</h3>

<dl>
 <dt><code>proto</code></dt>
 <dd>指定新物件的原型 (prototype) 物件。</dd>
 <dt><code>propertiesObject</code></dt>
 <dd>選用,為一物件。如有指定且非 {{jsxref("undefined")}},則此參數物件中可列舉出的屬性 (即參數物件自身定義的屬性,並非指原型鏈上的 <code>enumerable</code> 特性 ) 對應其屬性名稱,根據其屬性敘述元 (property descriptors) 加進新創建的物件。這些屬性對應到 {{jsxref("Object.defineProperties()")}} 的第二個參數。</dd>
</dl>

<h3 id="回傳">回傳</h3>

<p>具有指定原型物件與屬性的新物件。</p>

<h3 id="例外">例外</h3>

<p> 如果 <code>proto</code> 參數不是 {{jsxref("null")}} 或一個物件,將會拋出 {{jsxref("TypeError")}} 例外。</p>

<h2 id="範例">範例</h2>

<h3 id="使用_Object.create()_實現類別繼承">使用 <code>Object.create() </code>實現類別繼承</h3>

<p>下方是如何使用 <code>Object.create()</code> 去實現類別繼承的示範,此為 JavaScript 支援的單一繼承.。</p>

<pre class="brush: js">// Shape - 父類別
function Shape() {
  this.x = 0;
  this.y = 0;
}

// 父類別的方法
Shape.prototype.move = function(x, y) {
  this.x += x;
  this.y += y;
  console.info('Shape moved.');
};

// Rectangle - 子類別
function Rectangle() {
  Shape.call(this); // call super constructor.
}

// 子類別擴展(extends)父類別
Rectangle.prototype = Object.create(Shape.prototype);
Rectangle.prototype.constructor = Rectangle;

var rect = new Rectangle();

console.log('Is rect an instance of Rectangle?', rect instanceof Rectangle);// true
console.log('Is rect an instance of Shape?', rect instanceof Shape);// true
rect.move(1, 1); // Outputs, 'Shape moved.'
</pre>

<p>也可像 mixin 繼承多個物件。</p>

<pre class="brush: js">function MyClass() {
  SuperClass.call(this);
  OtherSuperClass.call(this);
}

// 繼承一個父類別
MyClass.prototype = Object.create(SuperClass.prototype);
// mixin另一個父類別
Object.assign(MyClass.prototype, OtherSuperClass.prototype);
// 重新指定建構式
MyClass.prototype.constructor = MyClass;

MyClass.prototype.myMethod = function() {
  // do a thing
};
</pre>

<p><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign">Object.assign</a> 複製 OtherSuperClass 原型上的所有屬性到 MyClass 的原型上,使所有 MyClass 的實例都能使用。Object.assign 為 ES2015 標準且<a href="https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Global_Objects/Object/assign#Polyfill">有 polyfill</a>。如需支援較舊的瀏覽器,可使用第三方套件實現如 <a href="https://api.jquery.com/jQuery.extend/">jQuery.extend()</a> 或 <a href="https://lodash.com/docs/#assign">_.assign()</a> 。</p>

<h3 id="propertiesObject_參數的使用"><code>propertiesObject</code> 參數的使用</h3>

<pre class="brush: js">var o;

// 建立以null為原型的物件
o = Object.create(null);


o = {};
// 等同於:
o = Object.create(Object.prototype);


// Example where we create an object with a couple of sample properties.
// (Note that the second parameter maps keys to *property descriptors*.)
o = Object.create(Object.prototype, {
  // foo 為數值屬性
  foo: { writable: true, configurable: true, value: 'hello' },
  // bar 為 getter-and-setter 訪問屬性
  bar: {
    configurable: false,
    get: function() { return 10; },
    set: function(value) { console.log('Setting `o.bar` to', value); }
/* with ES5 Accessors our code can look like this
    get function() { return 10; },
    set function(value) { console.log('setting `o.bar` to', value); } */
  }
});


function Constructor() {}
o = new Constructor();
// 等同於:
o = Object.create(Constructor.prototype);
// Of course, if there is actual initialization code in the
// Constructor function, the Object.create() cannot reflect it


// 創建一個新物件,指定原型是全新的空物件,並加入值為 42 的屬性'p'
o = Object.create({}, { p: { value: 42 } });

// 屬性敘述元 writable, enumerable , configurable 未定義,預設皆為 false
o.p = 24;
o.p;
// 42

o.q = 12;
for (var prop in o) {
  console.log(prop);
}
// 'q'

delete o.p;
// false

// to specify an ES3 property
o2 = Object.create({}, {
  p: {
    value: 42,
    writable: true,
    enumerable: true,
    configurable: true
  }
});
</pre>

<h2 id="Polyfill">Polyfill</h2>

<p>此 polyfill 涵蓋了主要的使用情境:指定一個原型創建一個新的物件,第二個參數為選用。</p>

<p>要注意的是在 ES5 的<code>Object.create</code>中, <code>[[Prototype]]</code> 可以為 <code>null</code>,但在ECMAScript 5 以前的版本,polyfill 會因為繼承限制( limitation inherent )而不支援此情形。</p>

<pre><code>if (typeof Object.create !== "function") {
    Object.create = function (proto, propertiesObject) {
        if (!(proto === null || typeof proto === "object" || typeof proto === "function")) {
            throw TypeError('Argument must be an object, or null');
        }
        var temp = new Object();
        temp.__proto__ = proto;
        if(typeof propertiesObject === "object")
            Object.defineProperties(temp, propertiesObject);
        return temp;
    };
}</code></pre>

<h2 id="規範">規範</h2>

{{Specifications}}

<h2 id="瀏覽器相容性">瀏覽器相容性</h2>

{{Compat}}

<h2 id="參閱">參閱</h2>

<ul>
 <li>{{jsxref("Object.defineProperty()")}}</li>
 <li>{{jsxref("Object.defineProperties()")}}</li>
 <li>{{jsxref("Object.prototype.isPrototypeOf()")}}</li>
 <li>John Resig's post on <a href="http://ejohn.org/blog/objectgetprototypeof/">getPrototypeOf()</a></li>
</ul>