JavaScript/TypeScript

オブジェクトの基本

4
  • JavaScript

オブジェクトの基本 — JavaScript Tips

オブジェクトは キーと値の集まり です。プロパティの読み書き、メソッド、参照の等価、Object.keys あたりが日常の操作になります。

参考: MDN — オブジェクト · MDN — オブジェクト初期化子 · MDN — プロパティ


目次

  1. オブジェクトリテラル
  2. プロパティの読み書き
  3. メソッド
  4. 参照と等価
  5. Object.keys などの基本操作
  6. スプレッドと浅いコピー
  7. よくある失敗

オブジェクトリテラル

{ } でオブジェクトを作ります。

const user = {  name: "太郎",  age: 30,  active: true,};console.log(user.name); // 太郎

変数名と同じキーは省略できる(短縮記法)

const name = "花子";const age = 25;const profile = { name, age };// { name: "花子", age: 25 } と同じ

計算されたプロパティ名

const field = "score";const record = {  [field]: 100,  [`${field}_max`]: 100,};// { score: 100, score_max: 100 }

オブジェクトは 参照型 です。変数には「中身のコピー」ではなく「オブジェクトへの参照」が入ります。


プロパティの読み書き

ドット記法とブラケット記法

const book = { title: "JS入門", year: 2024 };book.title;           // "JS入門"book["title"];        // "JS入門"const key = "year";book[key];            // 2024(キーが変数のときはブラケット)

存在しないプロパティは undefined になります。

book.publisher; // undefined

追加・更新・削除

book.publisher = "Example Press";book.year = 2025;delete book.active; // あれば削除(この例ではもともと無い)

const で宣言したオブジェクトでも プロパティの変更は可能 です(再代入だけ不可)。

const config = { debug: false };config.debug = true; // OK

メソッド

プロパティの値に関数を入れたものがメソッドです。短縮記法で書けます。

const counter = {  value: 0,  increment() {    this.value += 1;    return this.value;  },  reset() {    this.value = 0;  },};counter.increment(); // 1counter.increment(); // 2counter.reset();

this呼び出し方 で変わります。メソッドとして counter.increment() のように呼べば、thiscounter を指します。アロー関数をメソッドにすると this が期待とずれることがあるため、オブジェクトのメソッドは通常の function 短縮記法が無難です。

const math = {  add(a, b) {    return a + b;  },};console.log(math.add(2, 3)); // 5

参照と等価

===同じ参照か を見ます。中身が同じ別オブジェクトは等しくありません。

const a = { x: 1 };const b = { x: 1 };const c = a;console.log(a === b); // false(別オブジェクト)console.log(a === c); // true(同じ参照)c.x = 99;console.log(a.x); // 99(a も変わる)
flowchart LR  subgraph heap["メモリ上のオブジェクト"]    O["{ x: 99 }"]  end  a["変数 a"] --> O  c["変数 c"] --> O  b["変数 b"] --> O2["{ x: 1 }(別インスタンス)"]

配列もオブジェクト

[1, 2] === [1, 2]; // false

中身まで比較するにはループや JSON.stringify(制限あり)、専用ライブラリなどが必要です。学習段階では「オブジェクト比較は参照」と覚えるのが先です。


Object.keys などの基本操作

組み込みの Object 静的メソッドで、キーや値を列挙できます。

const product = {  id: "P001",  name: "ノート",  price: 500,};Object.keys(product);    // ["id", "name", "price"]Object.values(product);  // ["P001", "ノート", 500]Object.entries(product); // [["id","P001"], ["name","ノート"], ["price",500]]

ループとの組み合わせ

for (const key of Object.keys(product)) {  console.log(key, product[key]);}for (const [key, value] of Object.entries(product)) {  console.log(`${key}: ${value}`);}
メソッド 返すもの
Object.keys(obj) 自身の列挙可能なキーの配列
Object.values(obj) 値の配列
Object.entries(obj) [キー, 値] の配列

プロパティの有無

"price" in product;              // trueproduct.hasOwnProperty("id");    // true(プロトタイプチェーンを除く)

in はプロトタイプ鎖上も見ます。自分が定義したプロパティだけなら hasOwnPropertyObject.hasOwn(モダン)を使います。

Object.hasOwn(product, "name"); // true

スプレッドと浅いコピー

オブジェクトのコピーやマージにスプレッド構文を使います。

const defaults = { theme: "light", lang: "ja" };const userPrefs = { lang: "en", fontSize: 14 };const merged = { ...defaults, ...userPrefs };// { theme: "light", lang: "en", fontSize: 14 }// 後から書いた lang が優先

浅いコピーであることに注意

const original = {  meta: { version: 1 },};const copy = { ...original };copy.meta.version = 2;console.log(original.meta.version); // 2(ネストは共有)

深いコピーが必要なら、構造が単純なうちは手で書くか、学習が進んでから専用手段を検討します。

凍結(再代入・プロパティ変更の防止)

const frozen = Object.freeze({ id: 1 });// frozen.id = 2; // 厳格モードではエラー、緩いモードでは無視

よくある失敗

症状 原因 対処
プロパティが undefined typo、存在しないキー キー名を確認。オプショナルチェーン obj?.key
変更したのに別変数が変わらない 参照の共有を理解していない コピーが必要ならスプレッドで新オブジェクトを作る
=== で同じ内容なのに false 参照比較 意図どおり。中身比較は別ロジック
Object.keys に想定外のキー プロトタイプ由来 hasOwn / hasOwnProperty でフィルタ
スプレッド後もネストが共有 浅いコピー ネストごとコピーするか設計を見直す
メソッド内の this が undefined メソッドを変数に抜いて呼んだ call / bind で束縛するか、呼び出し方を見直す

関連: MDN — オブジェクトの使い方 · MDN — Object.keys

シェア