オブジェクト初期化子

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

構文

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

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

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

ECMAScript 2015 での新しい表記法

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

// Shorthand property names (ES2015)
var a = 'foo', b = 42, c = {};
var o = {a, b, c};

// Shorthand method names (ES2015)
var o = {
  property(parameters) {}
};

// Computed property names (ES2015)
var prop = 'foo';
var o = {
  [prop]: 'hey',
  ['b' + 'ar']: 'there'
};

説明

オブジェクト初期化子は、Object の初期化を表す式です。オブジェクトはオブジェクトを表すプロパティで構成されます。オブジェクトプロパティの値は特定の primitive データ型か他のオブジェクトのどちらかを含みます。

オブジェクトの生成

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

var object = {};

リテラル表記法、initializer 表記法の利点は中括弧内にプロパティをもつオブジェクトをすばやく生成できる点です。また、カンマで区切られた key: value のペアを記述することでプロパティ値の生成も可能です。以下に、三つのプロパティをもつオブジェクトを生成する方法を記します。キーは "foo""age""baz" であり、各々のキーの値は、文字列の "bar"、数値の 42 、そして baz はオブジェクトがプロパティ値となります。

var object = {
  foo: 'bar',
  age: 42,
  baz: {myProp: 12},
}

プロパティへのアクセス

一度オブジェクトを生成した後も、プロパティにアクセスすることができます。その方法は「ドット表記法」か「ブラケット表記法」と言われます。詳細については、プロパティへのアクセスをご覧ください。

object.foo; // "bar"
object['age']; // 42

object.foo = 'baz';

プロパティの定義

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

var a = 'foo',
    b = 42,
    c = {};

var o = {
  a: a,
  b: b,
  c: c
};

ECMAScript 2015 では、同じことを達成するために利用可能な短い表記があります。:

var a = 'foo',
    b = 42,
    c = {};

// Shorthand property names (ES2015)
var o = {a, b, c};

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

重複したプロパティ名

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

var a = {x: 1, x: 2};
console.log(a); // {x: 2}

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

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

    // No error thrown, duplicate property names allowed in strict mode
    return true;
  } catch (e) {
    // Error thrown, duplicates prohibited in strict mode
    return false;
  }
}

メソッドの定義

オブジェクトのプロパティは functiongetter メソッド、setter メソッドも参照することができます

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

ECMAScript 2015 では、省略表記が利用可能です。そのため、キーワード "function" はもはや必要ではありません。

// Shorthand method names (ES2015)
var o = {
  property(parameters) {},
  *generator() {}
};

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

var o = {
  *generator() {
    ...........
  }
};

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

var o = {
  generator: function* () {
    ...........
  }
};

メソッドの詳細や例については、メソッド定義をご覧ください。

計算されたプロパティ名

ECMAScript 2015 から、オブジェクト初期化子構文も計算されたプロパティ名をサポートします。括弧 [] の中に式を記述でき、それが計算されてプロパティ名として使用されます。これは、あなたが既にプロパティを読み込んだり設定したりするために使用したことがあるかもしれない、メンバー演算子構文のブラケット表記を思い起こさせます。今では、オブジェクトリテラルでも同様な構文を使うことができます:

// Computed property names (ES2015)
var i = 0;
var 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

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

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

スプレッドプロパティ

ECMAScript proposal の Rest/Spread プロパティ (ステージ 4) オブジェクトリテラルにスプレッドプロパティを追加します。 渡されたオブジェクトから新しいオブジェクトに独自の列挙可能なプロパティをコピーします。

Object.assign() を使うよりも短いコードで prototype を除いた浅いコピーの作成や、マージしたオブジェクトの作成を書けます。

var obj1 = { foo: 'bar', x: 42 };
var obj2 = { foo: 'baz', y: 13 };

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

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

Object.assign()setters をトリガーしますが、スプレッド構文はトリガーできません。

プロトタイプ変異

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

var obj1 = {};
assert(Object.getPrototypeOf(obj1) === Object.prototype);

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

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

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

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

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

var __proto__ = 'variable';

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

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

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

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

オブジェクトリテラル表記法は JavaScript Object Notation (JSON) とは異なります。それらは似ていますが、それらの間には違いがあります。:

  • JSON は、"property": value 構文を使用するプロパティ定義のみ許可します。プロパティ名称は二重引用符で囲まなければなりません。そして、その定義は簡略にすることはできません。
  • JSON ではその値は strings、numbers、arrays、truefalsenull、別の (JSON) オブジェクトのみです。
  • 関数の値 (上記"メソッド"を参照) は JSON では値を割り当てることができません。
  • Date のようなオブジェクトは JSON.parse() の後で string になります。
  • JSON.parse() は計算されたプロパティ名を拒否し、エラーがスローされます。

仕様

仕様 ステータス コメント
ECMAScript 1st Edition (ECMA-262) 標準 初期定義。
ECMAScript 5.1 (ECMA-262)
Object Initializer の定義
標準 gettersetter が追加されました。
ECMAScript 2015 (6th Edition, ECMA-262)
Object Initializer の定義
標準 簡略表現メソッド/プロパティの名称と計算されたプロパティ名が追加されました。
ECMAScript (ECMA-262)
Object Initializer の定義
現行の標準

ブラウザー実装状況

BCD tables only load in the browser

関連情報