404 Not Found

404 Not Found


nginx

JavaScriptのオブジェクト

オブジェクトはJavaScriptで最も重要なデータ構造です。インフォメーションカードのように考えましょう。表面には「名前:花子」、裏面には「年齢:20」と書かれています。各情報にはキーがあり、キーと値のペアを形成します。

📖 まとめ

オブジェクトリテラルの作成

波括弧{}を使ってオブジェクトを直接記述します。これが最も一般的な方法です:

HTML
<script>
const student = {
  name: "花子",
  age: 20,
  major: "コンピュータサイエンス"
};
console.log(student);
</script>

キーと値のペアはコロンで区切られ、ペアはカンマで区切られます。最後のペアの後にカンマを付けることもでき、将来の追加に便利です。

プロパティへのアクセス

オブジェクトのプロパティにアクセスする2つの方法:

方法 構文 いつ使うか
ドット記法 obj.name プロパティ名が有効な識別子の場合
ブラケット記法 obj["name"] 名前に特殊文字が含まれるか、変数に格納されている場合

ブラケット記法の最大の利点:変数をキーとして使用できることです。

HTML
<script>
const key = "name";
console.log(student[key]); // student["name"]と同じ
</script>

プロパティの変更と追加

オブジェクト作成後、いつでも既存のプロパティを変更したり、新しいプロパティを追加したりできます。constで宣言されたオブジェクトでも可能です(constは参照をロックし、内容はロックしない)。

HTML
<script>
student.age = 21;          // 変更
student.grade = "3年生";   // 新しいプロパティを追加
console.log(student);
</script>

プロパティの削除

delete演算子でプロパティを完全に削除します:

HTML
<script>
delete student.grade;
console.log(student);
</script>

削除後、そのプロパティにアクセスするとundefinedを返します。

メソッド

オブジェクト内の関数はメソッドと呼ばれます。関数がプロパティの値になると、オブジェクトが「行動」できるようになります:

HTML
<script>
const dog = {
  name: "レックス",
  bark() {
    return "ワン!僕は" + this.name;
  }
};
console.log(dog.bark());
</script>

thisキーワード

thisは「現在のオブジェクト」を指します。メソッドを呼び出したのが誰かで、thisがそのオブジェクトになります。これはJavaScriptのもっとも厄介な概念の一つで、メソッドを抽出して別に呼び出すと、thisは元のオブジェクトを指さなくなります

HTML
<script>
const bark = dog.bark;
console.log(bark()); // thisはdogを指さない — windowまたはundefinedになる可能性
</script>

コンストラクタ

同じ構造の複数のオブジェクトを一括作成する必要がある場合、コンストラクタ関数を使います:

HTML
<script>
function Person(name, age) {
  this.name = name;
  this.age = age;
  this.sayHi = function() {
    return "こんにちは、僕は" + this.name + "です";
  };
}

const p1 = new Person("太郎", 25);
const p2 = new Person("一郎", 30);
console.log(p1.sayHi());
console.log(p2.sayHi());
</script>

newは3つのことを行います:空のオブジェクトを作成 → thisをそこに設定 → オブジェクトを返します。

Object.keys / values / entries

この3つの静的メソッドは、オブジェクトのキー、値、キーと値のペアの配列を返します:

メソッド 戻り値
Object.keys(obj) ["name", "age"]
Object.values(obj) ["花子", 20]
Object.entries(obj) [["name","花子"], ["age",20]]

オブジェクトの反復に非常に便利です:Object.keys(obj).forEach(key => ...)


実例:学生オブジェクトの作成と情報表示

HTML
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>オブジェクト基礎</title>
  <style>
    body { font-family: sans-serif; padding: 20px; }
    .card { border: 2px solid #4a90d9; border-radius: 8px; padding: 16px; max-width: 360px; background: #f0f7ff; }
    .card h3 { margin: 0 0 8px; color: #4a90d9; }
    .card p { margin: 4px 0; }
  </style>
</head>
<body>
  <h2>学生情報カード</h2>
  <div id="output"></div>
  <script>
    const student = {
      name: "花子",
      age: 20,
      major: "コンピュータサイエンス",
      gpa: 3.7,
      introduce() {
        return `私の名前は${this.name}です。${this.age}歳で、${this.major}を専攻しており、GPAは${this.gpa}です。`;
      }
    };

    const output = document.getElementById("output");
    output.innerHTML = `
      <div class="card">
        <h3>${student.name}</h3>
        <p>年齢: ${student.age}</p>
        <p>専攻: ${student.major}</p>
        <p>GPA: ${student.gpa}</p>
        <p><em>${student.introduce()}</em></p>
      </div>
    `;
  </script>
</body>
</html>

実例:ドット記法とブラケット記法の比較

HTML
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>プロパティアクセス方法</title>
  <style>
    body { font-family: sans-serif; padding: 20px; }
    .result { background: #f5f5f5; padding: 12px; border-radius: 6px; margin: 8px 0; }
    code { background: #e0e0e0; padding: 2px 6px; border-radius: 3px; }
  </style>
</head>
<body>
  <h2>プロパティアクセス比較</h2>
  <div id="output"></div>
  <script>
    const user = {
      name: "太郎",
      age: 28,
      "home-city": "東京"
    };

    const key = "name";
    const results = [];

    results.push(`user.name → ${user.name}`);
    results.push(`user["name"] → ${user["name"]}`);
    results.push(`user[key](key="name") → ${user[key]}`);
    results.push(`user["home-city"] → ${user["home-city"]}`);

    document.getElementById("output").innerHTML = results
      .map(r => `<div class="result"><code>${r}</code></div>`)
      .join("");
  </script>
</body>
</html>

実例:プロパティの動的な追加、変更、削除

HTML
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>プロパティ操作</title>
  <style>
    body { font-family: sans-serif; padding: 20px; }
    table { border-collapse: collapse; margin: 12px 0; }
    td, th { border: 1px solid #ccc; padding: 8px 14px; text-align: left; }
    th { background: #4a90d9; color: #fff; }
    .action { color: #888; font-style: italic; margin: 8px 0; }
  </style>
</head>
<body>
  <h2>オブジェクトプロパティ操作</h2>
  <div id="output"></div>
  <script>
    const product = { name: "ノートPC", price: 999 };
    const log = [];

    function showState(label) {
      log.push({ label, snapshot: JSON.stringify(product) });
    }

    showState("初期状態");
    product.price = 899;
    showState("価格を899に変更");
    product.brand = "レノボ";
    showState("brandプロパティを追加");
    delete product.brand;
    showState("brandプロパティを削除");

    const output = document.getElementById("output");
    output.innerHTML = "<table><tr><th>操作</th><th>オブジェクト状態</th></tr>" +
      log.map(r => `<tr><td>${r.label}</td><td>${r.snapshot}</td></tr>`).join("") +
      "</table>";
  </script>
</body>
</html>

実例:コンストラクタとObject.keys/values/entries

HTML
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>コンストラクタとObjectメソッド</title>
  <style>
    body { font-family: sans-serif; padding: 20px; }
    .section { margin: 16px 0; padding: 12px; background: #f9f9f9; border-radius: 6px; }
    .section h3 { margin-top: 0; color: #4a90d9; }
    ul { padding-left: 20px; }
    li { margin: 4px 0; }
  </style>
</head>
<body>
  <h2>コンストラクタと静的Objectメソッド</h2>
  <div id="output"></div>
  <script>
    function Phone(brand, model, price) {
      this.brand = brand;
      this.model = model;
      this.price = price;
      this.showInfo = function() {
        return `${this.brand} ${this.model} — $${this.price}`;
      };
    }

    const p1 = new Phone("サムスン", "Galaxy S24", 899);
    const p2 = new Phone("アップル", "iPhone 15", 999);

    const keys = Object.keys(p1);
    const values = Object.values(p1);
    const entries = Object.entries(p1);

    document.getElementById("output").innerHTML = `
      <div class="section">
        <h3>コンストラクタで作成したオブジェクト</h3>
        <p>${p1.showInfo()}</p>
        <p>${p2.showInfo()}</p>
      </div>
      <div class="section">
        <h3>Object.keys(p1)</h3>
        <ul>${keys.map(k => `<li>${k}</li>`).join("")}</ul>
      </div>
      <div class="section">
        <h3>Object.values(p1)</h3>
        <ul>${values.map(v => `<li>${v}</li>`).join("")}</ul>
      </div>
      <div class="section">
        <h3>Object.entries(p1)</h3>
        <ul>${entries.map(([k, v]) => `<li><code>${k}</code>: <code>${v}</code></li>`).join("")}</ul>
      </div>
    `;
  </script>
</body>
</html>

❓ よくある質問

Q constで宣言されたオブジェクトのプロパティは変更できますか?
A はい。constは変数の参照(常に同じオブジェクトを指すことを意味する)をロックしますが、オブジェクトの内容はロックしません。プロパティの追加、変更、削除は自由に行えますが、obj = {}のように再代入はできません。
Q ドット記法ではなくブラケット記法を使うのはいつですか?
A プロパティ名にスペースやハイフンが含まれる場合("home-city"など)、または動的アクセスのために名前が変数に格納されている場合は、ブラケット記法を使う必要があります。それ以外の場合は、ドット記法がクリーンで推奨されます。
Q コンストラクタでnewを忘れた場合どうなりますか?
A thisがグローバルオブジェクトを指すようになり(厳密モードではundefined)、プロパティが間違った場所に配置されるかエラーが発生します。これは古典的な落とし穴で、ES6のclass構文では自動的に処理されます。

📝 演習

  1. titleauthoryearプロパティと、"title by author, published in year"のような文字列を返すgetSummary()メソッドを持つbookオブジェクトを作成してください。
  2. コンストラクタCar(brand, model, year)を書き、それを使って3台の車を作成し、Object.keysで1台の車のすべてのプロパティ名を一覧表示してください。
  3. 上記の車のいずれかにdrive()メソッドを動的に追加してください("brand model is driving"を返す)。呼び出して、メソッド内でthisが現在のオブジェクトを指すことを観察してください。
100%