オブジェクト(Object)

[up] [prev] [next]

目次

オブジェクトとは

Object は、Number, String, Boolean, Date などのオブジェクトの親(祖先)となるオブジェクトで、Object が持つメソッドやプロパティは、すべての子孫オブジェクトで使用可能です。

オブジェクトを作成する

オブジェクトを作成するには、new Object() を用いる、{ ... } を用いる、Object.create() を用いるの3通りの方式があります。

obj = new Object([value])

少し古い書き方です。new を用いてオブジェクトを生成します。

JavaScript
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") と同じ
obj = { key1: value1, key2: value2, ... }

ECMAScript でサポートされた書き方で、最近ではほとんどの場合、この書き方を用います。

JavaScript
var obj = {};

下記の様に、オブジェクトのプロパティを定義することもできます。

JavaScript
var obj = {
  width: 160,
  height: 120
};
console.log(obj.width);   // => 160
console.log(obj.height);  // => 120

ES5 では、末尾のプロパティの最後にカンマ(,)を記述してもエラーとならなくなりました。

JavaScript
var obj = {
  width: 160,
  height: 120,  // ES5 以降であればエラーとならない
};
Object.create(prototype[, properties])

親のプロトタイプを継承して、子のオブジェクトに設定することができます。ES5.1 から追加された機能で、Chrome, Firefox, Safari, IE9以降で利用可能です。properties の詳細は defineProperties を参照してください。

JavaScript
// 親オブジェクトを作成する
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);

プロトタイプ

プロトタイプは、子オブジェクトやサブクラスに継承されるプロパティやメソッドの集合です。

Object.prototype

オブジェクトのプロトタイプを示します。このオブジェクトタイプに新しいプロパティを定義したり、継承するメソッドをオーバライドしたりする際に用いられます。

JavaScript
// プロパティを追加する
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);
Object.getPrototypeOf(obj)

指定したオブジェクトの、プロトタイプを返します。

JavaScript
var proto = {x:100, y:200};
var obj = Object.create(proto);
var proto2 = Object.getPrototypeOf(obj);
console.log(proto2);           // => {x:100, y:200}
Object.setPrototypeOf(obj)

オブジェクトのプロトタイプを設定します。

JavaScript
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!!
obj1.isPrototypeOf(obj2)

obj2 のプロトタイプが、obj1 のプロトタイプに由来しているものか否かを調べます。

JavaScript
function obj1() {}
const obj2 = new obj1();
console.log(obj1.prototype.isPrototypeOf(obj2));  // => true
obj.__proto__ (非推奨)

オブジェクトのプロトタイプを返します。互換性を保つために残されていますが非推奨の機能です。代わりに getPrototypeOf(), setPrototypeOf() を使用してください。

JavaScript
var obj = {x:100, y:200};
console.log(obj.__proto__);    // => {constructor: function Object() { ... }, ...}

プロパティ

Object.keys(obj)

オブジェクトが持つ、列挙可能なプロパティの名前の配列を返します。列挙不可のものも併せて取得するには getOwnPropertyNames() を用います。

JavaScript
var obj = {x:100, y:200};
console.log(Object.keys(obj));       // => ["x", "y"]
Object.values(obj)

ES2017(ES8) で追加された機能で、オブジェクトが持つ、列挙可能なプロパティの値の配列を返します。

JavaScript
var obj = {x:100, y:200};
console.log(Object.values(obj));      // => [100, 200]
Object.entries(obj)

ES2017(ES8) で追加された機能で、オブジェクトのプロパティに対して、[key, value] の配列を返します。

JavaScript
var obj = {x:100, y:200};
console.log(Object.entries(obj));     // => [["x",100], ["y":200]]
Object.fromEntries(obj)

ES2019(ES10) で追加された機能で、[key, value] の配列をオブジェクトに変換します。

JavaScript
var obj = Object.fromEntries([["x", 100], ["y", 200]]);
console.log(obj);             // => {x: 100, y: 200}
Object.getOwnPropertyNames(obj)

指定したオブジェクトの、列挙可能なプロパティ名のリストを返します。

JavaScript
var obj = {x: 100, y: 200, z: 300};
var names = Object.getOwnPropertyNames(obj);
console.log(names);           // => ["x", "y", "z"]
Object.getOwnPropertySymbols(obj)

指定したオブジェクトの、列挙可能なシンボルのリストを返します。

JavaScript
var obj = {}
obj[Symbol('x')] = 100;
obj[Symbol('y')] = 200;
var symbols = Object.getOwnPropertySymbols(obj);
console.log(symbols);        // => [Symbol(x), Symbol(y)]
obj.hasOwnProperty(propertyName)

オブジェクトが propertyName で指定した名前の属性を、自身のプロパティとして持っているかを調べます。

JavaScript
var obj = { x:100 };
console.log(obj.hasOwnProperty('x'));   // => true
Object.hasOwn(obj, propertyName)

hasOwnProperty() が持つ問題点を解決する目的で ES2022 で追加されました。詳細は「hasOwn() によるプロパティ保持チェック」を参照してください。

JavaScript
var obj = { x: 100 };
console.log(Object.hasOwn(obj, 'x'));    // => true
obj.propertyIsEnumerable(prop)

prop で指定したプロパティが列挙可能か否かを返します。

JavaScript
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

プロパティ記述子

Object.defineProperty(obj, property, descriptor)

obj のプロパティ値、および、プロパティ記述子を設定・変更します。obj にはオブジェクト、prop にはプロパティ名または Symbol、description にプロパティ記述子を指定します。プロパティ記述子には下記の属性を指定します。

value にはプロパティの値を指定します。省略した場合は undefined となります。get, set と同時に指定することはできません。

JavaScript
var obj = {};
Object.defineProperty(obj, 'a', { value: 100 });
console.log(obj.a);                   // => 100

writable にはプロパティの値を上書きできるか否かを true または false で指定します。省略時は false となります。get, set と同時に指定することはできません。下記の例では、obj.a = 200 を実行していますが、上書きが禁止されているため、値は 100 のままとなります。ストリクトモード の時には TypeError となります。

JavaScript
'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 に変更することは禁止されません。

JavaScript
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 のみが列挙されます。

JavaScript
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 と同時に指定することはできません。下記の例では、プロパティに値を設定したり、値を取得する度にコンソールにログを出力します。

JavaScript
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
Object.defineProperties(obj, properties)

複数のプロパティを同時に指定します。詳細は defineProperty() を参照してください。

JavaScript
var obj = {};
Object.defineProperties(obj, {
  a: { value: 100, writable: true },
  b: { value: 200, writable: true },
});
Object.getOwnPropertyDescriptor(obj, prop)

指定したオブジェクトのプロパティの、プロパティ記述子を取得します。プロパティ記述子の詳細は defineProperty() を参照してください。

JavaScript
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);
Object.getOwnPropertyDescriptors(obj)

ES2017(ES8) で追加された機能で、指定したオブジェクトの、列挙可能なすべてのプロパティについて、プロパティ記述子を取得します。プロパティ記述子の詳細は defineProperty() を参照してください。

JavaScript
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)×
Object.freeze(obj)

オブジェクトを凍結します。拡張、削除、設定変更、値変更が禁止されます。禁止された操作を行おうとすると、通常モードでは無視され、ストリクトモード では TypeError が発生します。

JavaScript
'use strict';
var obj = { a: 100, b: 200 };
Object.freeze(obj);
obj.a = 300;             // => TypeError
Object.seal(obj)

オブジェクトを封印します。拡張、削除が禁止されます。設定変更、値変更は禁止されません。禁止された操作を行おうとすると、通常モードでは無視され、ストリクトモード では TypeError が発生します。

JavaScript
'use strict';
var obj = {x:100, y:200};
Object.seal(obj);
obj['z'] = 300;                // => TypeError
delete obj.x;                  // => TypeError
Object.preventExtensions(obj)

オブジェクトを拡張禁止にします。削除、設定変更、値変更は禁止されません。禁止された操作を行おうとすると、通常モードでは無視され、ストリクトモード では TypeError が発生します。

JavaScript
'use strict';
var obj = {x:100, y:200};
Object.preventExtensions(obj);
obj['z'] = 300;                // => TypeError
Object.isFrozen(obj)

オブジェクトが凍結されているか否かを返します。オブジェクトは freeze()により凍結されます。プロパティをひとつも持たない場合や、プロパティがすべて変更不可(writable:false)、かつ、設定変更不可(configurable:false)であれば、seal(), preventExtensions() によっても凍結状態となります。

JavaScript
var obj = {};
console.log(Object.isFrozen(obj));    // => true
Object.freeze(obj);
console.log(Object.isFrozen(obj));    // => false
Object.isSealed(obj)

オブジェクトが封印されているか否かを返します。オブジェクトは freeze()seal() により封印されます。

JavaScript
var obj = {};
console.log(Object.isSealed(obj));    // => true
Object.seal(obj);
console.log(Object.isSealed(obj));    // => false
Object.isExtensible(obj)

オブジェクトが拡張可能であるか否かを返します。オブジェクトは freeze(), seal(), preventExtensions() により拡張不可となります。

JavaScript
var obj = {};
console.log(Object.isExtensible(obj));    // => true
Object.freeze(obj);
console.log(Object.isExtensible(obj));    // => false

文字列への変換

object.toString()

オブジェクトを文字列に変換する際に用いられます。オブジェクトの種類や JavaScript のバージョンによって文字列のフォーマットは異なります。このメソッドは、オブジェクトを文字列に変換する必要がある時に暗黙的に呼ばれます。

JavaScript
var date = new Date();
console.log(date.toString());        // => Sun Mar 24 2019 14:02:41 GMT+0900 (日本標準時)
obj.toLocaleString()

オブジェクトを文字列に変換します。Object では toLocaleString() は toString() と同等ですが、Date などのサブクラスでは、toLocaleString() をオーバーライドすることで、言語依存の文字列に変換することができます。

JavaScript
var date = new Date();
console.log(date.toLocaleString());  // => 2019/3/24 14:02:41
object.toSource() (非推奨)

オブジェクトの中身の値を得ます。toString()だと [object Object] としか表示されなかったところを、({x:100, y:200}) などのように、オブジェクトのプロパティまで文字列化することができます。Netscape Navigator 4.5 や Firefox でサポートされていますが、他の多くのブラウザではサポートされていません。

JavaScript
var obj = {x:100, y:200};
console.log(obj.toString());  // => [object Object]
console.log(obj.toSource());  // => ({x:100, y:200})

その他

obj.constructor

オブジェクトのコンストラクタへの参照を返します。

JavaScript
var obj = {x:100, y:200};
console.log(obj.constructor);    // => function Object() { ... }
Object.assign(target, obj1, obj2, ...)

target オブジェクトに、obj1, obj2, ... オブジェクトが持つプロパティをコピーします。ES2015(ES6) で追加された機能で、Chrome, Firefox, Safari, Edge ではサポートされていますが、IE11 ではサポートしていません。

JavaScript
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}
Object.is(value1, value2)

value1value2 を比較し、同一であれば true、異なるものであれば false を返します。=== による比較とほぼ同じ結果を返しますが、-0 と +0、Number.Nan と NaN を別物とみなす点が異なります。

JavaScript
Object.is(123, "123");       // => false
Object.is(-0, +0);           // => false
obj.valueOf()

オブジェクトのプリミティブな値を返します。Number などのサブクラスでは、valueOf() をオーバーライドすることで、Number オブジェクトからプリミティブな数値を取り出します。

JavaScript
var num = new Number(12.345);
console.log(num);            // => Number {12.345}
console.log(num.valueOf());  // => 12.345

ゲッターとセッター

ES5 では、プロパティに設定した時、参照した時に関数を呼び出す、ゲッター(getter)とセッター(setter)がサポートされました。下記の例では、name プロパティに値を設定したり、値を参照したりする際に、ゲッター関数、セッター関数が呼び出され、コンソールにログを出力します。

JavaScript
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) では、オブジェクトに対するレスト構文とスプレッド構文がサポートされました。

JavaScript
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() メソッドを上書き(オーバーライド)するものです。

JavaScript
function Person(name, age) {
  this.name = name;
  this.age = age;
  this.toString = function() {
    return (this.name + "(" + this.age + ")");
  }
}

Person() 関数は Person クラスの生成関数(コンストラクタ)として扱われます。Person オブジェクトの実体(インスタンス)を生成するには new 演算子を用います。

JavaScript
var p1 = new Person("Suzuki", 26);
console.log(p1.name);         // => Suzuki
console.log(p1.toString());   // => Suzuki(26)

クラスを継承する

call()apply() を用いて、Person のサブクラス Person2 や Person3 を作成することができます。引数固定の場合は call()、可変個引数の場合は apply() を用います。

JavaScript
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);

[up] [prev] [next]
Copyright (C) 1996-2019 杜甫々
改訂版初版:2001年5月20日、最終更新:2019年3月24日
http://www.tohoho-web.com/js/object.htm