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
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
|
---
title: Object.create()
slug: Web/JavaScript/Reference/Global_Objects/Object/create
tags:
- ECMAScript 5
- JavaScript
- メソッド
- 'Null'
- Object
- リファレンス
- ポリフィル
browser-compat: javascript.builtins.Object.create
translation_of: Web/JavaScript/Reference/Global_Objects/Object/create
---
{{JSRef}}
**`Object.create()`** メソッドは、既存のオブジェクトを新しく生成されるオブジェクトのプロトタイプとして使用して、新しいオブジェクトを生成します。
{{EmbedInteractiveExample("pages/js/object-create.html", "taller")}}
## 構文
```js
Object.create(proto)
Object.create(proto, propertiesObject)
```
### 引数
- `proto`
- : 新たに生成されるオブジェクトのプロトタイプになるべきオブジェクトです。
- `propertiesObject` {{Optional_inline}}
- : 指定されていて、 {{jsxref("undefined")}} でない場合、それ自身の列挙可能なプロパティ (つまり、それ自身に定義されているものであり、プロトタイプチェーンの中での列挙可能なプロパティでは*ない*もの) が、それらのプロパティ名を伴う一連のプロパティ記述子を指定し、新たに生成されるオブジェクトに追加されることになります。これらのプロパティは、 {{jsxref("Object.defineProperties()")}} の 2 番目の引数に対応するものです。
### 返値
指定したプロトタイプオブジェクトとプロパティを持つ新しいオブジェクトです。
### 例外
`proto` 引数は次のいずれかになります。
- {{jsxref("null")}} または
- {{jsxref("Object")}} ただし[プリミティブラッパーオブジェクト](/ja/docs/Glossary/Primitive#primitive_wrapper_objects_in_javascript)を除く
`proto` がどちらでもない場合、 {{jsxref("TypeError")}} が発生します。
## カスタムオブジェクトと Null オブジェクト
完全なカスタムオブジェクト (特に `null` オブジェクトから作成されたもの、基本的にはメンバーを持たないカスタムオブジェクト) から生成された新しいオブジェクトは、予想外の振る舞いをすることがあります。これは特にデバッグ時に当てはまります。一般的なオブジェクト-プロパティ変換/検出ユーティリティ関数はエラーを生成したり、単に情報を失ったりする可能性があるからです (特にエラーを無視するサイレントエラートラップを使用している場合)。例えば、ここに 2 つのオブジェクトがあります。
```js
oco = Object.create( {} ); // 通常のオブジェクトを生成
ocn = Object.create( null ); // "null" オブジェクトを生成
> console.log(oco) // {} -- 普通に見えます
> console.log(ocn) // {} -- これまでのところ、普通に見えます
oco.p = 1; // 通常オブジェクトに単純なプロパティを生成
ocn.p = 0; // "null" オブジェクトに単純なプロパティを生成
> console.log(oco) // {p: 1} -- まだ普通に見えます
> console.log(ocn) // {p: 0} -- まだ普通に見えますが、待ってください...
```
上記のように、今のところすべてが正常なように見えます。しかし、実際に使ってみると、その違いはすぐに明らかになります。
```js
> "oco is: " + oco // "oco is: [object Object]" と表示
> "ocn is: " + ocn // エラーが発生: Cannot convert object to primitive value
```
多くの最も基本的な組み込み機能のほんの一部をテストするだけで、問題の大きさがより明確にわかります。
```js
> alert(oco) // [object Object] と表示
> alert(ocn) // エラーが発生: Cannot convert object to primitive value
> oco.toString() // [object Object] と表示
> ocn.toString() // エラーが発生: ocn.toString is not a function
> oco.valueOf() // {} と表示
> ocn.valueOf() // エラーが発生: ocn.valueOf is not a function
> oco.hasOwnProperty("p") // "true" と表示
> ocn.hasOwnProperty("p") // エラーが発生: ocn.hasOwnProperty is not a function
> oco.constructor // "Object() { [native code] }" と表示
> ocn.constructor // "undefined" と表示
```
このように、これらの違いにより、一見単純そうに見える問題であっても、デバッグがすぐに迷走してしまうことがあります。例えば、以下のようなものです。
_シンプルな共通デバッグ関数です。_
```js
// 与えられたオブジェクトの最上位のプロパティ名と値の組を表示
function ShowProperties(obj){
for(var prop in obj){
console.log(prop + ": " + obj[prop] + "\n" );
}
}
```
_このような単純な結果ではありません。 (特にサイレントエラートラップがエラーメッセージを隠していた場合)_
```js
ob={}; ob.po=oco; ob.pn=ocn; // 上記のテストオブジェクトをプロパティ値として使用して、複合オブジェクトを生成します。
> ShowProperties( ob ) // 最上位のプロパティを表示
- po: [object Object]
- Error: Cannot convert object to primitive value
最初のプロパティのみが表示されることに注意してください。
```
_(しかし、同じオブジェクトが単に順番が違うだけで作成されている場合 -- 少なくともいくつかの実装では...)_
```js
ob={}; ob.pn=ocn; ob.po=oco; // 同じ複合オブジェクトを再度作成しますが、同じプロパティを異なる順序で作成します。
> ShowProperties( ob ) // 最上位のプロパティを表示
- Error: Cannot convert object to primitive value
どちらのプロパティも表示されないことに注意してください。
```
なお、このような順序の変化は、静的にはここにあるような異なる固定されたコードによって生じることがありますが、動的には、このようなプロパティを追加するコードの分岐が、入力やランダム変数によって実行される順序が変わることで生じることもあります。ただし、どのような順序でメンバーを追加しても、実際の反復順序は保証されません。
また、 Object.create() で生成されたオブジェクトに Object.entries() を使用すると、空の配列が返されることにも注意してください。
```js
var obj = Object.create({ a: 1, b: 2 });
> console.log(Object.entries(obj)); // "[]" と表示
```
#### いくつかの解決しない方法
オブジェクトメソッドが不足していることについての良い解決策は、すぐには見つかりません。
不足しているオブジェクトメソッドを標準オブジェクトから直接追加してもうまくいきません。
```js
ocn = Object.create( null ); // "null" オブジェクトを生成 (既出と同じ)
ocn.toString = Object.toString; // 新しいオブジェクトにはメソッドがないので、標準オブジェクトから直接代入してみる
> ocn.toString // "toString() { [native code] }" と表示 -- 存在しないメソッドが来たように見えます
> ocn.toString == Object.toString // "true" と表示 -- 標準オブジェクトのメソッドと同じように見えるメソッド
> ocn.toString() // エラー: Function.prototype.toString requires that 'this' be a Function
```
不足しているオブジェクトメソッドを新しいオブジェクトの「プロトタイプ」に直接追加してもうまくいきません。なぜなら、新しいオブジェクトは本当のプロトタイプを持っておらず (これがすべての問題における真の原因です)、プロトタイプを**直接**追加することはできないからです。
```js
ocn = Object.create( null ); // "null" オブジェクトを生成 (既出と同じ)
ocn.prototype.toString = Object.toString; // エラー: Cannot set property 'toString' of undefined
ocn.prototype = {}; // プロトタイプを生成してみる
ocn.prototype.toString = Object.toString; // 新しいオブジェクトにはメソッドがないので、標準オブジェクトから代入してみる
> ocn.toString() // エラー: ocn.toString is not a function
```
[`Object.setPrototypeOf()`](/ja/docs/Web/JavaScript/Reference/Global_Objects/Object/setPrototypeOf) の第 2 引数に標準オブジェクト自身の名前を指定して、不足しているオブジェクトメソッドを追加しようとしても、うまくいきません。
```js
ocn = Object.create( null ); // "null" オブジェクトを生成 (既出と同じ)
Object.setPrototypeOf(ocn, Object); // 間違い。新しいオブジェクトのプロトタイプを Object() 関数に設定している
> ocn.toString() // エラー: Function.prototype.toString requires that 'this' be a Function
```
#### いくつかの解決方法
繰り返しになりますが、欠落しているオブジェクトメソッドを**標準オブジェクト**から直接追加しても動作しません。しかし、**ジェネリック**メソッドを直接追加すると、動作します。
```js
ocn = Object.create( null ); // "null" オブジェクトを生成 (既出と同じ)
ocn.toString = toString; // 新しいオブジェクトにはメソッドがないので、ジェネリック版から直接代入する
> ocn.toString() // "[object Object]" と表示
> "ocn is: " + ocn // "ocn is: [object Object]" と表示
ob={}; ob.pn=ocn; ob.po=oco; // 複合オブジェクトを生成 (既出と同じ)
> ShowProperties(ob) // 最上位のプロパティを表示
- po: [object Object]
- pn: [object Object]
```
しかし、ジェネリック**プロトタイプ**を新しいオブジェクトのプロトタイプとして設定すると、さらに効果的です。
```js
ocn = Object.create( null ); // "null" オブジェクトを生成 (既出と同じ)
Object.setPrototypeOf(ocn, Object.prototype); // 新しいオブジェクトのプロトタイプを (標準オブジェクトではなく) 「ジェネリック」オブジェクトに設定
```
_(上記の文字列関連の関数に加えて、以下の関数も追加されています)_
```js
> ocn.valueOf() // {} と表示
> ocn.hasOwnProperty("x") // "false" と表示
> ocn.constructor // "Object() { [native code] }" と表示
// ...そして、それ以外の Object.prototype のすべてのプロパティとメソッドも
```
このように、この方法で変更されたオブジェクトは、普通のオブジェクトと同じように見えます。
## 例
### `Object.create()` を用いた古典的な継承
以下の例は、古典的な継承をするための `Object.create()` の使用方法です。これは、すべての JavaScript が対応している単一継承です。
```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.
}
// サブクラスはスーパークラスを拡張する
Rectangle.prototype = Object.create(Shape.prototype);
// Rectangle.prototype.constructor を Rectangle に設定しないと、
// Shape (親) の prototype.constructor を取ることになります。
// これを防ぐために、 prototype.constructor を Rectangle (子) に設定します。
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.'
```
### Object.create() と propertiesObject 引数の併用
```js
var o;
// プロトタイプを null にしてオブジェクトを生成
o = Object.create(null);
o = {};
// これは次のものと同等です。
o = Object.create(Object.prototype);
// いくつかのサンプルプロパティを持つオブジェクトを作成
// する例です。(2 番目の引数は、キーを*プロパティ記述子*に
// マッピングしていることに注意してください。)
o = Object.create(Object.prototype, {
// foo は普通の「値プロパティ」です
foo: {
writable: true,
configurable: true,
value: 'hello'
},
// bar はゲッターとセッター (アクセサー) によるプロパティです
bar: {
configurable: false,
get: function() { return 10; },
set: function(value) {
console.log('Setting `o.bar` to', value);
}
/* ES2015 のアクセサーでは、このようになります。
get() { return 10; },
set(value) {
console.log('Setting `o.bar` to', value);
} */
}
});
function Constructor() {}
o = new Constructor();
// これは次のものと同等です。
o = Object.create(Constructor.prototype);
// もちろん、コンストラクター関数に実際の初期化
// コードがある場合は、 Object.create() には反映
// されません
// プロトタイプが新規の空オブジェクトである新しいオブジェクトを
// 生成し、単一のプロパティ 'p' を値を 42 にして追加します。
o = Object.create({}, { p: { value: 42 } });
// 既定では、プロパティは書き込み可能、列挙可能、構成可能ではありません
o.p = 24;
o.p;
// 42
o.q = 12;
for (var prop in o) {
console.log(prop);
}
// 'q'
delete o.p;
// false
// ES3 プロパティを指定
o2 = Object.create({}, {
p: {
value: 42,
writable: true,
enumerable: true,
configurable: true
}
});
/* 次のものと同じではありません。
これはプロトタイプが {p: 42 } であるオブジェクトを生成します。
o2 = Object.create({p: 42}) */
```
## 仕様書
{{Specifications}}
## ブラウザーの互換性
{{Compat}}
## 関連情報
- `Object.create` のポリフィルは [`core-js`](https://github.com/zloirock/core-js#ecmascript-object) で利用できます
- {{jsxref("Object.defineProperty()")}}
- {{jsxref("Object.defineProperties()")}}
- {{jsxref("Object.prototype.isPrototypeOf()")}}
- {{jsxref("Reflect.construct()")}}
- John Resig の [getPrototypeOf()](http://ejohn.org/blog/objectgetprototypeof/) の投稿
|