本日はJavaScriptオブジェクトの作成・追加・削除・アクセス・プロパティとメソッドおよびそれらの操作について理解していきましょう。
Array(配列)オブジェクトの基礎は下記で解説しております。
JavaScriptには8つのデータ型があります。それらのうちの7つは、プリミティブと呼ばれます。
対照的に、JavaScriptオブジェクトは、さまざまなデータやより複雑なキー付きコレクションを格納する、非プリミティブデータ型です。
配列や関数でさえ、内部ではオブジェクトです。
JavaScriptでは、操作する最も重要なデータの1つはオブジェクトでもあります。
JavaScriptでは、オブジェクトは3つの方法で作成できます。
・ オブジェクトリテラル(初期構文の使用)
・ newキーワードの演算子を使用したオブジェクトの作成
・オブジェクトコンストラクタを使用して、JavaScriptオブジェクトを初期化することもできます。
本日では初期構文のオブジェクトリテラル構文を使用したオブジェクト作成を解説していきます。
JavaScript オブジェクト宣言
オブジェクトを宣言するための構文は下記となります。
const my_obj = { key1: "value1", key2: "value2" }
上記では、『my_obj』として定義されています。
let user = { name: "Taro", age: 30 }
オブジェクトは波括弧{}で作成でき、オブジェクトは変数となります。
つまり上記であれば、オブジェクトはuser変数に格納されています。
オブジェクトは変数ですが、多くの値を含める事が可能です。
プロパティは『キー:値』のペアであり、keyは文字列(プロパティ名とも呼ばれる)であり、任意のvalueである値にすることができます。
つまり、オブジェクトの各それぞれはkeyであり、複数ある場合はカンマ( , )で区切られ、波括弧で囲まれた値{}のペアとなります。
また1行としてオブジェクトを定義可能です。
const person = {name: 'Taro', age: 30}; console.log(typeof person); //object
nameとageはキーであり、Taroと30は値となります。
先述した通り、『キー:値』のペアはプロパティと呼ばれます。
コロン記号( : )はキーと値のペア間の区切り文字として使用しています。
オブジェクトの全てのデータはkeyによってファイルに保存されます。
また、プロパティのキーは下記のいずれかになります。
・ String(文字列)型
・ Symbol(シンボル)型
この2つがオブジェクトプロパティのキーとして機能します。
Symbol()はES6で新しく追加された、プリミティブデータ型で特殊なデータ型でもある関数です。
学習の際はRubyや他の言語と違いJavaScriptシンボルは異なりますので気をつけて下さい。
これらを踏まえて、名前でファイルを検索したり、ファイルを追加や削除そして値にアクセスしたりするのは比較的簡単となっています。
プロパティの属性
データを格納するための、オブジェクトプロパティは名前(key)と値のペアだけではありません。
3つの属性もあります
・ 構成可能な属性
この属性はプロパティを削除したり追加または変更可能かどうかを指定します。
・ 列挙可能
プロパティをfor…inループで返すことができるかどうかを指定します、後に解説します。
・ 書き込み可能
プロパティを変更できるかどうかを指定します。
これらの属性は、プロパティへのアクセス方法を定義します。
つまり、すべての属性を読み取ることができますが、変更できるのはプロパティが書き込み可能である場合のみであり、またvalue属性のみとなります。
プロパティ属性は、一般的に属性とプロパティはどちらも同じです。
これら3つの属性はすべてがデフォルトで有効となっています。
各データのプロパティには3つの属性があることに注意しておいて下さい。
混同してしまうかもしれませんが、オブジェクトにも3つの属性があります、プロトタイプ、クラス、拡張可能の3つです。
これはプロパティの属性とは別のオブジェクト属性となります。
ここでは、オブジェクトとプロパティにはそれぞれ異なった複数の属性があると思っておいて下さい。
また別途記事に致します。
オブジェクトプロパティの操作
値にアクセス
プロパティの値には、ドット表記を使用してアクセスできます。
const person = { name: 'Taro', age: 30 }; console.log( person.name ); // Taro console.log( person.age ); // 30
オブジェクトが格納されているperson変数にドット( . )表記で繋げてアクセスしたいキーを指定し記述します。
角括弧[ ]表記を使用してアクセスする場合は下記となります。
console.log(person["name"]);
角括弧の場合、キーをシングルまたはダブルクォートで囲って下さい。
また角括弧表記では、変数でプロパティ名の全部または一部を指定できるため、ドット表記よりも表現力があります。
さらにプロパティ名にドット表記で禁止されている文字を含めることもできるので使い勝手が良いです。
角括弧の変数は後ほど解説します。
プロパティの追加
オブジェクトに新しいプロパティを追加するには、2つの方法がございます。
それは先述したアクセスする際と同様に、ドット表記または角括弧のどちらかになります。
const person = { name: 'Taro', age: 30 }; person.public = true; console.log(person); /* { name: "Taro", age: 30, public: true //追加 */ } //または角括弧 person["public"] = true;
値は任意の型にすることができます、上記ではブール値のtrueとなっております。
角括弧を使用した利点で、プロパティ名は文字列と連結して作成できます。
const person = { name: 'Taro', age: 30 }; person["public" + "_status"] = true; console.log(person["public_status"]); //true
変数として格納してから、文字列と変数の連結も可能です。
上記と同じ出力となります。
const person = { name: 'Taro', age: 30 }; let x = "public"; person[x + "_status"] = true; console.log(person);
プロパティの削除
プロパティを削除するには、delete演算子を使用できます。
delete person.age //または角括弧 delete person["age"] console.log(person);
delete演算子は指定したプロパティをオブジェクトから取り除き、削除に成功した場合はブール値である 『true 』を返し、そうでなければ 『false 』を返します。
プロパティの削除方法はdelete演算子以外でも様々ございますのでお試し下さい。
マルチワードプロパティ名
マルチワードプロパティ名を使用することもできますが、引用符で囲む必要があります。
const person = { name: 'Taro', age: 30, "public status": true //引用符で囲む }; console.log(person);
そしてマルチワードの場合は欠点があります。
マルチワードプロパティの場合、ドット表記は機能しませんのでご注意下さい。
構文エラー(SyntaxError)をスローします。
person.public status = true //SyntaxError
ドット表記では、キーが有効な識別子である必要があるためです、スペースが含まれていないか、先頭が数字で始まっていないか、特殊文字が含まれていないかこれらに当てはまるとエラーとなります。
ですが角括弧表記であれば機能します。
person["public status"] = true console.log(person);
なぜ角括弧では機能するのかは、先述でも学んだように角括弧は文字列リテラルだけでなく変数も指定できます、ですので任意の式の結果としてプロパティ名を取得する方法を提供してくれています。
計算されたプロパティ名
計算されたプロパティとは、ECMAScript 2015(ES6)にこの機能を導入することによって、リテラル表記のJavaScriptオブジェクトプロパティの値がどのように設定されているかを動的に計算できるようになり、JavaScriptオブジェクト構造の柔軟性が向上致します。
オブジェクトを作成する際に、オブジェクトリテラルで角括弧を使用可能です。
let setKey = prompt("プロパティを追加しますか?", "public_status"); let myObj = { [setKey]: true, }; console.log( myObj.public_status ); // true console.log(myObj); /* { "public_status": true; } */
これは、計算されたプロパティ名と呼ばれます。
計算されたプロパティは複雑な事ではありません。
上記ではポップアップが表示され、OKをクリックするとプロパティ名はpublic_statusに変更され追加されます。
では別の例でも見てましょう。
const key = 'name'; const value = 'Taro'; const user = { [key]: value }; console.log(user.name); // Taro
プロパティ名の『key』はuser変数の値から派生します。
ログでnameにアクセスすると、『key』はプロパティの値を評価して返します。
計算されたプロパティの値を計算するということは、値を計算してから返すことを意味します。
プロパティ名を宣言するためにオブジェクト内に角かっこ []を挿入すると呼び出されます。
下記にまた別の例も示しておきます。
const propertyName = 'firstName'; let myObject = { [propertyName] : 'Taro', lastName: 'Tanaka' } console.log(myObject); /* { firstNam: 'Taro', lastName: 'Tanaka' } */
見栄えよく、見やすく書く場合は下記のようにお勧めします。
上記と変わらず同じように機能します。
const propertyName = 'firstName'; let myObject = {} myObject[propertyName] = 'Taro' // 角括弧表記 myObject.lastName = 'Tanaka' //ドット表記 console.log(myObject)
また、角括弧内で複雑な式も可能となっています。
let country = "country_"; let obj = { [ country + "name"]: 'Japan', [ country + "capital"]: "Tokyo", [ country + "code"]: 81 }; console.log(obj); /* { country_name: 'Japan', country_capital: "Tokyo", country_code: 81 } */
プロパティ名の式として、テンプレートリテラルを使用したい場合は下記のようにします。
const user = { [`${key}`]: value };
特定の名前に応じてプロパティ名を作成する必要がある場合など、より複雑なオブジェクトに実装できます。
角括弧表記は、ドット表記よりも非常に強力でこれらは、任意のプロパティ名と変数を許可します。
ですが、ほとんどの場合ではプロパティ名が単純な際はドット表記が一般的です。
ですので複雑なものが必要の場合に角括弧を使用し、そうでない場合はドット表記と上手く切り替えて活用下さい。
プロパティの値を省略
実際のコードでは、プロパティ名の値として既存の変数を使用することが多々あります。
const name = "Taro"; const obj = { name, age: 30 }; console.log(obj); /* { name: "Taro", age: 30 } */
nameというプロパティ名でnameの変数を値に設定しています。
同じオブジェクトで通常のプロパティと省略形の両方を使用できるという事になります。
プロパティ名の制限
すでにご存知かも知れませんが、変数を定義する際に予約語を使用し名前を付ける事はできません。
ですが、オブジェクトのプロパティの場合ではその制限はございません。
let obj = { for: 1, let: 2, const: 3, return: 4 }; console.log(obj);
これらは、任意の文字列や記号にすることができます、その他の型はJSによって自動的に文字列へと変換されます。
constで定義されたオブジェクトは変更可能
constで宣言したオブジェクトのプロパティはエラーなく変更できます。
const myObj = { key: "value" }; myObj.key = "Hello!!"; console.log(myObj.key); //Hello!!
JavaScriptのconstは変数への再代入を防ぐ為の定数です。
なので、変数の再代入は防げますが、変数に代入された値であるオブジェクトの変更は防げませんので注意して下さい。
const myObj = { key: "value" }; myObj = {}; // SyntaxError
プロパティの存在を確認
JavaScriptオブジェクトの機能は、他の言語と比較して任意のプロパティにアクセスが可能という事です。
プロパティが存在しなくてもエラーが発生する事はありません。
存在しないプロパティを読み取ると、undefined(未定義)が返されます。
const obj = {}; //プロパティが存在しない console.log(obj.notFound); // undefined
上記のようにJavaScriptでは存在しないプロパティへアクセスした場合に例外が発生しません。
プロパティ名を間違えた場合に単にundefinedという値を返すため、間違いに気づきにくいという問題があります。
なので、プロパティが存在するかどうかを簡単にテストができます。
const obj = { key: "value" }; console.log(obj.key !== undefined) //true
下記はif文でテストした場合です。
const obj = { key: "value" }; if (obj.key !== undefined) { console.log(" 'key'プロパティの値は'undefined'ではありません"); }
下記では、オブジェクトのプロパティが存在しないのでtrueとなります。
let obj = {}; console.log( obj.key === undefined ); //true
ネストされたオブジェクト
オブジェクトには、別のオブジェクトを含めることもできます。
let user = { name: "Taro" , age: 30, user2: { name: "Hanako", age: 20 } }; console.log(user.user2); console.log(user.user2.name); // Hanako
上記では、オブジェクト『user』のプロパティに『user2』オブジェクト値が含まれています。
このネストされたオブジェクトは、別のオブジェクトの内部にあるオブジェクトとなります。
JavaScriptのES6ではネストされたオブジェクトを、計算されたプロパティ名で動的に作成したりもします。
オブジェクトメソッド
JavaScriptでは、オブジェクトに関数を含めることもできます。
JavaScriptメソッドは、関数宣言を含むプロパティです。
つまり値が関数の場合は、プロパティはメソッドになります。
const user = { name: 'Taro', age: 30, greeting: function() { console.log('Hello') } } user.greeting();// Hello
上記では、greetingをキーの値として、関数が使用されています。
メソッドを呼び出す際は、user.greeting()で呼び出します。
メソッドの省略形
ES6は、オブジェクトのメソッドを定義できる簡潔なメソッド構文を提供しています。
const user = { name: 'Taro', age: 30, greeting() { console.log('Hello') } } user.greeting();// Hello
また、関数式(無名関数)を使用して関数を定義してから、それをオブジェクトのプロパティに割り当て(代入)も可能です。
let user = { name: 'Taro', age: 30 }; user.greeting = function () { console.log('Hello'); } user.greeting();//Hello
上記は前述した書き方と同じように機能します。
参照によるコピー
プリミティブを介した、オブジェクトの主な違いの1つは、参照によって格納およびコピーできることになります。
オブジェクトに割り当てられた変数は、オブジェクト自体ではなく、その『メモリ内のアドレス』つまりオブジェクトへの『参照』を格納します。
プリミティブ値である(文字列、数値、ブール値)を値全体として割り当てまたはコピー可能です。
let user = { name: "Taro" }; let copyName = user; // 参照元をコピー copyName.name = "Hanako"; console.log(copyName.name); //Hanako console.log(user.name); // Hanako
2つの変数があり、それぞれが同じオブジェクトへの参照を格納しています。
つまり、2つとして機能している事になります。
オブジェクト変数をコピーするときはいつでも、参照を複製します、ですがオブジェクトそのものはコピーされません。あくまでも値の全体だけです。
オブジェクトのループ
JavaScriptオブジェクトをループするために使用できるさまざまなメソッドは下記のとおりです。
・ for...inループの使用
・ Object.keysメソッド
・ Object.valuesメソッド
・ Object.entries メソッド
まず、JavaScriptでオブジェクトと見なされる配列がある場合、map()、forEach()、またはfor..ofループを使用して配列をループすることはできません、エラーが発生します。
オブジェクトのプロパティをループする最も簡単な方法は、for...inを使用することです。
この方法は、『Internet Explorer 6 』以降を含むすべての最新および古いブラウザで機能します。
for...inループを使用してオブジェクトを反復処理する例を次に示します。
const user = { name: 'Taro', email: 'sample@example.com', age: 30, public: true }; for (const key in user) { console.log(`${key}: ${user[key]}`); }
JavaScriptのオブジェクトはプロトタイプからプロパティを継承できるため、for…inを使用するとプロトタイプチェーン内のプロパティもループします。
回避方法はございます。
hasOwnProperty()メソッドを使用し、プロパティがオブジェクトに属しているかどうかを明示的に確認する必要があります。
for (const key in user) { if (user.hasOwnProperty(key)) { console.log(`${key}: ${user[key]}`); } }
Object.keys()メソッド
ES6より以前では、オブジェクトをループする唯一の方法は、for...inループを使用することでした。
Object.keys()メソッドは、オブジェクトのループを簡単にするためにES6で導入されたものです。
下記に例を示します。
const user = { name: 'Taro', email: 'sample@example.com', age: 30, public: true }; const keys = Object.keys(user); console.log(keys); keys.forEach((key, index) => { console.log(`${key}: ${user[key]}`); });
ループするオブジェクトを引数として取り、すべてのプロパティ名(またはキー)を含む配列を返します。
その後、forEach()などの任意の配列ループメソッドを使用して、配列を反復処理し、各プロパティの値を取得が可能です。
Object.values()メソッド
Object.values()メソッドはES8で導入されました。
Object.keys()とはまったく逆に機能します。
オブジェクト内のすべてのプロパティの値を確認可能で配列として返しその後、いずれかの配列ループメソッドを使用して、values配列をループできます。
const user = { name: 'Taro', email: 'sample@example.com', age: 30, public: true }; Object.values(user).forEach(val => console.log(val));
オブジェクトを受け取り、その列挙可能なプロパティを配列で返しています。
値は、オブジェクトを手動でループし配列にプッシュするかのように並べ替える事も可能です。
Object.entries() メソッド
ES8の他のメソッドでもある、Object.entries()を使用して配列をトラバースできます。
Object.entries()は配列の配列を出力し、各内部配列には 2つの要素があります。
最初の要素はプロパティで、2番目の要素は値となります。
const user = { name: 'Taro', email: 'sample@example.com', age: 30, public: true }; const getObj = Object.entries(user); console.log(getObj);
この関数は、列挙可能なプロパティ([キー、値]のペア)が返されるオブジェクトを受け取ります。
それらのプロパティを含む配列を返します
Object.entries()によって返された配列をループするには、下記のようにfor...ofループまたはforEach()メソッドを使用可能となります。
// forEach() loop Object.entries(user).forEach(([key, value]) => { console.log(`${key}: ${value}`) }); // for...of loop for (const [key, value] of Object.entries(user)) { console.log(`${key}: ${value}`); }
古いブラウザを使用している場合は、for...inが適切なオプションですが、それ以外の場合は、上記で解説した最新の方法のいずれかを使用するのを推奨します。
まとめ
オブジェクトは、いくつかの特別な機能を備えた連想配列となってます。
それらは、プロパティ(キーと値のペア)を格納します 。
プロパティのキーは文字列または記号である必要性があり、値は任意の型でも構いません。
プロパティのアクセスはドット表記または角括弧を使用すると変数からキーを取得可能です。
プロパティの削除はdelete演算子または他の方法を活用します。
JavaScriptオブジェクトでは関数を含める事ができ、値が関数の場合は、プロパティはメソッドとなります。
constで宣言したオブジェクトのプロパティの値は変更が可能ですが、変数として代入されたオブジェクトは変更はできません。
プロパティの存在を確認したい場合は、『 in 』演算子を使用し、("key" in obj)のようにします。
オブジェクトを反復処理(ループ)する際は、主に4つの方法があります。
JavaScriptでは柔軟性を拡張する、さまざまな種類の組み込みオブジェクトがございます。
ArrayやData…などなど、それらはまた別途学習していく必要があります。
JavaScriptオブジェクトは、コードの編成と再利用を容易にする基本的なJavaScriptの概念です。
オブジェクトとプロパティを作成する際の柔軟性によって、他のプログラミング言語にはないオプションが提供されております。
本日は以上となります。
最後までこの記事を読んで頂きありがとうございます。