aboutsummaryrefslogtreecommitdiff
path: root/files/ja/web/javascript/reference/operators/object_initializer/index.md
blob: 21b3b36f98185cc9e5e58e9fed1a3f2aefd6750c (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
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
---
title: オブジェクト初期化子
slug: Web/JavaScript/Reference/Operators/Object_initializer
tags:
  - ECMAScript 2015
  - JSON
  - JavaScript
  - 言語機能
  - リテラル
  - メソッド
  - オブジェクト
  - Primary Expression
  - computed
  - mutation
  - プロパティ
browser-compat: javascript.operators.object_initializer
translation_of: Web/JavaScript/Reference/Operators/Object_initializer
---
{{JsSidebar("Operators")}}

オブジェクトは [`new Object()`](/ja/docs/Web/JavaScript/Reference/Global_Objects/Object)、[`Object.create()`](/ja/docs/Web/JavaScript/Reference/Global_Objects/Object/create)、*リテラル*表記法 (*初期化子*表記法) を使用して初期化されます。オブジェクト初期化子はオブジェクトのプロパティ名と関連した値のゼロ以上のペアのリストで、中括弧 (`{}`) で囲まれます。

{{EmbedInteractiveExample("pages/js/expressions-objectinitializer.html", "taller")}}

## 構文

```js
let o = {}
let o = {a: 'foo', b: 42, c: {}}

let a = 'foo', b = 42, c = {}
let o = {a: a, b: b, c: c}

let o = {
  property: function (parameters) {},
  get property() {},
  set property(value) {}
};
```

### ECMAScript 2015 での新しい表記法

これらの表記をサポートするための互換性の表を参照してください。非サポート環境では、これらの表記は、構文エラーにつながります。

```js
// 略記プロパティ名 (ES2015)
let a = 'foo', b = 42, c = {};
let o = {a, b, c}

// 略記メソッド名 (ES2015)
let o = {
  property(parameters) {}
}

// 計算プロパティ名 (ES2015)
let prop = 'foo';
let o = {
  [prop]: 'hey',
  ['b' + 'ar']: 'there'
}
```

## 解説

オブジェクト初期化子は、{{jsxref("Object")}} の初期化を表す式です。オブジェクトはオブジェクトを表す*プロパティ*で構成されます。オブジェクトプロパティの値は、特定の[プリミティブ](/ja/docs/Glossary/Primitive)データ型か他のオブジェクトのどちらかを含みます。

### オブジェクトリテラル表記法 vs JSON

オブジェクトリテラル表記法は **J**ava**S**cript **O**bject **N**otation ([JSON](/ja/docs/Glossary/JSON)) とは異なります。両者は似ていますが、ちがいがあります。

- JSON は、`"property": value` 構文を使用するプロパティ定義*のみ*を許可します。プロパティ名は二重引用符で囲まなければなりません。そして、その定義を略記にすることはできません。
- JSON で値とすることができるのは、文字列、数値、配列、`true`、`false`、`null`、別の (JSON) オブジェクトのみです。
- 関数の値(後述の「メソッド」を参照)は JSON では値を割り当てることができません。
- {{jsxref("Date")}} のようなオブジェクトは、 {{jsxref("JSON.parse()")}} の後で文字列になります。
- {{jsxref("JSON.parse()")}} では計算プロパティ名は拒否され、エラーが発生します。

## 例

### オブジェクトの生成

プロパティを持たない空のオブジェクトは、下記のように中括弧を記述することで生成されます。

```js
let object = {}
```

しかし、*リテラル*記法、*初期化子*記法の利点は、中括弧内にプロパティをもつオブジェクトを簡潔に生成できる点です。 `key: value` の組をカンマで区切ったリストで記述することができます。

以下のコードでは、 `"foo"``"age"``"baz"` の 3 つのプロパティをもつオブジェクトを生成します。これらのキーの値はそれぞれ、文字列の `"bar"`、数値の `42`、そして他のオブジェクトです。

```js
let object = {
  foo: 'bar',
  age: 42,
  baz: {myProp: 12}
}
```

### プロパティへのアクセス

オブジェクトを生成すると、読み取ったり変更したりしたくなるでしょう。オブジェクトのプロパティには、ドット記法またはブラケット記法でアクセスすることができます。(詳細については、[プロパティへのアクセス](/ja/docs/Web/JavaScript/Reference/Operators/Property_Accessors)をご覧ください。)

```js
object.foo // "bar"
object['age'] // 42
object.baz          // {myProp: 12}
object.baz.myProp   //12
```

### プロパティの定義

初期化構文を使用してプロパティを記述する方法について既に学びました。多くの場合、コード内には、オブジェクトに設定したい変数があります。下記のコードをご覧ください。

```js
let a = 'foo',
    b = 42,
    c = {};

let o = {
  a: a,
  b: b,
  c: c
}
```

ECMAScript 2015 では、同じことを実現するために利用できる短い記法があります。

```js
let a = 'foo',
    b = 42,
    c = {};

// 略記プロパティ名 (ES2015)
let o = {a, b, c}

// In other words,
console.log((o.a === {a}.a)) // true
```

#### 重複したプロパティ名

プロパティに対して同じ名前を使用するとき、二番目のプロパティは最初のプロパティを上書きします。

```js
let a = {x: 1, x: 2}
console.log(a) // {x: 2}
```

ECMAScript 5 の厳格モードのコードでは、重複したプロパティの名前は {{jsxref("SyntaxError")}} とみなされます。実行時に重複を可能にする計算プロパティ名の導入により、 ECMAScript 2015 ではこの制限は取り除かれました。

```js
function haveES2015DuplicatePropertySemantics() {
  'use strict';
  try {
    ({prop: 1, prop: 2});

    // 厳格モードで重複するプロパティ名が許可されているため、エラーが発生しない場合。
    return true;
  } catch(e) {
    // 厳格モードで重複が禁止されているため、エラーが発生する場合。
    return false;
  }
}
```

### メソッドの定義

オブジェクトのプロパティは[関数](/ja/docs/Web/JavaScript/Reference/Functions)、[ゲッター](/ja/docs/Web/JavaScript/Reference/Functions/get)メソッド、[セッター](/ja/docs/Web/JavaScript/Reference/Functions/set)メソッドも参照することができます。

```js
let o = {
  property: function (parameters) {},
  get property() {},
  set property(value) {}
}
```

ECMAScript 2015 では、略記法が利用可能ですので、キーワード "`function`" は必要なくなりました。

```js
// メソッド名の略記法 (ES2015)
let o = {
  property(parameters) {},
}
```

ECMAScript 2015 では、ジェネレーター関数であるプロパティを簡潔に定義する方法があります。

```js
let o = {
  *generator() {
    ...........
  }
};
```

ECMAScript 5 では、下記のように記述します(ただし、 ES5 にはジェネレーターがないことに注意してください)。

```js
let o = {
  generator: function* () {
    ...........
  }
};
```

メソッドの詳細や例については、[メソッド定義](/ja/docs/Web/JavaScript/Reference/Functions/Method_definitions)をご覧ください。

### 計算プロパティ名

ECMAScript 2015 から、オブジェクト初期化子構文でも、計算プロパティ名に対応します。括弧 `[]` の中に式を記述することができ、それが計算されてプロパティ名として使用されます。これは、プロパティの読み込みと設定に使用したことのある、[プロパティアクセサー](/ja/docs/Web/JavaScript/Reference/Operators/Property_Accessors)構文のブラケット表記を彷彿とさせるものです。

今では、オブジェクトリテラルでも同様な構文を使うことができます。

```js
// Computed property names (ES2015)
let i = 0
let a = {
  ['foo' + ++i]: i,
  ['foo' + ++i]: i,
  ['foo' + ++i]: i
}

console.log(a.foo1) // 1
console.log(a.foo2) // 2
console.log(a.foo3) // 3

const items = ["A","B","C"];
const obj = {
[items]: "Hello"
}
console.log(obj); // A,B,C: "Hello"
console.log(obj["A,B,C"]) // "Hello"

let param = 'size'
let config = {
  [param]: 12,
  ['mobile' + param.charAt(0).toUpperCase() + param.slice(1)]: 4
}

console.log(config) // {size: 12, mobileSize: 4}
```

### スプレッドプロパティ

[ECMAScript proposal の Rest/Spread プロパティ](https://github.com/tc39/proposal-object-rest-spread) (ステージ 4) では、オブジェクトリテラルに[スプレッド](/ja/docs/Web/JavaScript/Reference/Operators/Spread_syntax)プロパティを追加します。 渡されたオブジェクトから新しいオブジェクトに独自の列挙可能なプロパティをコピーします。

{{jsxref("Object.assign()")}} を使うよりも短いコードで `prototype` を除いた浅いコピーの作成や、マージしたオブジェクトの作成を書くことができます。

```js
let obj1 = { foo: 'bar', x: 42 }
let obj2 = { foo: 'baz', y: 13 }

let clonedObj = { ...obj1 }
// Object { foo: "bar", x: 42 }

let mergedObj = { ...obj1, ...obj2 }
// Object { foo: "baz", x: 42, y: 13 }
```

> **Warning:** {{jsxref("Object.assign()")}} は[セッター](/ja/docs/Web/JavaScript/Reference/Functions/set)を起動しますが、スプレッド構文は起動しません。

### プロトタイプの変更

`__proto__: value` 形式、または `"__proto__": value` 形式でプロパティを定義しても、 `__proto__` という名をもつプロパティを生成しません。代わりに、与えられた値がオブジェクトまたは [`null`](/ja/docs/Web/JavaScript/Reference/Global_Objects/null) の場合、その値に生成されたオブジェクトの `[[Prototype]]` を変更します(その値がオブジェクト、または null ではない場合、オブジェクトは変更されません)。

```js
let obj1 = {}
assert(Object.getPrototypeOf(obj1) === Object.prototype)

let obj2 = {__proto__: null}
assert(Object.getPrototypeOf(obj2) === null)

let protoObj = {}
let obj3 = {'__proto__': protoObj}
assert(Object.getPrototypeOf(obj3) === protoObj)

let obj4 = {__proto__: 'not an object or null'}
assert(Object.getPrototypeOf(obj4) === Object.prototype)
assert(!obj4.hasOwnProperty('__proto__'))
```

オブジェクトリテラルでは、単一のプロトタイプの変更のみが許可されています。すなわち、複数のプロトタイプを変更すると構文エラーになります。

「コロン」表記法を使用しないプロパティ定義は、プロトタイプの変更にはなりません。任意の他の名称を使用する同様の定義と同じように動作するプロパティ定義です。

```js
let __proto__ = 'variable'

let obj1 = {__proto__}
assert(Object.getPrototypeOf(obj1) === Object.prototype)
assert(obj1.hasOwnProperty('__proto__'))
assert(obj1.__proto__ === 'variable')

let obj2 = {__proto__() { return 'hello'; }}
assert(obj2.__proto__() === 'hello')

let obj3 = {['__prot' + 'o__']: 17}
assert(obj3.__proto__ === 17)
```

## 仕様書

{{Specifications}}

## ブラウザーの互換性

{{Compat}}

## 関連情報

- [メンバー演算子](/ja/docs/Web/JavaScript/Reference/Operators/Property_Accessors)
- [`get`](/ja/docs/Web/JavaScript/Reference/Functions/get) / [`set`](/ja/docs/Web/JavaScript/Reference/Functions/set)
- [メソッド定義](/ja/docs/Web/JavaScript/Reference/Functions/Method_definitions)
- [字句文法](/ja/docs/Web/JavaScript/Reference/Lexical_grammar)