オブジェクトを作成するには、new Object() を用いる、{ ... } を用いる、Object.create() を用いるの3通りの方式があります。
少し古い書き方です。new を用いてオブジェクトを生成します。
var obj = new Object(); var obj1 = new Object(false); // new Boolean(false) と同じ var obj2 = new Object(12.3); // new Number(12.3) と同じ var obj3 = new Object("ABC"); // new String("ABC") と同じ
ECMAScript でサポートされた書き方で、最近ではほとんどの場合、この書き方を用います。
var obj = {};
下記の様に、オブジェクトのプロパティを定義することもできます。
var obj = { width: 160, height: 120 }; console.log(obj.width); // => 160 console.log(obj.height); // => 120
ES5 では、末尾のプロパティの最後にカンマ(,)を記述してもエラーとならなくなりました。
var obj = {
width: 160,
height: 120, // ES5 以降であればエラーとならない
};
親のプロトタイプを継承して、子のオブジェクトに設定することができます。ES5.1 から追加された機能で、Chrome, Firefox, Safari, IE9以降で利用可能です。properties の詳細は defineProperties を参照してください。
// 親オブジェクトを作成する function parentObj() {}; parentObj.prototype.width = 160; parentObj.prototype.height = 120; // 子オブジェクトを作成する function childObj() {} childObj.prototype = Object.create(parentObj.prototype); console.log(childObj.prototype); // なにも継承しない純粋なオブジェクトを作成する var obj = Object.create(null);
プロトタイプは、子オブジェクトやサブクラスに継承されるプロパティやメソッドの集合です。
オブジェクトのプロトタイプを示します。このオブジェクトタイプに新しいプロパティを定義したり、継承するメソッドをオーバライドしたりする際に用いられます。
// プロパティを追加する Date.prototype.tzname = "(unknown)"; var date1 = new Date(); console.log(date1.tzname); // メソッドをオーバーライドする Date.prototype.toString = function() { return(this.getFullYear() + "年" + (this.getMonth() + 1) + "月" + this.getDate() + "日" + this.getHours() + "時" + this.getMinutes() + "分" + this.getSeconds() + "秒"); } var date2 = new Date(); console.log(date2.toString()); // => 2019年3月24日16時31分12秒 // プロトタイプを継承するオブジェクトを作成する var date3 = Object.create(Date.prototype);
指定したオブジェクトの、プロトタイプを返します。
var proto = {x:100, y:200};
var obj = Object.create(proto);
var proto2 = Object.getPrototypeOf(obj);
console.log(proto2); // => {x:100, y:200}
オブジェクトのプロトタイプを設定します。
var proto = { hello: function() { console.log("Hello!!"); } } var obj = {x:100, y:200}; Object.setPrototypeOf(obj, proto); console.log(obj); // => {x:100, y:200} obj.hello(); // => Hello!!
obj2 のプロトタイプが、obj1 のプロトタイプに由来しているものか否かを調べます。
function obj1() {}
const obj2 = new obj1();
console.log(obj1.prototype.isPrototypeOf(obj2)); // => true
オブジェクトのプロトタイプを返します。互換性を保つために残されていますが非推奨の機能です。代わりに getPrototypeOf(), setPrototypeOf() を使用してください。
var obj = {x:100, y:200};
console.log(obj.__proto__); // => {constructor: function Object() { ... }, ...}
オブジェクトが持つ、列挙可能なプロパティの名前の配列を返します。列挙不可のものも併せて取得するには getOwnPropertyNames() を用います。
var obj = {x:100, y:200};
console.log(Object.keys(obj)); // => ["x", "y"]
ES2017(ES8) で追加された機能で、オブジェクトが持つ、列挙可能なプロパティの値の配列を返します。
var obj = {x:100, y:200};
console.log(Object.values(obj)); // => [100, 200]
ES2017(ES8) で追加された機能で、オブジェクトのプロパティに対して、[key, value] の配列を返します。
var obj = {x:100, y:200};
console.log(Object.entries(obj)); // => [["x",100], ["y":200]]
ES2019(ES10) で追加された機能で、[key, value] の配列をオブジェクトに変換します。
var obj = Object.fromEntries([["x", 100], ["y", 200]]);
console.log(obj); // => {x: 100, y: 200}
指定したオブジェクトの、列挙可能なプロパティ名のリストを返します。
var obj = {x: 100, y: 200, z: 300};
var names = Object.getOwnPropertyNames(obj);
console.log(names); // => ["x", "y", "z"]
指定したオブジェクトの、列挙可能なシンボルのリストを返します。
var obj = {}
obj[Symbol('x')] = 100;
obj[Symbol('y')] = 200;
var symbols = Object.getOwnPropertySymbols(obj);
console.log(symbols); // => [Symbol(x), Symbol(y)]
オブジェクトが propertyName で指定した名前の属性を、自身のプロパティとして持っているかを調べます。
var obj = { x:100 };
console.log(obj.hasOwnProperty('x')); // => true
hasOwnProperty() が持つ問題点を解決する目的で ES2022 で追加されました。詳細は「hasOwn() によるプロパティ保持チェック」を参照してください。
var obj = { x: 100 };
console.log(Object.hasOwn(obj, 'x')); // => true
prop で指定したプロパティが列挙可能か否かを返します。
var arr = ["x", "y"]; console.log(arr.propertyIsEnumerable(0)); // => true console.log(arr.propertyIsEnumerable('length')); // => false var obj = {}; Object.defineProperty(obj, 'x', {enumerable: true}); Object.defineProperty(obj, 'y', {enumerable: false}); console.log(obj.propertyIsEnumerable('x')); // => true console.log(obj.propertyIsEnumerable('y')); // => false
obj のプロパティ値、および、プロパティ記述子を設定・変更します。obj にはオブジェクト、prop にはプロパティ名または Symbol、description にプロパティ記述子を指定します。プロパティ記述子には下記の属性を指定します。
value にはプロパティの値を指定します。省略した場合は undefined となります。get, set と同時に指定することはできません。
var obj = {};
Object.defineProperty(obj, 'a', { value: 100 });
console.log(obj.a); // => 100
writable にはプロパティの値を上書きできるか否かを true または false で指定します。省略時は false となります。get, set と同時に指定することはできません。下記の例では、obj.a = 200 を実行していますが、上書きが禁止されているため、値は 100 のままとなります。ストリクトモード の時には TypeError となります。
'use strict';
var obj = {};
Object.defineProperty(obj, 'a', { value: 100, writable: false });
obj.a = 200; // TypeError
configurable にはプロパティ記述子を変更できるか否かを true または false で指定します。省略時は false となります。下記の例ではプロパティ記述子の変更が禁止されているため、writable を true に変更しようとすると TypeError となります。writable の false を true に変更することは禁止されますが、true を false に変更することは禁止されません。
Object.defineProperty(obj, 'a', { writable: false, configurable: false });
Object.defineProperty(obj, 'a', { writable: true }); // TypeError
enumerable には for ... in や Object.keys() などで列挙されるか否かを true または false で指定します。省略時は false となります。下記の例では、b は列挙が禁止されているため、a のみが列挙されます。
Object.defineProperty(obj, "a", { value: 100, enumerable: true });
Object.defineProperty(obj, "b", { value: 200, enumerable: false });
for (var prop in obj) {
console.log(prop); // => a
}
get, set には、プロパティに対するゲッター関数、セッター関数を指定します。value, writable と同時に指定することはできません。下記の例では、プロパティに値を設定したり、値を取得する度にコンソールにログを出力します。
Object.defineProperty(obj, 'a', { get() { console.log("get:" + a); return a; }, set(value) { console.log("set:" + value); a = value; } }); obj.a = 100; // => set:100 var n = obj.a; // => get:100
複数のプロパティを同時に指定します。詳細は defineProperty() を参照してください。
var obj = {}; Object.defineProperties(obj, { a: { value: 100, writable: true }, b: { value: 200, writable: true }, });
指定したオブジェクトのプロパティの、プロパティ記述子を取得します。プロパティ記述子の詳細は defineProperty() を参照してください。
var obj = { a: 100 }; var desc = Object.getOwnPropertyDescriptor(obj, 'a'); console.log(desc.value); console.log(desc.writable); console.log(desc.configurable); console.log(desc.enumerable);
ES2017(ES8) で追加された機能で、指定したオブジェクトの、列挙可能なすべてのプロパティについて、プロパティ記述子を取得します。プロパティ記述子の詳細は defineProperty() を参照してください。
var obj = { a: 100 };
var descs = Object.getOwnPropertyDescriptors(obj);
console.log(descs); // => {a: {value: 100, writable: true, ...}}
オブジェクトは、凍結・封印・拡張禁止することができます。また、プロパティ記述子 の設定により個々のプロパティを値変更不可・設定変更不可にすることもできます。それぞれの関係をまとめると下記の様になります。拡張とはプロパティを追加すること、削除とはプロパティを削除すること、設定変更とは defineProperty() などでプロパティ記述子を制限が緩い方向に変更すること、値変更とは代入などによりプロパティの値を変更することを示します。
種別 | 拡張 | 削除 | 設定変更 | 値変更 |
---|---|---|---|---|
凍結(freeze) | × | × | × | × |
封印(seal) | × | × | ○ | ○ |
拡張禁止(preventExtensions) | × | ○ | ○ | ○ |
値変更不可(writable:false) | ○ | ○ | ○ | × |
設定変更不可(configurable:false) | ○ | ○ | × | ○ |
オブジェクトを凍結します。拡張、削除、設定変更、値変更が禁止されます。禁止された操作を行おうとすると、通常モードでは無視され、ストリクトモード では TypeError が発生します。
'use strict';
var obj = { a: 100, b: 200 };
Object.freeze(obj);
obj.a = 300; // => TypeError
オブジェクトを封印します。拡張、削除が禁止されます。設定変更、値変更は禁止されません。禁止された操作を行おうとすると、通常モードでは無視され、ストリクトモード では TypeError が発生します。
'use strict'; var obj = {x:100, y:200}; Object.seal(obj); obj['z'] = 300; // => TypeError delete obj.x; // => TypeError
オブジェクトを拡張禁止にします。削除、設定変更、値変更は禁止されません。禁止された操作を行おうとすると、通常モードでは無視され、ストリクトモード では TypeError が発生します。
'use strict';
var obj = {x:100, y:200};
Object.preventExtensions(obj);
obj['z'] = 300; // => TypeError
オブジェクトが凍結されているか否かを返します。オブジェクトは freeze()により凍結されます。プロパティをひとつも持たない場合や、プロパティがすべて変更不可(writable:false)、かつ、設定変更不可(configurable:false)であれば、seal(), preventExtensions() によっても凍結状態となります。
var obj = {}; console.log(Object.isFrozen(obj)); // => true Object.freeze(obj); console.log(Object.isFrozen(obj)); // => false
オブジェクトが封印されているか否かを返します。オブジェクトは freeze() や seal() により封印されます。
var obj = {}; console.log(Object.isSealed(obj)); // => true Object.seal(obj); console.log(Object.isSealed(obj)); // => false
オブジェクトが拡張可能であるか否かを返します。オブジェクトは freeze(), seal(), preventExtensions() により拡張不可となります。
var obj = {}; console.log(Object.isExtensible(obj)); // => true Object.freeze(obj); console.log(Object.isExtensible(obj)); // => false
オブジェクトを文字列に変換する際に用いられます。オブジェクトの種類や JavaScript のバージョンによって文字列のフォーマットは異なります。このメソッドは、オブジェクトを文字列に変換する必要がある時に暗黙的に呼ばれます。
var date = new Date();
console.log(date.toString()); // => Sun Mar 24 2019 14:02:41 GMT+0900 (日本標準時)
オブジェクトを文字列に変換します。Object では toLocaleString() は toString() と同等ですが、Date などのサブクラスでは、toLocaleString() をオーバーライドすることで、言語依存の文字列に変換することができます。
var date = new Date();
console.log(date.toLocaleString()); // => 2019/3/24 14:02:41
オブジェクトの中身の値を得ます。toString()だと [object Object] としか表示されなかったところを、({x:100, y:200}) などのように、オブジェクトのプロパティまで文字列化することができます。Netscape Navigator 4.5 や Firefox でサポートされていますが、他の多くのブラウザではサポートされていません。
var obj = {x:100, y:200}; console.log(obj.toString()); // => [object Object] console.log(obj.toSource()); // => ({x:100, y:200})
オブジェクトのコンストラクタへの参照を返します。
var obj = {x:100, y:200};
console.log(obj.constructor); // => function Object() { ... }
target オブジェクトに、obj1, obj2, ... オブジェクトが持つプロパティをコピーします。ES2015(ES6) で追加された機能で、Chrome, Firefox, Safari, Edge ではサポートされていますが、IE11 ではサポートしていません。
var target = { a: 1, b: 2 }
var obj1 = { c: 3, d: 4 }
var obj2 = { e: 5, f: 6 }
Object.assign(target, obj1, obj2);
console.log(target); // => {a: 1, b: 2, c: 3, d: 4, e: 5, f: 6}
value1 と value2 を比較し、同一であれば true、異なるものであれば false を返します。=== による比較とほぼ同じ結果を返しますが、-0 と +0、Number.Nan と NaN を別物とみなす点が異なります。
Object.is(123, "123"); // => false Object.is(-0, +0); // => false
オブジェクトのプリミティブな値を返します。Number などのサブクラスでは、valueOf() をオーバーライドすることで、Number オブジェクトからプリミティブな数値を取り出します。
var num = new Number(12.345); console.log(num); // => Number {12.345} console.log(num.valueOf()); // => 12.345
ES5 では、プロパティに設定した時、参照した時に関数を呼び出す、ゲッター(getter)とセッター(setter)がサポートされました。下記の例では、name プロパティに値を設定したり、値を参照したりする際に、ゲッター関数、セッター関数が呼び出され、コンソールにログを出力します。
var user = { _name: '', set name(name) { // setter関数 console.log("Set name : " + name); this._name = name; }, get name() { // getter関数 console.log("Get name : " + this._name); return this._name; } } user.name = "Tanaka"; // => Set name : Tanaka name = user.name; // => Get name : Tanaka
ES2018(ES9) では、オブジェクトに対するレスト構文とスプレッド構文がサポートされました。
var obj1 = {x: 200, y: 300}; var obj2 = {w: 400, h: 500}; var obj3 = {...obj1, ...obj2}; // スプレッド構文 console.log(obj3); // {x: 200, y: 300, w: 400, h: 500} var { x, y, ...rest } = obj3; // レスト構文 console.log(rest); // {w: 400, h: 500}
ES2015(ES6) より古い JavaScript では class による クラス 定義がサポートされておらず、代わりに function を用いてクラスを擬似的に定義していました。下記では、Person というクラスを定義しています。これは name と age を属性(プロパティ)として持ち、toString() を動作(メソッド)として持ちます。toString() は、すべてのクラスに共通な toString() メソッドを上書き(オーバーライド)するものです。
function Person(name, age) { this.name = name; this.age = age; this.toString = function() { return (this.name + "(" + this.age + ")"); } }
Person() 関数は Person クラスの生成関数(コンストラクタ)として扱われます。Person オブジェクトの実体(インスタンス)を生成するには new 演算子を用います。
var p1 = new Person("Suzuki", 26); console.log(p1.name); // => Suzuki console.log(p1.toString()); // => Suzuki(26)
call() や apply() を用いて、Person のサブクラス Person2 や Person3 を作成することができます。引数固定の場合は call()、可変個引数の場合は apply() を用います。
function Person2(name, age, email) { this.email = email; Person.call(this, name, age); } var p2 = new Person2("Suzuki", 26, "suzuki@example.com"); console.log(p2.name); console.log(p2.age); console.log(p2.email); function Person3(/* ..., email */) { var args = [].slice.call(arguments); this.email = args.pop(); Person.apply(this, args); } var p3 = new Person3("Suzuki", 26, "suzuki@example.com"); console.log(p3.email);