JavaScript/Object

Object はグローバルオブジェクトの一部で、すべてのJavaScriptオブジェクトの機能とプロパティを表す基本的な組み込みオブジェクトです。Object クラスは、JavaScript のオブジェクト階層の基盤となっており、すべてのオブジェクトに共通の機能を提供します[1]

説明

編集

JavaScript において、オブジェクトはプロパティと呼ばれる名前と値のペアのコレクションです。Object コンストラクタは、指定されたオブジェクトをラップするオブジェクトを作成します。Objectnew 演算子と共に呼び出す場合も、単に関数として呼び出す場合も、新しいオブジェクトが生成されます。

構文

編集
// オブジェクトリテラル
let obj = { property1: value1, property2: value2, ... };

// コンストラクタを使用
let obj = new Object();

// Object.create() を使用
let obj = Object.create(proto);

プロパティとメソッド

編集

静的プロパティ

編集
静的プロパティ
名称 解説
Object.length Objectコンストラクタが受け取る引数の数を返します。常に1です。
Object.name Objectコンストラクタの名前を返します。常に"Object"です。
Object.prototype すべてのJavaScriptオブジェクトの祖先となるObjectプロトタイプオブジェクトへの参照です。
一般的なオブジェクトは、code>Object.prototypeからプロパティ(メソッドを含む)を継承しますが、これらのプロパティはオーバーライドされることがあります。
しかし、Object.create(null)を使用すると、継承関係を持たないオブジェクトを作成できます。
また、<Object.setPrototypeOfを使用すると、既存のオブジェクトの継承関係を変更することも可能です。

静的アクセサ

編集

なし

静的メソッド

編集
静的メソッド
名称 解説
Object.assign() ターゲットオブジェクトにソースオブジェクトのプロパティをコピーします。
Object.create() 指定されたプロトタイプオブジェクトとプロパティを持つ新しいオブジェクトを作成します。
Object.defineProperties() オブジェクトに複数の新しいプロパティを定義または既存のプロパティを変更します。
Object.defineProperty() オブジェクトに新しいプロパティを定義または既存のプロパティを変更します。
Object.entries() オブジェクトの列挙可能な文字列キープロパティ [key, value] ペアの配列を返します。
Object.freeze() オブジェクトを凍結します。凍結されたオブジェクトは変更できません。
Object.fromEntries() [key, value] ペアのリストから新しいオブジェクトを作成します。
Object.getOwnPropertyDescriptor() オブジェクトの特定のプロパティのプロパティ記述子を返します。
Object.getOwnPropertyDescriptors() オブジェクトのすべてのプロパティのプロパティ記述子を返します。
Object.getOwnPropertyNames() オブジェクトの列挙可能および列挙不可能なプロパティ名の配列を返します。
Object.getOwnPropertySymbols() オブジェクトの直接所有するシンボルプロパティの配列を返します。
Object.getPrototypeOf() 指定されたオブジェクトのプロトタイプ (内部 Prototype プロパティの値) を返します。
Object.groupBy() 配列要素をグループ化し、グループ化された要素をプロパティとして持つオブジェクトを返します。
Object.hasOwn() オブジェクトが指定されたプロパティを直接所有しているかどうかを示すブール値を返します。
Object.is() 2つの値が同じ値であるかを判定します。厳密等価演算子 (===) よりも厳密です。
Object.isExtensible() オブジェクトが拡張可能かどうかを判定します。
Object.isFrozen() オブジェクトが凍結されているかどうかを判定します。
Object.isSealed() オブジェクトが封印されているかどうかを判定します。
Object.keys() オブジェクトの列挙可能な文字列キープロパティ名の配列を返します。
Object.preventExtensions() オブジェクトの拡張を防止します。
Object.seal() オブジェクトを封印します。封印されたオブジェクトは新しいプロパティを追加できません。
Object.setPrototypeOf() 指定されたオブジェクトのプロトタイプ (内部 Prototype プロパティ) を設定します。
Object.values() オブジェクトの列挙可能な文字列キープロパティ値の配列を返します。

Object のメソッドは、オブジェクトの構造や振る舞いを制御し、安全に操作するために必要です。これにより、プロトタイプの管理、プロパティの列挙や保護、動的な性質を持つJavaScriptの一貫性を保ちながら柔軟に対応できます。

また、Object のメソッドが使われる大きな理由は名前の衝突を避けるためです。もしプロトタイプにインスタンスメソッドを追加すると、既存のフレームワークやライブラリで同じ名前のメソッドが使われている場合に衝突が発生し、互換性の問題を引き起こします。

例えば、Array.prototype.groupBy をインスタンスメソッドとして追加した場合、古いライブラリが独自に groupBy を定義していると、その動作に影響を与えます。このため、標準的な操作やユーティリティ的な機能は静的メソッドとして定義され、既存のプロトタイプを汚染しないように設計されています。

インスタンスプロパティ

編集

なし

インスタンスアクセサ

編集
get Object.prototype.__proto__

インスタンスメソッド

編集
インスタンスメソッド
名称 解説
Object.prototype.__defineGetter__() オブジェクトのプロパティにゲッター関数を定義します。(非推奨)
Object.prototype.__defineSetter__() オブジェクトのプロパティにセッター関数を定義します。(非推奨)
Object.prototype.__lookupGetter__() オブジェクトのプロパティのゲッター関数を返します。(非推奨)
Object.prototype.__lookupSetter__() オブジェクトのプロパティのセッター関数を返します。(非推奨)
Object.prototype.constructor() オブジェクトのコンストラクタ関数への参照を返します。
Object.prototype.hasOwnProperty() オブジェクトが指定されたプロパティを直接所有しているかどうかを示すブール値を返します。
Object.prototype.isPrototypeOf() 指定されたオブジェクトが、このオブジェクトのプロトタイプチェーンに存在するかどうかを示すブール値を返します。
Object.prototype.propertyIsEnumerable() 指定されたプロパティが列挙可能かどうかを示すブール値を返します。
Object.prototype.toLocaleString() オブジェクトの地域対応文字列を返します。
Object.prototype.toString() オブジェクトの文字列表現を返します。
Object.prototype.valueOf() オブジェクトのプリミティブ値を返します。

オブジェクトの作成

編集

以下のプログラムは、オブジェクトを作成する様々な方法を示しています。

// オブジェクトリテラルを使用
const person1 = {
  firstName: "John",
  lastName: "Doe",
  age: 30
};

// new Object() を使用
const person2 = new Object();
person2.firstName = "Jane";
person2.lastName = "Doe";
person2.age = 28;

// Object.create() を使用
const personProto = {
  greet: function() {
    return <code>Hello, my name is ${this.firstName} ${this.lastName}</code>;
  }
};

const person3 = Object.create(personProto);
person3.firstName = "Alice";
person3.lastName = "Smith";
person3.age = 25;

console.log(person3.greet()); // "Hello, my name is Alice Smith"

このプログラムでは、オブジェクトリテラル、new Object()Object.create() の3つの方法でオブジェクトを作成しています。

オブジェクトのプロパティの操作

編集

以下のプログラムは、オブジェクトのプロパティを操作する方法を示しています。

const obj = { a: 1, b: 2 };

// プロパティの追加
obj.c = 3;
console.log(obj); // { a: 1, b: 2, c: 3 }

// プロパティの削除
delete obj.b;
console.log(obj); // { a: 1, c: 3 }

// プロパティの存在確認
console.log('a' in obj); // true
console.log(obj.hasOwnProperty('a')); // true
console.log('b' in obj); // false

// プロパティの列挙
console.log(Object.keys(obj)); // ["a", "c"]
console.log(Object.values(obj)); // [1, 3]
console.log(Object.entries(obj)); // [["a", 1], ["c", 3]]

このプログラムでは、プロパティの追加、削除、存在確認、列挙などの基本的なオブジェクト操作を行っています。

オブジェクトの複製と結合

編集

以下のプログラムは、オブジェクトの複製と結合を行う方法を示しています。

const obj1 = { a: 1, b: 2 };
const obj2 = { b: 3, c: 4 };

// オブジェクトの浅いコピー
const copy = Object.assign({}, obj1);
console.log(copy); // { a: 1, b: 2 }

// オブジェクトの結合
const merged = Object.assign({}, obj1, obj2);
console.log(merged); // { a: 1, b: 3, c: 4 }

// スプレッド構文を使用した結合(ES6以降)
const mergedSpread = { ...obj1, ...obj2 };
console.log(mergedSpread); // { a: 1, b: 3, c: 4 }

このプログラムでは、Object.assign() とスプレッド構文を使用してオブジェクトの複製と結合を行っています。

注意点

編集
  • プリミティブ値: undefinednull 以外のプリミティブ値(文字列、数値、論理値)を new Object() に渡すと、対応するラッパーオブジェクトが作成されます。
  • プロパティアクセス: オブジェクトのプロパティには、ドット記法(obj.property)またはブラケット記法(obj["property"])でアクセスできます。
  • プロトタイプチェーン: すべてのJavaScriptオブジェクトは Object.prototype から継承し、プロトタイプチェーンを通じてそのメソッドとプロパティにアクセスできます。
  • 不変性: Object.freeze()Object.seal()Object.preventExtensions() を使用してオブジェクトの変更を制限できます。

諸注意

編集

メソッドの使用例と注意点

編集

オブジェクトのディープクローン

編集
function deepClone(obj) {
  if (obj === null || typeof obj !== 'object') return obj;

  if (typeof structuredClone === 'function') {
    return structuredClone(obj);
  }

  const clone = Array.isArray(obj) ? [] : {};
  for (const [key, value] of Object.entries(obj)) {
    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);

オブジェクトの不変性の実装

編集
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と組み合わせる場合は、追加の互換性チェックが必要になる場合があります。

下位階層のページ

編集

脚註

編集
  1. ^ Object は JavaScript における基本的なデータ型であり、すべてのオブジェクトの原型(プロトタイプ)となります。

外部リンク

編集