JavaScript 再入門(その14) オブジェクト 1 概要とデータ構造

概要とデータ構造

JavaScript は、オブジェクトベース言語

JavaScript のオブジェクトを説明するのに非常に悩ましい部分があります。

PHP の連想配列や C++ のハッシュテーブル等と同じような働きをするデータ構造の側面と、PHP や C++ / JAVA のようなクラスベース言語ではなく、クラスを使用せずにオブジェクトの prototype プロパティを使ってメソッドやプロパティを継承するプロトタイプチェーンを利用した、プロトタイプに基づいたオブジェクトベース言語の側面を持っています。

JavaScript 入門であれば、データ構造だけを説明すればよいのですが、「再入門」となればそれなりに踏み込む必要がありまが、踏み込みすぎると深い沼にはまり込みます。どこまで説明するか悩ましいところです。

ES2015 以降 class キーワードが導入され、クラスベースに近いコードが許されるようになりましたが、これはシンタックスシュガー(糖衣構文:ある構文を簡略化したり可読性をよくするための記法)であり、あくまでもJavaScript はプロトタイプベース言語(厳密にはプロトタイプに基づいたオブジェクトベースの言語)に変わりありません。

class キーワードが導入されたためオブジェクトのプロトタイプについて深く知識がなくても、オブジェクト指向プログラミングはできるようになりました。しかし、テクニカルな部分の知識を持つことはプログラミングをする上で、アドバンテージとなります。オブジェクトを理解することは、JavaScript を理解する上で大きなウェイトをしめます。この記事では詳しいところまで掘り下げませんが、記事下部に MDN のオブジェクトに関する記事のリンクがありますので、一読して理解を深められることをお勧めします。

ぜひとも手を動かしてください。
例は、なるべくわかりやすいものになるように心がけていますが、実際に動かしてみると理解がより深く迅速になります。

今回この記事を書くために勉強し直しましたが、正しく理解できていない部分もあるとおもいますが、生暖かく見守ってください。

データ構造としてのオブジェクト

データ構造としてのオブジェクトは、PHP の連想配列や C++ のハッシュテーブル等のデータ構造と同じような働きをします。

キー(名前)と値のセットであるプロパティを格納するコレクションです。
「キー(名前)」は文字列であるのに対し、値は、オブジェクトや関数等どんな値(型)でも構いません。

初期化の方法は Object を使う方法と {} (オブジェクトリテラル構文)を使う方法があります。

let obj = new Object() ;
let obj2 = {} ; // オブジェクトリテラル構文

オブジェクトリテラル構文はオブジェクト全体を初期化するのにも使えます。

let person = {
	age : 10 ,
	fname : 'Ippei' ,
	lname : 'Kimura' ,
	profile : function() {
      console.log( 'name:' +  this.lname + this.fname + ' age:' +  this.age ) ;
    } ,
} ;
console.log( person ) ;
/*
{age: 10, fname: 'Ippei', lname: 'Kimura', profile: ƒ}
	age: 10
	fname: "Ippei"
	lname: "Kimura"
	profile: ƒ ()
	[[Prototype]]: Object
*/
person.profile() ; // name:KimuraIppei age:10

プロパティの追加、変更と削除。

let person = {
	age : 10 ,
	fname : 'Ippei' ,
	lname : 'Kimura' ,
	profile : function() { console.log( 'name:' +  this.lname + this.fname + ' age:' +  this.age ) ; } ,
} ;
// person オブジェクトに birth プロパティを追加
person.birth = '2000/10/1' ;
// person オブジェクトの age プロパティを 21 に変更
person.age = 21 ; 
console.log( person ) ; // {age: 21, fname: 'Ippei', lname: 'Kimura', birth: '2000/10/1', profile: ƒ}
person.profile() ; // name:KimuraIppei age:21
// person オブジェクトの age プロパティを削除
delete person.age ;
console.log( person ) ; // {fname: 'Ippei', lname: 'Kimura', birth: '2000/10/1', profile: ƒ} <- age プロパティが削除されています。

ブラケット記法によるプロパティへのアクセス

キー(名前)が以下の場合はドット記法でのプロパティへのアクセスはできないので、ブラケット記法でアクセスします。

  • 数字から始まっている。
  • ハイフンが含まれている。
  • 予約語である。
  • 変数でアクセスする。
let person = {
	age : 10 ,
	fname : 'Ippei' ,
	lname : 'Kimura' ,
	10 : 'Numeric' , // 数字から始まっている
	'1one' : 'Numeric start' , // 数字から始まっている
	'birth-day' : '2000/10/1' , // ハイフンが含まれてる
	for : 'Reserved word' , // 予約語である
	profile : function() { console.log( 'name:' +  this.lname + this.fname + ' age:' +  this.age ) ; } ,
} ;
// 数字から始まる person[10] でも可だがキーは文字列に変換されるのでリテラル付きが望ましい
console.log( person['10'] ) ; // Numeric
// 数字から始まる
console.log( person['1one'] ) ; // Numeric start
// ハイフンが含まれる
console.log( person['birth-day'] ) ; // 2000/10/1
// 予約語
console.log( person['for'] ) ; // Reserved word
// 変数でアクセス
const pty = 'age' ;
console.log( person[pty] ) ; // 10

ループ

for…in *ES2015 を使ってオブジェクトからプロパティを取り出します。

let person = {
	age : 10 ,
	fname : 'Ippei' ,
	lname : 'Kimura' ,
	profile : function() { console.log( 'name:' +  this.lname + this.fname + ' age:' +  this.age ) ; } ,
} ;
for( let k in person ) { // オブジェクトのプロパティからキーを取り出してループ
	console.log( k + ': ' + person[k] ) ; // キーを使ってプロパティへアクセス
}
/*
age: 10
fname: Ippei
lname: Kimura
profile: function() { console.log( 'name:' +  this.lname + this.fname + ' age:' +  this.age ) ; }
*/

参考リンク

MDN 開発者向けのウェブ技術 > 標準組み込みオブジェクト > Object
MDN 開発者向けのウェブ技術 > オブジェクト初期化子
MDN 開発者向けのウェブ技術 > オブジェクトでの作業
MDN 開発者向けのウェブ技術 > JavaScript「再」入門