The Good Parts 「良いパーツ」によるベストプラクティス 3章
読んだのでまとめる。
3章 オブジェクト
変数型(=オブジェクト以外) 数値 文字列 真偽値 null undefined このうち、数値、文字列、真偽値はメソッドを呼び出すことが可能 イミュータブル(=変更不可能) オブジェクト 変数型以外はすべてオブジェクト オブジェクトは名前と値で構成されるプロパティを複数含むコンテナ プロパティ名:空文字も含む、任意の文字列が使用可能 プロパティ値:undefinedを除くすべてのJavaScriptの値をセット可能 他のオブジェクトのプロパティを継承することを可能にするプロトタイプチェイン オブジェクト初期化のコストとメモリ消費量を抑えることが出来る
3.1 オブジェクトリテラル
新しいオブジェクトの生成を簡潔に記述することが可能 2つのブレースで囲まれ、名前(=プロパティ名)と値(=プロパティ値)のペアを列挙したもの 式が記述可能であれば、どこにでも記述可能 プロパティ名は、予約語ではなくJavaScriptの名前に沿っていればクォートを省略可能 プロパティ値は、任意の式を記述可能 他のオブジェクトリテラルも含むことができる したがって、オブジェクトはネストすることができる
var tyamaguc = { 'blog' : 'http://d.hatena.ne.jp/tyamaguc07/', account : { twitter : 'tyamaguc07', hatena : 'tyamaguc07' } };
3.2 値の取得
取得方法は2つ 1. プロパティ名を[] で囲んで指定 2. . を利用 ただし、プロパティ名が定数かつ、JavaScriptの名前のルールに沿っていることが条件 . を使った表現がおすすめ 存在しないメンバ(=プロパティ?)を取得しようとした場合はundefinedが返る
演算子を使うことで、デフォルト値を設定可能 |
// 値の取得 console.log( tyamaguc["blog"] ); // http://d.hatena.ne.jp/tyamaguc07/ console.log( tyamaguc.account.twitter ); // tyamaguc07 // 存在しないプロパティ console.log( tyamaguc.account.mixi ); // undefined // デフォルト値を指定 console.log( tyamaguc.account.mixi || "none" ); // none // 存在しないプロパティのプロパティを取得 // console.log( tyamaguc.account.mixi.name ); // エラーが発生する! // && 演算子で例外の発生を回避 console.log( tyamaguc.account.mixi && tyamaguc.account.mixi.name ); // undefined
3.3 値の更新
オブジェクトに指定されたプロパティ名が... 存在しない プロパティが追加される 存在する プロパティ値が更新される
// プロパティ値の追加 tyamaguc.name = 'hoge'; console.log( tyamaguc.name ); // プロパティ値の更新 tyamaguc.name = 'tyamguc'; console.log( tyamaguc.name );
3.4 参照
オブジェクトは参照渡しが行われる
var temp = tyamaguc; // tyamagucはオブジェクト、したがって参照が渡される temp.name = "hoge"; console.log( temp.name ); // hoge console.log( tyamaguc.name ); // hoge var name = temp.name; // temp.nameは変数、したがってコピーされる name = 'tyamaguc'; console.log( name ); // tyamaguc console.log( temp.name ); // hoge console.log( tyamaguc.name ); // hoge
3.5 プロトタイプ
オブジェクトはすべて、プロトタイプオブジェクトとリンクしている プロトタイプオブジェクトのプロパティを継承する オブジェクトリテラル作成したオブジェクトは、 Object.prototype オブジェクトとリンクする
// プロトタイプオブジェクト console.log( Object.prototype ); // {} console.log( typeof Object.prototype ); // object
オブジェクトを新規作成する場合、プロトタイプとするオブジェクトを選ぶ事が出来る これを、プロトタイプオブジェクトとリンクしているという? JavaScriptが用意したメカニズムは複雑で扱いづらい 簡素化することが出来る
// Object に createメソッドの追加 if ( typeof Object.create != 'function' ) { Object.create = function( obj ) { var Func = function() {}; // コンストラクタらしい? // function Func() {}; // こちらの書き方でもOK Func.prototype = obj; // 新しく作成する return new Func; }; } var new_tyamaguc = Object.create( tyamaguc );
新たに作成したオブジェクトを変更しても、リンクしているプロトタイプオブジェクトに影響はない つまり、new_tyamaguc のプロパティを変更しても、tyamaguc に影響はない
console.log( tyamaguc.name ); // hoge console.log( new_tyamaguc.name ); // hoge new_tyamaguc.name = "tyamaguc"; console.log( tyamaguc.name ); // hoge console.log( new_tyamaguc.name ); // tyamaguc
リンクしているプロトタイプオブジェクトのはどのように使われるか? オブジェクトから値を取得する際に利用される オブジェクトに指定したプロパティがない場合、 リンクしているプロトタイプオブジェクトのプロパティ値を取得しようとする そのプロトタイプオブジェクトにもプロパティがない場合、 それがリンクしているプロトタイプオブジェクトを参照しようとする 最終的に、Object.prototype にプロパティがないか確認される それでも、プロパティがない場合 undefined が返される プロトタイプのリンクは動的 プロトタイプオブジェクトにプロパティを追加すると、 それをリンクしているオブジェクトは、追加されたプロパティにアクセスできるようになる この仕組をプロトタイプチェーンと呼ぶ 詳しくは6章で。
console.log( tyamaguc.nickname ); // undefined console.log( new_tyamaguc.nickname ); // undefined tyamaguc.nickname = 'ちゃまぐ'; console.log( tyamaguc.nickname ); // ちゃまぐ console.log( new_tyamaguc.nickname ); // ちゃまぐ
3.6 リフレクション
リフレクション? プログラムの実行過程でプログラム自身の構造を読み取ったり書き換えたりする技術のこと オブジェクトの中身を調べる方法 typeof演算子を使い、プロパティの変数型をチェック プロトタイプチェーン上に存在するプロパティに対しても利用出来る プロトタイプチェーンをさかのぼりたくない場合は、hasOwnPropertyメソッドを使う
tyamaguc.birthday = '2011/01/01'; console.log( typeof tyamaguc.birthday ); // string console.log( typeof new_tyamaguc.birthday ); // string console.log( tyamaguc.hasOwnProperty('birthday') ); // true console.log( new_tyamaguc.hasOwnProperty('birthday') ); // false
3.7 プロパティの列挙
for in文を使用すると、オブジェクト内に存在するプロパティ名を順に取り出すことが出来る プロトタイプチェーン上のプロパティも対象になる 取得されるプロパティ名は順番が保証されない
var name; for ( name in new_tyamaguc ) { console.log( name + " : " + new_tyamaguc[name] ); }
3.8 プロパティの削除
オブジェクトからプロパティを削除するときは、delete演算子を使う プロトタイプチェーン上のプロパティは削除できない
delete new_tyamaguc.birthday; // プロトタイプチェーン上のプロパティなので削除されない console.log( new_tyamaguc.birthday ); // 2011/01/01 new_tyamaguc.birthday = '2000年1月1日'; console.log( new_tyamaguc.birthday ); // 2000年1月1日 delete new_tyamaguc.birthday; console.log( new_tyamaguc.birthday ); // 2011/01/01
3.9 グローバル領域の利用を減らす
グローバル変数を定義するのは簡単 だが、使うべきではない グローバル変数を最低限にする方法 アプリケーション用のグローバル変数を1つだけ定義する 他のアプリケーションなどに悪影響を及ぼす可能性が劇的に減る プログラムも読みやすくなる もうひとつの方法はクロージャ 詳しくは、次の章
var MyApp = {}; // アプリケーション用のグローバル変数定義 // この変数をアプリケーション用のコンテナとして利用する MyApp.tyamaguc = { 'blog' : 'http://d.hatena.ne.jp/tyamaguc07/', account : { twitter : 'tyamaguc07', hatena : 'tyamaguc07' } }
感想
文言の統一がされてないのが気になった。
同じ節の中で、名前とプロパティ名が同じ意味で使われていたり…。
理解は出来るんだけどね!
あと、自分のレベルでこの本を読むのは少し辛い模様。
プロトタイプ周りの処理は、何を意味するのか分からずに調べることになった。
この本はサイ本読んだ後に読んだほうがいいのかなって気がしてます。