概要
...【JavaScript】オブジェクト①の続きです。
JavaScriptを学習、理解を深めるため「JavaScript Primer 迷わないための入門書」を読み、
理解した内容等を記載していく。
「【JavaScript】JavaScript入門一覧」に他の記事をまとめています。
この記事で理解できること
- オブジェクトのプロパティの追加方法
プロパティの追加
- オブジェクトは、プロパティの追加など
オブジェクト作成後も値を変更できる。
- オブジェクトに指定したプロパティが存在しない場合、
自動的にプロパティが作成される。
-
ドット記法
、ブラケット記法
のどちらでも追加可能。 - 追加時にプロパティ名(キー)を
変数
、変数の命名規則には適合しない文字列
、Symbol
を指定する際は、ブラケット記法を使用する。
// 空のオブジェクト「obj」を作成
const obj = {};
// nameプロパティをドット記法で追加して値を代入
obj.name = "Taro"; // 自動的にnameプロパティが作成される
// 変数「key」に変数の命名規則には適合しないプロパティ名「e-mail」を代入
const key = "e-mail";
obj[key] = "sample@mail.com"; // 変数「key」に代入したe-mailプロパティが作成、および指定した値が設定される
// Symbolのプロパティを追加
obj[Symbol("hobby")] = "baseball";
console.log(obj); // => {name: 'Taro', e-mail: 'sample@mail.com', Symbol(hobby): 'baseball'}
【Tips】Computed property names
- ブラケット記法を用いたプロパティの定義は、オブジェクトリテラル
{ }
内でも可能。 - その際、プロパティ名は
「Computed property names」
と呼ばれる。 - 「Computed property names」は
ES2015から導入された記法
object.js
// 変数「key」に変数の命名規則には適合しないプロパティ名「e-mail」を代入
const key = "e-mail";
// 空のオブジェクト「obj」を作成
const obj = {
[key]: "sample@mail.com" // => 変数「key」が評価されプロパティ名「e-mail」の設定、および値が設定される
};
// 変数「key」をブラケット記法で指定
console.log(obj[key]); // => sample@mail.com
注意点
- 冒頭で記載した通り、JavaScriptのオブジェクトは
オブジェクト作成後にプロパティを変更可能
という特性を持つ。 - オブジェクトの作成時以外でプロパティを追加すると、
オブジェクトがどんなプロパティを持っているか不明確
になりやすい。 - できる限りオブジェクト作成後に新しいプロパティは追加せず、
オブジェクトの作成時のオブジェクトリテラルの中でプロパティを定義する
ことが推奨されている。
プロパティの削除
- オブジェクトのプロパティを削除する場合は、
delete演算子
を使用する。 - ドット記法の場合
delete オブジェクト.プロパティ名;
で削除可能。 - ブラケット記法の場合
delete オブジェクト[プロパティ名];
で削除可能。
object.js
// 3つのプロパティを持つ、オブジェクト「obj」を作成
const obj = {
"name": "Taro",
"age": 24,
"e_mail": "main@mail.com",
};
// オブジェクト「obj」からプロパティ「age」を削除
delete obj.age;
// オブジェクト「obj」からプロパティ「e_mail」を削除
delete obj["e_mail"];
console.log(obj); // => {name: 'Taro'}
プロパティの存在を確認する
JavaScriptでは、存在しないプロパティにアクセスした場合、例外
ではなくundefined
を返す。
あるオブジェクトがあるプロパティを持っているかを確認する方法として、次の3つがある。
- undefinedとの比較
- in演算子
- hasOwnPropertyメソッド
undefinedとの比較
- 存在しないプロパティにアクセスした場合
undefined
が返されるため、プロパティにアクセスすると存在を確認できる。 - しかし、プロパティの値が
undefined
だった場合、区別が難しくなる。 - そのため、プロパティが存在するかの判定には
in演算子
かhasOwnPropertyメソッド
を使用する。
object.js
// オブジェクト「obj」を作成
const obj = {
"name": "Taro",
"age": undefined
};
// 事前に確認してみる
console.log(obj.name); // => Taro
console.log(obj.age); // => undefined(値がundefined)
console.log(obj.not); // => undefined(存在しないプロパティを指定した場合の挙動)
// オブジェクト「obj」にプロパティ「name」が存在するか確認
if (obj.name !== undefined) {
// undefinedじゃなければconsole.logが実行される
console.log("undefinedではない"); // => undefinedではない
}
// オブジェクト「obj」にプロパティ「age」が存在するか確認
if (obj.age !== undefined) {
// undefinedじゃなければconsole.logが実行される
console.log("undefinedではない");
}
// => プロパティageが存在しているが何も表示されない = プロパティの値がundefinedのためif文内の処理が実行されていない
in演算子
-
"プロパティ名" in オブジェクト;
で指定したオブジェクトにプロパティが存在するかを判定できる。 - in演算子は
プロパティの値は関係なく、プロパティが存在するか
の判定を行う。 -
ture
もしくはfalse
が返される。
object.js
// オブジェクト「obj」を作成
const obj = {
"name": "Taro",
"age": undefined
};
// "プロパティ名" in オブジェクト;でプロパティが存在するかを判定
console.log("name" in obj); // => true
console.log("age" in obj); // => 値はundefinedだがプロパティが存在するためtrue
console.log("city" in obj); // => プロパティが存在しないためfalse
hasOwnPropertyメソッド
-
オブジェクト.hasOwnProperty("プロパティ名");
でプロパティが存在するかを判定できる。 - hasOwnPropertyメソッドの引数には、
存在を判定したいプロパティ名を指定する。
- hasOwnPropertyメソッドも
プロパティの値は関係なく、プロパティが存在するか
の判定を行う。 -
ture
もしくはfalse
が返される。
object.js
// オブジェクト「obj」を作成
const obj = {
"name": "Taro",
"age": undefined
};
// オブジェクト.hasOwnProperty("プロパティ名");でプロパティが存在するかを判定
console.log(obj.hasOwnProperty("name")); // => true
console.log(obj.hasOwnProperty("age")); // => 値はundefinedだがプロパティが存在するためtrue
console.log(obj.hasOwnProperty("city")); // => プロパティが存在しないためfalse
【Tips】Optional chaining演算子(?.)
- ES2020では
Optional chaining演算子(?.)
が導入された。 -
ネストしたプロパティの存在確認
とアクセス
を簡単に行えるのが特徴。 - (プロパティを持つオブジェクトの場合)
オブジェクト?.プロパティ名
と指定しアクセスする。 - 左辺のアクセス対象が
null
またはundefined
の場合は、それ以上評価せずundefined
を返す。 - プロパティが存在する場合は、
プロパティの評価結果
を返す。
object.js
// オブジェクト「obj」を作成
const obj = {
"team_a": {
"name": "Taro",
"age": undefined,
"e_mail": "main@mail.com"
}
};
// ドット記法やブラケット記法の場合、ネストしたプロパティのいずれかが「undefined」の場合、例外が発生してしまう
console.log(obj.team_b.name); // => Uncaught TypeError: Cannot read properties of undefined (reading 'name')
console.log(obj["team_b"]["name"]); // => Uncaught TypeError: Cannot read properties of undefined (reading 'name')
// オブジェクト.hasOwnProperty("プロパティ名");でプロパティが存在するかを判定
console.log(obj?.team_a?.name); // => Taro
console.log(obj?.team_a?.age); // => undefined
console.log(obj?.team_a?.["e_mail"]); // => main @mail.com(ブラケット記法との組み合わせも可能)
console.log(obj?.team_b?.name); // => 例外の発生、「team_b」以降の評価はされず「team_b」の評価結果「undefined」が返される
toStringメソッド
- toStringメソッドは
オブジェクト自身を文字列化するメソッド。
-
Stringコンストラクタ関数
でこのtoStringメソッドが呼び出されている。 -
オブジェクト.toString();
でオブジェクトを文字列化可能。
object.js
// オブジェクト「obj」を作成
const obj = {
"team_a": {
"name": "Taro",
"age": undefined,
"e_mail": "main@mail.com"
}
};
// オブジェクト「obj」をtoStringメソッドで文字列化する
console.log(obj.toString()); // => オブジェクトを文字列化すると[object Object]という文字列になる
オブジェクトの静的メソッド(スタティックメソッド)
- オブジェクトの静的メソッドとは、
インスタンスの元となる「Object」そのものから呼び出せるメソッド
のことである -
オブジェクトの列挙やマージ
などオブジェクトを操作する静的メソッドが存在する。
オブジェクトの列挙
オブジェクトのプロパティを列挙する3つの以下の静的メソッドが存在する。
- Object.keysメソッド(オブジェクトのプロパティ名を配列で返す)
- Object.valuesメソッド(オブジェクトの値を配列で返す) ※ES2017から
- Object.entriesメソッド(オブジェクトのプロパティ名と値の配列を返す) ※ES2017から
object.js
// オブジェクト「obj」を作成
const obj = {
"name": "Taro",
"age": undefined,
"e_mail": "main@mail.com"
};
// Object.keys(オブジェクト);でプロパティ名を配列で返す
console.log(Object.keys(obj)); // => (3) ['name', 'age', 'e_mail']
// Object.values(オブジェクト);でオブジェクトの値を配列で返す
console.log(Object.values(obj)); // => (3) ['Taro', undefined, 'main@mail.com']
// Object.entries(オブジェクト);でオブジェクトのプロパティ名と値の配列を返す
console.log(Object.entries(obj)); // => [Array(2), Array(2), Array(2)]
// 0: (2)['name', 'Taro']
// 1: (2) ['age', undefined]
// 2: (2) ['e_mail', 'main@mail.com'] ...
オブジェクトのマージと複製
-
Object.assgin
メソッドは、あるオブジェクトを別のオブジェクトに代入する
ことが可能。 - オブジェクトの
複製やマージ
を行うことが可能。 - 既存のオブジェクトには影響を与えずマージしたオブジェクトを作ることができるため、
第一引数(上記ではコピー先オブジェクト)には空のオブジェクトを指定すること
が典型的な方法とされている。 - プロパティ名が重複した場合は、
後ろのオブジェクトのプロパティにより上書きされる
ことに注意。 - ES2015から使用可能。
object.js
// オブジェクト「returnObj」を作成
const returnObj = {};
const objA = {
"name": "Hanako",
"age": 22,
"e_mail": "main@mail.com"
};
const objB = {
"name": "Eita",
"age": 28
};
// 結果的にobjAを複製した形でオブジェクト「returnObj」が返される
console.log(Object.assign(returnObj, objA)); // => {name: 'Hanako', age: 22, e_mail: 'main@mail.com'}
// objAとobjBではプロパティ「name」と「age」が重複しているためobjAのプロパティの値が上書きされている
console.log(Object.assign(returnObj, objA, objB)); // => {name: 'Eita', age: 28, e_mail: 'main@mail.com'}
【Tips】オブジェクトのspread構文(...)
- ES2018から
オブジェクトのspread構文(...)
が追加された。 - ES2015で
配列の要素を展開するspread構文
はサポートされていたが、オブジェクトに対してはES2018
からサポートされた。 - 新たにオブジェクトを作成する
オブジェクトリテラル({ })
の中に指定し、使用する。 - プロパティ名が重複した場合は、
後ろのオブジェクトのプロパティにより上書きされる
ことに注意。
object.js
const objA = {
"name": "Hanako",
"age": 22,
"e_mail": "main@mail.com"
};
const objB = {
"name": "Eita",
"age": 28
};
// spread構文でマージするオブジェクトを指定
const returnObj = {
...objA,
...objB
};
// マージしたオブジェクトを確認してみる
console.log(returnObj); // => {name: 'Eita', age: 28, e_mail: 'main@mail.com'}