JavaScript/Object
Objectオブジェクト
編集Object
オブジェクトは、String
やNumber
など他のオブジェクトの雛形として利用される基本的なオブジェクトです。
JavaScriptでは、ほぼすべてのデータ型がObject
型を継承しています。
Objectの型
編集以下のコードで、Object
や他の組み込みオブジェクトの型について確認できます。
console.log(`Objectの型 typeof Object => ${typeof Object} typeof String => ${typeof String} typeof Number => ${typeof Number} typeof Function => ${typeof Function} Object === Object.prototype.constructor => ${Object === Object.prototype.constructor} String === String.prototype.constructor => ${String === String.prototype.constructor} Number === Number.prototype.constructor => ${Number === Number.prototype.constructor} Function === Function.prototype.constructor => ${Function === Function.prototype.constructor} `)
実行結果
編集上記のコードを実行すると、以下の結果が得られます:
Objectの型 typeof Object => function typeof String => function typeof Number => function typeof Function => function Object === Object.prototype.constructor => true String === String.prototype.constructor => true Number === Number.prototype.constructor => true Function === Function.prototype.constructor => true
解説
編集Object
の型はfunction
です。これは、Object
だけでなく、String
やNumber
、さらにはFunction
も同様に型がfunction
であることを示しています。- このことから、これらは関数であり、それぞれが自身のオブジェクトを生成するためのコンストラクタ(constructor)であることがわかります。
静的プロパティ
編集Object.length
編集コンストラクターとしてのパラメーター数。
- 値
- 1
- 型
number
Object.name
編集型名。
- 値
- "Object"
- 型
string
Object.prototype
編集一般的なオブジェクトは、Object.prototype
からプロパティ(メソッドを含む)を継承しますが、これらのプロパティはシャドウイング(別名オーバーライド)されることがあります。
しかし、Object.create(null)のように意図的に継承されていないオブジェクトを作成したり、Object.setPrototypeOf
のように継承されていないオブジェクトを変更することもできます。
静的メソッド
編集Object
の静的メソッドは、オブジェクトの構造や振る舞いを制御し、安全に操作するために必要です。これにより、プロトタイプの管理、プロパティの列挙や保護、動的な性質を持つJavaScriptの一貫性を保ちながら柔軟に対応できます。
また、Object
の静的メソッドが使われる大きな理由は名前の衝突を避けるためです。もしプロトタイプにインスタンスメソッドを追加すると、既存のフレームワークやライブラリで同じ名前のメソッドが使われている場合に衝突が発生し、互換性の問題を引き起こします。
例えば、Array.prototype.groupBy
をインスタンスメソッドとして追加した場合、古いライブラリが独自に groupBy
を定義していると、その動作に影響を与えます。このため、標準的な操作やユーティリティ的な機能は静的メソッドとして定義され、既存のプロトタイプを汚染しないように設計されています。
Object.assign()
編集1つ以上のソースオブジェクトから、ターゲットオブジェクトにプロパティをコピーします。
- 構文
Object.assign(target, ...sources)
- パラメータ
-
target
: プロパティのコピー先となるオブジェクトsources
: プロパティのコピー元となる1つ以上のオブジェクト
- 戻り値
-
- 変更されたターゲットオブジェクト
- 例
const target = { a: 1 }; const source = { b: 2, c: 3 }; const result = Object.assign(target, source); console.log(result); // { a: 1, b: 2, c: 3 }
Object.create()
編集指定されたプロトタイプオブジェクトとプロパティを持つ新しいオブジェクトを生成します。
- 構文
Object.create(proto[, propertiesObject])
- パラメータ
-
proto
: 新しいオブジェクトのプロトタイプとなるオブジェクトpropertiesObject
: 新しいオブジェクトに追加するプロパティを指定するオブジェクト(省略可能)
- 戻り値
-
- 指定されたプロトタイプとプロパティを持つ新しいオブジェクト
- 例
const person = { sayHello() { console.log('Hello!'); } }; const john = Object.create(person, { name: { value: 'John', writable: true } }); john.sayHello(); // "Hello!" console.log(john.name); // "John"
Object.defineProperties()
編集オブジェクトに複数の新しいプロパティを定義するか、既存のプロパティを変更します。
- 構文
Object.defineProperties(obj, props)
- パラメータ
-
obj
: プロパティを定義または修正するオブジェクトprops
: 新しいプロパティ記述子を含むオブジェクト
- 戻り値
-
- 変更されたオブジェクト
- 例
const obj = {}; Object.defineProperties(obj, { name: { value: 'John', writable: true }, age: { value: 30, writable: false } });
Object.defineProperty()
編集オブジェクトに新しいプロパティを定義するか、既存のプロパティを変更します。
- 構文
Object.defineProperty(obj, prop, descriptor)
- パラメータ
-
obj
: プロパティを定義または修正するオブジェクトprop
: 定義または修正するプロパティ名descriptor
: プロパティの記述子
- 戻り値
-
- 変更されたオブジェクト
- 例
const obj = {}; Object.defineProperty(obj, 'name', { value: 'John', writable: false, enumerable: true, configurable: true });
Object.entries()
編集オブジェクトの列挙可能なプロパティの [key, value]
ペアの配列を返します。
- 構文
Object.entries(obj)
- パラメータ
-
obj
: 変換するオブジェクト
- 戻り値
-
- 文字列キーを持つ列挙可能なプロパティの
[key, value]
ペアの配列
- 文字列キーを持つ列挙可能なプロパティの
- 例
const obj = { a: 1, b: 2, c: 3 }; console.log(Object.entries(obj)); // [['a', 1], ['b', 2], ['c', 3]]
Object.freeze()
編集オブジェクトを凍結し、プロパティの追加、削除、変更を防ぎます。
- 構文
Object.freeze(obj)
- パラメータ
-
obj
: 凍結するオブジェクト
- 戻り値
-
- 凍結されたオブジェクト
- 例
const obj = { prop: 42 }; Object.freeze(obj); obj.prop = 33; // 厳格モードでエラー console.log(obj.prop); // 42
Object.fromEntries()
編集[key, value]
ペアのリストからオブジェクトを生成します。
- 構文
Object.fromEntries(iterable)
- パラメータ
-
iterable
:[key, value]
ペアを含むイテラブルオブジェクト
- 戻り値
-
- 新しいオブジェクト
- 例
const entries = [['a', 1], ['b', 2], ['c', 3]]; const obj = Object.fromEntries(entries); console.log(obj); // { a: 1, b: 2, c: 3 }
Object.getOwnPropertyDescriptor()
編集オブジェクトの指定されたプロパティの記述子を返します。
- 構文
Object.getOwnPropertyDescriptor(obj, prop)
- パラメータ
-
obj
: 対象のオブジェクトprop
: プロパティ名
- 戻り値
-
- プロパティ記述子オブジェクト
- 例
const obj = { name: 'John' }; const descriptor = Object.getOwnPropertyDescriptor(obj, 'name'); console.log(descriptor); // { // value: 'John', // writable: true, // enumerable: true, // configurable: true // }
Object.getOwnPropertyDescriptors()
編集オブジェクトのすべての独自プロパティの記述子を返します。
- 構文
Object.getOwnPropertyDescriptors(obj)
- パラメータ
-
obj
: 対象のオブジェクト
- 戻り値
-
- すべてのプロパティ記述子を含むオブジェクト
- 例
const obj = { name: 'John', get age() { return 30; } }; console.log(Object.getOwnPropertyDescriptors(obj));
Object.getOwnPropertyNames()
編集オブジェクトの独自プロパティ名の配列を返します。
- 構文
Object.getOwnPropertyNames(obj)
- パラメータ
-
obj
: 対象のオブジェクト
- 戻り値
-
- プロパティ名の配列
- 例
const obj = { a: 1, b: 2 }; Object.defineProperty(obj, 'c', { enumerable: false }); console.log(Object.getOwnPropertyNames(obj)); // ['a', 'b', 'c']
Object.getOwnPropertySymbols()
編集オブジェクトのすべてのSymbolプロパティを返します。
- 構文
Object.getOwnPropertySymbols(obj)
- パラメータ
-
obj
: 対象のオブジェクト
- 戻り値
-
- Symbolプロパティの配列
- 例
const sym = Symbol('mySymbol'); const obj = { [sym]: 'value' }; console.log(Object.getOwnPropertySymbols(obj)); // [Symbol(mySymbol)]
Object.getPrototypeOf()
編集指定されたオブジェクトのプロトタイプを返します。
- 構文
Object.getPrototypeOf(obj)
- パラメータ
-
obj
: プロトタイプを取得するオブジェクト
- 戻り値
-
- 指定されたオブジェクトのプロトタイプ
- 例
const prototype = { x: 10 }; const obj = Object.create(prototype); console.log(Object.getPrototypeOf(obj) === prototype); // true
Object.groupBy()
編集反復可能なオブジェクトの要素をグループ化します。
- 構文
Object.groupBy(items, callbackFn)
- パラメータ
-
items
: グループ化する要素を含むイテラブルcallbackFn
: 各要素のグループを決定するコールバック関数
- 戻り値
-
- グループ化されたオブジェクト
- 例
const inventory = [ { name: 'apple', type: 'fruit' }, { name: 'carrot', type: 'vegetable' } ]; const grouped = Object.groupBy(inventory, item => item.type); console.log(grouped); // { // fruit: [{ name: 'apple', type: 'fruit' }], // vegetable: [{ name: 'carrot', type: 'vegetable' }] // }
Object.hasOwn()
編集オブジェクトが指定されたプロパティを独自のプロパティとして持っているかを判定します。
- 構文
Object.hasOwn(obj, prop)
- パラメータ
-
obj
: 検査するオブジェクトprop
: プロパティ名
- 戻り値
-
- プロパティを持っている場合は true、そうでない場合は false
- 例
const obj = { prop: 42 }; console.log(Object.hasOwn(obj, 'prop')); // true console.log(Object.hasOwn(obj, 'toString')); // false
Object.is()
編集2つの値が同じ値であるかを判定します。
- 構文
Object.is(value1, value2)
- パラメータ
-
value1
: 比較する最初の値value2
: 比較する2番目の値
- 戻り値
-
- 2つの値が同じ場合は true、そうでない場合は false
- 例
console.log(Object.is(0, -0)); // false console.log(Object.is(NaN, NaN)); // true console.log(Object.is({}, {})); // false
Object.isExtensible()
編集オブジェクトに新しいプロパティを追加できるかどうかを判定します。
- 構文
Object.isExtensible(obj)
- パラメータ
-
obj
: 検査するオブジェクト
- 戻り値
-
- オブジェクトが拡張可能な場合は true、そうでない場合は false
- 例
const obj = {}; console.log(Object.isExtensible(obj)); // true Object.freeze(obj); console.log(Object.isExtensible(obj)); // false
Object.isFrozen()
編集オブジェクトが凍結されているかどうかを判定します。
- 構文
Object.isFrozen(obj)
- パラメータ
-
obj
: 検査するオブジェクト
- 戻り値
-
- オブジェクトが凍結されている場合は true、そうでない場合は false
- 例
const obj = { prop: 42 }; console.log(Object.isFrozen(obj)); // false Object.freeze(obj); console.log(Object.isFrozen(obj)); // true
Object.isSealed()
編集オブジェクトがシールされているかどうかを判定します。
- 構文
Object.isSealed(obj)
- パラメータ
-
obj
: 検査するオブジェクト
- 戻り値
-
- オブジェクトがシールされている場合は true、そうでない場合は false
- 例
const obj = { prop: 42 }; console.log(Object.isSealed(obj)); // false Object.seal(obj); console.log(Object.isSealed(obj)); // true
Object.keys()
編集オブジェクトの列挙可能なプロパティ名の配列を返します。
- 構文
Object.keys(obj)
- パラメータ
-
obj
: プロパティを取得するオブジェクト
- 戻り値
-
- 文字列の配列
- 例
const obj = { a: 1, b: 2, c: 3 }; console.log(Object.keys(obj)); // ['a', 'b', 'c']
Object.preventExtensions()
編集オブジェクトに新しいプロパティが追加されるのを防ぎます。
- 構文
Object.preventExtensions(obj)
- パラメータ
-
obj
: 拡張を防止するオブジェクト
- 戻り値
-
- 拡張が防止されたオブジェクト
- 例
const obj = { prop: 42 }; Object.preventExtensions(obj); obj.newProp = 123; // 厳格モードでエラー console.log(obj.newProp); // undefined
Object.seal()
編集オブジェクトをシールし、プロパティの追加や削除を防ぎます。
- 構文
Object.seal(obj)
- パラメータ
-
obj
: シールするオブジェクト
- 戻り値
-
- シールされたオブジェクト
- 例
const obj = { prop: 42 }; Object.seal(obj); obj.newProp = 123; // 厳格モードでエラー delete obj.prop; // 厳格モードでエラー obj.prop = 123; // 可能
Object.setPrototypeOf()
編集オブジェクトのプロトタイプを設定します。
- 構文
Object.setPrototypeOf(obj, prototype)
- パラメータ
-
obj
: プロトタイプを変更するオブジェクトprototype
: 新しいプロトタイプオブジェクトまたは null
- 戻り値
-
- プロトタイプが変更されたオブジェクト
- 例
const obj = { a: 1}; const prototype = { b: 2 }; Object.setPrototypeOf(obj, prototype); console.log(obj.b); // 2
Object.values()
編集オブジェクトの列挙可能なプロパティの値の配列を返します。
- 構文
Object.values(obj)
- パラメータ
-
obj
: 値を取得するオブジェクト
- 戻り値
-
- 値の配列
- 例
const obj = { a: 1, b: 2, c: 3 }; console.log(Object.values(obj)); // [1, 2, 3] const str = 'hello'; console.log(Object.values(str)); // ['h', 'e', 'l', 'l', 'o']
メソッドの使用例と注意点
編集オブジェクトのディープクローン
編集function deepClone(obj) { // プリミティブ値の場合はそのまま返す if (obj === null || typeof obj !== 'object') return obj; // 新しいオブジェクトを作成 const clone = Array.isArray(obj) ? [] : {}; // プロパティをディープコピー Object.entries(obj).forEach((<code>[key, value]</code>) => { clone[key] = deepClone(value); }); return clone; } const original = { a: 1, b: { c: 2 }, d: [3, 4, { e: 5 }] }; const cloned = deepClone(original); console.log(cloned); // originalと同じ構造を持つ新しいオブジェクト
オブジェクトの不変性の実装
編集const config = { apiKey: 'secret123', endpoints: { users: '/api/users', posts: '/api/posts' } }; // オブジェクトを完全に不変にする const frozenConfig = Object.freeze(config); // ネストされたオブジェクトも含めて完全に不変にする function deepFreeze(obj) { // プリミティブ値の場合は何もしない if (obj === null || typeof obj !== 'object') return obj; // まず自身のプロパティを凍結 Object.freeze(obj); // 再帰的に全てのプロパティを凍結 Object.values(obj).forEach(deepFreeze); return obj; } const immutableConfig = deepFreeze(config);
プロパティの詳細な制御
編集const user = {}; // getter/setterを使用したプロパティの定義 Object.defineProperty(user, 'fullName', { get() { return `${this.firstName} ${this.lastName}`; }, set(value) { [this.firstName, this.lastName] = value.split(' '); } }); // 複数のプロパティを一度に定義 Object.defineProperties(user, { age: { value: 30, writable: true, enumerable: true }, id: { value: 'user123', writable: false, enumerable: false } }); user.fullName = 'John Doe'; console.log(user.fullName); // "John Doe"
性能に関する注意点
編集- Object.freeze()やObject.seal()は、大きなオブジェクトに対して使用すると性能に影響を与える可能性があります。
- Object.keys()、Object.values()、Object.entries()は、大きなオブジェクトに対して頻繁に呼び出す場合、キャッシュを検討してください。
- Object.defineProperty()による動的なプロパティの定義は、直接プロパティを設定するよりも若干遅くなる可能性があります。
互換性に関する注意点
編集- Object.groupBy()は比較的新しいメソッドで、すべての環境でサポートされているわけではありません。
- プロキシやリフレクションAPIと組み合わせる場合は、追加の互換性チェックが必要になる場合があります。
インスタンスメソッド
編集Object.prototype.__defineGetter__()
編集- 構文
obj.__defineGetter__(prop, func)
オブジェクトの指定されたプロパティにゲッタ関数を定義します。非推奨とされており、Object.defineProperty()
の使用が推奨されます。
Object.prototype.__defineSetter__()
編集- 構文
obj.__defineSetter__(prop, func)
オブジェクトの指定されたプロパティにセッタ関数を定義します。非推奨とされており、Object.defineProperty()
の使用が推奨されます。
Object.prototype.__lookupGetter__()
編集- 構文
obj.__lookupGetter__(prop)
指定されたプロパティに関連付けられたゲッタ関数を取得します。非推奨とされており、新しいコードでは使用を避けるべきです。
Object.prototype.__lookupSetter__()
編集- 構文
obj.__lookupSetter__(prop)
指定されたプロパティに関連付けられたセッタ関数を取得します。非推奨とされており、新しいコードでは使用を避けるべきです。
Object.prototype.constructor
編集- 構文
obj.constructor
オブジェクトを構築した関数を返します。オブジェクトのプロトタイプチェーンを確認する際に役立ちます。
Object.prototype.hasOwnProperty()
編集- 構文
obj.hasOwnProperty(prop)
オブジェクトが指定されたプロパティを直接所有しているかどうかを判定します。
Object.prototype.isPrototypeOf()
編集- 構文
obj.isPrototypeOf(object)
指定されたオブジェクトが、自身のプロトタイプチェーンに含まれているかどうかを判定します。
Object.prototype.propertyIsEnumerable()
編集- 構文
obj.propertyIsEnumerable(prop)
オブジェクトの指定されたプロパティが列挙可能かどうかを判定します。
Object.prototype.toLocaleString()
編集- 構文
obj.toLocaleString()
オブジェクトをロケールに依存した文字列表現に変換します。通常はtoString()
メソッドを呼び出しますが、ロケール固有の動作を実装することも可能です。
Object.prototype.toString()
編集- 構文
obj.toString()
オブジェクトを文字列表現に変換します。通常は[object Type]
の形式で返されます。
toString()メソッドは、オブジェクトを表す文字列を返します[1]。
すべてのオブジェクトは toString() メソッドを持っています。このメソッドは、オブジェクトがテキスト値として表現される場合や、文字列が期待される方法でオブジェクトが参照される場合に、自動的に呼び出されます。デフォルトでは、toString()メソッドは、Objectの子孫であるすべてのオブジェクトに継承されます。カスタム・オブジェクトでこのメソッドがオーバーライドされていない場合、toString() は "[object type]" を返し、type はオブジェクト・タイプです。以下のコードで説明します。
Object.prototype.valueOf()
編集オブジェクトのプリミティブ値を返します。
- 構文
obj.valueOf()
- 戻り値
-
- オブジェクトのプリミティブ値
- 例
const num = new Number(123); console.log(num.valueOf()); // 123 const str = new String("hello"); console.log(str.valueOf()); // "hello"
Object.prototype.toLocaleString()
編集基本的にtoStringと全く同じ動作を行う。 このメソッドは、ArrayやNumber、Date型のオブジェクトがtoLocaleStringを持っているのに対し、他のオブジェクトはこれを持っていないため、他の型でtoLocaleStringが呼び出される場合でもエラー出してプログラムの実行が止まらないための雛形として用意されています。 他のデータ型でtoLocaleStringを使うべき問題にあたった場合にそれぞれのデータ型でメソッドを定義してやればよい。
Object.prototype.hasOwnProperty(V)
編集オブジェクトが引数で渡したプロパティを自前で持っているかをチェックする。持っていない場合、および他のクラスから継承している場合はfalseを返す。
for~in文は通常、オブジェクトにプロパティやメソッドを追加したときにその違いが出る。 例えば次の様なオブジェクトを作成したとする。
Object.prototype.getBMI = function(){ return this[体重] / this[身長] ** 2 } const girl ={ 身長: 158, 体重: 49 }; for (const p in girl) console.log(p, ' : ', girl[p]); /* 身長 : 158 体重 : 49 getBMI : ƒ (){ return this[体重] / this[身長] ** 2 } */
この様にすると結果として、「身長」、「体重」の他に「getBMI」のメソッドの中身も表示されてしまう。 それを禁止するために、親オブジェクトから取得したデータを無視するため次の様に記述する。
for (const p in girl) if (girl.hasOwnProperty(p)) console.log(p, ' : ', girl[p]);
ちなみに、親オブジェクトも含めてそのプロパティを持っているかどうかを調べるにはin演算子を使用する。
if (p in girl) { /* ... */ }
Object.prototype.valueOf()
編集データの値をそのまま返す。 このメソッドは他のオブジェクトでそれぞれオーバーライドされるのを期待されて存在しています。 そのため、単体としてそれほどの意味は無い。 プリミティブ型のラッパーオブジェクトから元のプリミティブを得る時に使われる。
Object.prototype.isPrototypeOf(V)
編集引数で与えたオブジェクトが、自分の子孫ノードであるかどうかをチェックする。
function Foo(){} function Bar(){} function Baz(){} Bar.prototype = new Foo(); Baz.prototype = new Bar(); console.log(Foo.prototype.isPrototypeOf(new Bar())); // true console.log(Foo.prototype.isPrototypeOf(new Baz())); // true
Object.prototype.propertyIsEnumerable(V)
編集引数で指定したプロパティがオブジェクト自身のプロパティかつ、for~in文で列挙可能なものであるのかをチェックする。 プロパティでなければfalseを、列挙可能ならtrueを、不可能ならfalseを返す。
下位階層のページ
編集脚註
編集- ^ “Object.prototype.toString() - JavaScript // MDN” (2021年9月13日). 2021年11月23日閲覧。