Skip to content
This page has been auto-translated and may contain errors.View in English

オブジェクト

docs.scrimba.com

ユーザーを説明しているとします。名前、メールアドレス、年齢、サインイン状態などです。これらを4つの別々の変数に散らすこともできますが、それらは一緒に属しており、それらを分けておくと、「ユーザー」を意味するときに毎回4つのことを渡す必要があります。オブジェクトはすべてを1つの値に集め、各部分が検索できる名前を持つようにします。ほとんどのデータ、ユーザー、製品、カートはちょうどこのような形で到着します。

オブジェクトを作成する

**オブジェクト**は名前付き値の集まりで、中括弧で書きます。内部では、key: valueのペアをカンマで区切ってリストします。キーは名前であり、値はそれが保持しているもです:

js
const user = {
  name: "太郎",
  age: 27,
};

console.log(user.name); // 太郎

ドットとキーで値を読み取ります:user.name。これはドット記法と呼ばれ、ほとんどの場合これを使用します。左のキー、右に保存された値です。

値を読み取るための2番目の方法があり、キーを文字列として角括弧を使用します:

js
console.log(user["name"]); // 太郎

ほとんどの場合、ドット記法の方がクリーンに読めるため、それを使用してください。括弧は、キーが通常の単語ではない場合(例えばスペースが含まれている場合)や、キーが事前にわからず、別の変数に格納されている場合に活躍します。

**オブジェクト**は関連する値を文字列キーの下にグループ化し、中括弧内のkey: valueペアとして書きます。配列が位置で到達する順序付きリストを保持する場合、オブジェクトは名前で到達する値を保持します:

js
const user = {
  name: "太郎",
  age: 27,
  isActive: true,
};

console.log(user.name); // 太郎
console.log(user["age"]); // 27

アクセス方法は2つあります。ドット記法(user.name)がデフォルトで、より短く明確です。括弧記法(user["age"])は同じ仕事をしますが、キーを文字列として受け取り、ドット記法ができない2つのことを解放します。

括弧形式は、キーが有効な識別子ではない場合(例えばスペースを含む場合や数字で始まる場合)に必須で、キーが動的で、文字通り入力されるのではなく変数に格納されている場合に必須です:

js
const field = "name";
console.log(user[field]); // 太郎。fieldに格納されているキーを読み取ります
console.log(user.field); // undefined。"field"という文字通りのキーを探します

この違いは人々を混乱させます:user[field]fieldの値を使用し、user.fieldfieldというスペルのキーを探します。存在しないキーを読み取ると、エラーではなくundefinedが返されます。

**オブジェクト**はJavaScriptの値をキーの下にグループ化するための中核構造です。キーは文字列(またはSymbols、今のところ無視できます)です。値は別のオブジェクトや関数を含む何でもかまいません。中括弧内のkey: valueペアとして書きます:

js
const user = {
  name: "太郎",
  age: 27,
  isActive: true,
};

console.log(user.name); // 太郎
console.log(user["age"]); // 27

ドット記法はイディオマティックなデフォルトです。括弧記法は計算された式としてのキーで同じ検索であり、正確に2つの場合に必須です:キーが有効な識別子ではない場合(user["first name"]user["2fa"])、およびキーが動的な場合:

js
const field = "name";
console.log(user[field]); // 太郎。最初に`field`を"name"に評価します

保持する価値のある2つの動作があります。存在しないキーを読み取るとundefinedが返され、スローされることはないため、タイポは大きく失敗するのではなく静かに失敗します。キーは常にその内部で文字列です:user[27]user["27"]は同じスロットに到達します。これは数字が文字列キーに強制されるためです。この強制は、オブジェクトキーと配列インデックスが似た外観になり始めるときの混乱の一般的な原因です。

js
const product = {
  title: "デスクランプ",
  price: 40,
  inStock: true,
};

console.log(`${product.title}は${product.price}です`); // デスクランプは40です

オブジェクトは他の値と同様に値です。constに格納し、配列に入れ、関数に渡し、返すことができます。キーはその部分に名前を与え、それが全体です:product.priceはそれが何であるかを言い、変数に座っている裸の40はそうではありません。

Junoオブジェクトを作成する オブジェクトは中括弧内のkey: valueペアとして書かれた名前の下に関連する値を集めます。ドットとキーで値を読み取ります。user.nameのように。キーに奇妙な文字が含まれている場合または変数に格納されている場合にのみ、角括弧形式に手を伸ばしてください。
Junoオブジェクトを作成する オブジェクトは配列が位置で値に到達するのと同様に名前で値に到達します。ドット記法がデフォルトです。括弧記法はキーを文字列として使用し、通常の単語ではないキーまたは変数に格納されているキーに使用します。user[field]fieldに格納されているキーを読み取り、user.fieldはリテラルfieldキーを探し、存在しないキーは、エラーを発生させる代わりにundefinedとして返されることを覚えておいてください。
Junoオブジェクトを作成する キーはその内部で文字列であるため、user[27]user["27"]は同じスロットにヒットし、存在しないキーはスローされるのではなくundefinedを返します。ドット記法はイディオマティック;括弧記法は計算されたキーでの同じ検索で、識別子以外のキーと動的なキーに必要です。タイポの静かなundefinedは便利で、バグを隠すまでです。

オブジェクトを変更する

オブジェクトは一度作成されたら固定されていません。新しいキーを追加したり、既存のキーを変更したり、完全に削除したりできます。追加または更新するには、キーに割り当てます:

js
const user = {
  name: "太郎",
};

user.age = 30; // 新しいキーを追加します
user.name = "太郎山田"; // 既存のものを更新します

console.log(user); // { name: "太郎山田", age: 30 }

キーが既に存在する場合、割り当てると値が置き換わります。そうでない場合は、作成されます。キーを削除するには、deleteを使用します:

js
delete user.age;
console.log(user); // { name: "太郎山田" }

ここが人々を驚かせる部分です。Aconstオブジェクトでもそのプロパティを変更できます。constは名前userが異なるオブジェクトをポイントできないことを意味しますが、それが指すオブジェクトは公正なゲームです:

js
const cart = { total: 0 };
cart.total = 25; // 問題ありません。内部を変更する場合
// cart = { total: 25 }; // これはエラーになります。名前を再割り当てする場合

オブジェクトは可変です:作成後にキーを追加、更新、削除します。キーへの割り当ては、新しい場合は作成し、存在する場合は上書きします。キーを削除することはdeleteの仕事です:

js
const user = { name: "太郎" };

user.age = 30; // 追加
user.age = 31; // 更新
delete user.age; // 削除

console.log(user); // { name: "太郎" }

人々をキャッチするものはconstです。constは名前をロックし、内容をロックしません。バインディングは新しいオブジェクトに再割り当てできませんが、保持されるオブジェクトは完全に編集可能なままです:

js
const cart = { total: 0, items: 0 };
cart.total = 25; // 許可された。オブジェクトを変更する場合
cart.items += 1; // 許可された
// cart = {}; // TypeError。constバインディングを再割り当てする場合

これがconstが変更する予定のオブジェクトでも適切なデフォルトである理由です。変数をポイントし直したいことはほとんどなく、constは偶然それを実行するのを停止しながら、オブジェクト自体を開いたままにします。

オブジェクトは可変です。キーへの割り当てはアップサート(作成または上書き)し、deleteはそれを削除します:

js
const user = { name: "太郎", age: 30 };

user.role = "admin"; // 追加
delete user.age; // 削除

console.log(user); // { name: "太郎", role: "admin" }

constの区別は、constが保護するものについてのものであるため、内在化するものです。constはバインディングを凍結し、値を凍結しません。名前は再割り当てできません。参照されるオブジェクトは開いたままです:

js
const cart = { total: 0 };
cart.total = 25; // 問題ありません。参照オブジェクトを変更する場合
// cart = { total: 25 }; // TypeError: Assignment to constant variable

実際にオブジェクト自体をロックしたい場合、Object.freeze(obj)はキーの追加、変更、削除を防ぎますが、浅いフリーズ(ネストされたオブジェクトは可変のままです)で、厳密でないコード内でエラーではなく静かに何もしません。実践では、ほぼ必要ありません。保持する価値のある習慣は、constがデフォルトです。バインディングが安定していることを示し、偶発的な再割り当てを実際に起こる間違いをブロックしながら、通常の変更を利用可能なままにします。

Junoオブジェクトを変更する キーに割り当てて、追加または更新し、deleteを使用して削除します。驚きはconstです。userが別のオブジェクトをポイントするのを停止しますが、保持されているオブジェクトの内部を変更することはできます。すべてをロックするのを期待するのをやめるのに時間がかかりました。
Junoオブジェクトを変更する 割り当てはキーを追加または上書きし、deleteはキーを削除します。constは名前をロックし、内容をロックしません。constオブジェクトは変更予定のオブジェクトでもconstデフォルトが問題ない理由で、変数自体は再ポイントされず、完全に編集可能なままです。
Junoオブジェクトを変更する 割り当てはキーをアップサート,deleteはキーを削除し,constはバインディングではなく値を保護するため,参照オブジェクトは可変のままです。オブジェクトをロックする必要がある場合,Object.freezeは浅くロックし,厳密でないモード外で静かに失敗します。それを達成するのはまれです;constがデフォルトで既に実際に示される再割り当ての間違いを停止します。

メソッドとthis

オブジェクト内の値は関数です。その場合、**メソッド**と呼ばれます:オブジェクトが保存する事実ではなく、オブジェクトができることです。同じドットと括弧で呼び出します:

js
const user = {
  name: "太郎",
  greet() {
    return `Hi、I am ${this.name}`;
  },
};

console.log(user.greet()); // Hi、I am 太郎

内部の新しい単語はthisです。user.greet()を呼び出すと、thisは「このメソッドが呼び出されたオブジェクト」を意味し、ここではuserです。そのため、this.nameは同じオブジェクトからnameキーを読み取ります。これは、メソッドが渡されなくても独自のオブジェクトの値に到達する方法です。

関数がオブジェクト上の値として格納される場合、それは**メソッド**です。メソッドにより、オブジェクトはデータとともに動作を実行でき、thisを通じてそのデータに到達します:

js
const cart = {
  items: ["ランプ", "机"],
  total: 65,
  summary() {
    return `${this.items.length} items,${this.total} total`;
  },
};

console.log(cart.summary()); // 2 items,65 total

ほぼすべてをカバーするthisのルール:thisはコール時にドットの左側にあるオブジェクトです。cart.summary()を呼び出し、thiscartです。this.itemsthis.totalは同じオブジェクトから読み取られます。

「コール時」というフレーズは重要です。thisはメソッドを書く時に固定されません。メソッドが呼び出される方法によって決定されます。cart.summary()として呼び出し、thiscartです。関数を引き出して単独で呼び出し、thiscartをポイントしなくなります。この辺でその端をご覧になられますが、ドットで呼び出されるメソッドの場合、thisは希望通りに動作します。

オブジェクト上に格納された関数は**メソッド**で、thisを通じてオブジェクト自身の状態にアクセスします。実際には重要なバインディングルール:thisは定義されている場所ではなく、関数が呼び出される方法によって設定されます。通常のメソッド呼び出しの場合、thisはドットの左側にあるオブジェクトです:

js
const cart = {
  total: 65,
  discount: 0.1,
  finalPrice() {
    return this.total * (1 - this.discount);
  },
};

console.log(cart.finalPrice()); // 58.5

バインディングは動的であるため、メソッドを分離するのが破損します:const fn = cart.finalPrice; fn();cartのコンテキストを失い、thisはもはや希望する場所をポイントしません。

実際的な落とし穴は、メソッドとしての矢印関数です。矢印は独自のthisを取得しません。定義されたサラウンディングスコープからthisをキャプチャします。したがって、メソッドとして使用された矢印は、外側のthis(最上位では、オブジェクトではない)を読み取ります。ではなく、それが格納されているオブジェクト:

js
const user = {
  name: "太郎",
  greet: () => `Hi、I am ${this.name}`// 間違い:`this`は`user`ではない
  greetOk() {
    return `Hi、I am ${this.name}`; // 右:メソッド短縮形
  },
};

保持するルール:メソッド短縮形(greet() {})を使用して、関数がthisがオブジェクトを意味し、矢印を予約する必要がある場合、実際に周囲のthisが必要な他のほとんどの場所で、このほとんどはコールバックです。

Junoメソッドとthis オブジェクト上に格納された関数はメソッドで、ドットと括弧で呼び出されますuser.greet()のように。内部では,thisはメソッドが呼び出されたオブジェクトを意味するため,this.nameはそのオブジェクト自身のnameを読み取ります。これは、メソッドが独自のオブジェクトの値に到達する方法です。
Junoメソッドとthis メソッドはオブジェクト上に格納された関数で,thisはそれを呼び出すときにドットの左側にあるオブジェクトです。そのため,cart.summary()thiscartを意味するようにします。キャッチは,メソッドを書く時ではなく,コール時にthisが決定されることで,メソッドをそのオブジェクトから取り出す瞬間に重要です。
Junoメソッドとthisthisは定義されている場所ではなく,関数が呼び出される方法によってバインドされるため,メソッドをそのオブジェクトから分離するとそれが失われます。thisがオブジェクトを意味する必要がある場合はメソッド短縮形を使用し、実際に周囲のthisが必要なコールバックのために矢印関数を保持します。矢印が外側のものをキャプチャするため、そのメソッドの組み合わせは古典的で、静かに失敗します。

オブジェクトと配列を一緒に

ほとんどの実際のデータは、オブジェクトのリストです。多くのユーザー、多くの製品、各オブジェクト1つのレコード。同じキーを使用します。オブジェクトを配列内に置きます:

js
const products = [
  { title: "デスクランプ", price: 40 },
  { title: "ノートブック", price: 6 },
  { title: "ペン", price: 3 },
];

console.log(products[0].title); // デスクランプ

位置で1つのオブジェクトに到達し(products[0])、次にドットでそのフィールドの1つに到達します(.title)。チェーン化され、products[0].titleは最初の製品のタイトルを読み取ります。

すべてのオブジェクトからフィールドを読み取るために、配列をループします:

js
for (const product of products) {
  console.log(product.title);
}
// デスクランプ
// ノートブック
// ペン

ループの各ターンで、productはリストから1つのオブジェクトであり、product.titleはそのタイトルを読み取ります。このシェイプ、ループするオブジェクトの配列は、ほとんどの場合、実行するデータ作業です。

オブジェクトの配列は、ほとんどの実際のデータのシェイプです。各オブジェクト1つのレコード、各共有同じキー。配列アクセスとドットアクセスを組み合わせて、任意のシングルフィールドに到達します:

js
const products = [
  { title: "デスクランプ", price: 40 },
  { title: "ノートブック", price: 6 },
  { title: "ペン", price: 3 },
];

console.log(products[1].price); // 6

これは配列であるため、配列メソッドが機能し、ここはそれらがその価値を獲得する場所です。各オブジェクトから1つのフィールドをmapで引き出し、filterで一致するレコードを保持し、reduceで1つの値にロールします:

js
const titles = products.map((product) => product.title);
console.log(titles); // ["デスクランプ", "ノートブック", "ペン"]

const total = products.reduce((sum, product) => sum + product.price, 0);
console.log(total); // 49

コールバックはイテレーションごとに1つのオブジェクトを受け取り、キーでそのフィールドを読み取ります。これが「各レコードについて、このフィールドを取得」し、「すべてのレコードでこのフィールドを合計」するようにクリックするとワンライナーになります。

オブジェクトの配列は構造化データの標準的なシェイプで、配列メソッドがそれにどのように機能するかです。各コールバックは1つのレコードを受け取ります。キーでそのフィールドを読み取り、変換、フィルタリング、または集計します:

js
const orders = [
  { id: 1, total: 40, paid: true },
  { id: 2, total: 6, paid: false },
  { id: 3, total: 3, paid: true },
];

const paidTotal = orders
  .filter((order) => order.paid)
  .reduce((sum, order) => sum + order.total, 0);

console.log(paidTotal); // 43

チェーンは上から下へパイプラインとして読み取られます。支払済みの注文を保持してから、合計を合計します。各ステップはオブジェクトの配列を取り込み、別の配列を返すため、これは完全に構成されます(または、reduceの場合、単一の値)。

データが大きくなるにつれて、念頭に置くべき1つのこと:これらのオブジェクトは参照によって保持され、下の高度なセクションは正確にします。mapまたはforEachコールバック内のオブジェクトを変更すると、コピーではなく、配列内の元のレコードが変更されます。これはたまに必要で、多くの場合驚きです。ソースに触れずに変更することを意味する場合、渡されたオブジェクトを編集するのではなく、新しいオブジェクトを構築します。

Junoオブジェクトと配列を一緒に ほとんどの実際のデータはオブジェクトの配列です。リスト内の各アイテムが同じキーを持つ1つのレコードであります。products[0]で1つに到達し、products[0].titleでフィールドに到達します。配列をループして、すべてのレコードに接するため、実行するほとんどのデータ作業の背後にあるパターンです。
Junoオブジェクトと配列を一緒に オブジェクトの配列は最も実際のデータが到着するシェイプで、配列メソッドはそのために構築されています。mapは各レコードからフィールドを引き出し、filterは一致するレコードを保持し、reduceはそれらをまたいで合計し、コールバックはターンごとに1つのオブジェクトを受け取ります。「各レコードについて、このフィールドを取得」はループになるのを停止し、ワンライナーになります。
Junoオブジェクトと配列を一緒に 配列メソッドはレコードのパイプラインにチェーンされます。フィルタリング,その後の値への削減,各ステップはキーでフィールドを読み取ります。これらのオブジェクトが参照によって保持されることを監視して、mapまたはforEachコールバック内で1つを変更するとオリジナルが編集されます。ソースに触れずに変換することを意味する場合、渡されたものを編集する代わりに新しいオブジェクトを構築します。

オブジェクトの次のステップ

オブジェクトと配列は、常に手を伸ばすための2つの構造であり、ほとんどのデータは、配列フィールドを持つオブジェクト、オブジェクトの配列、両方の組み合わせの2つのネストです。配列メソッドと組み合わせるほぼすべてのデータを、必要なシェイプに形成できます。

次のステップはオブジェクトをページで機能させることです。DOMに到達するとき、読み取りと変更をするエレメントもオブジェクトで、設定するキーと呼び出すメソッドを持つため、ここのすべてが直接実行されます。