JavaScriptパターン第3章ノート
JavaScriptパターン ―優れたアプリケーションのための作法
- 作者: Stoyan Stefanov,豊福剛
- 出版社/メーカー: オライリージャパン
- 発売日: 2011/02/16
- メディア: 大型本
- 購入: 22人 クリック: 907回
- この商品を含むブログ (76件) を見る
コンストラクタよりリテラルの方が良い・・・が一貫したこの章のテーマです。
オブジェクトリテラル記法
キーと値の組みをカンマで区切り、波括弧で囲う記法でオブジェクトを定義できる。
数値、文字、関数、正規表現、配列、別のオブジェクト を含めることができる。
コンストラクタを使う方法は冗長なのでオブジェクトの宣言はなるべくオブジェクトリテラルで行うべき
var obj1 = { sample_string:"normal val",// string literal sample_number:5, //number literal sample_function:function(){ console.log("this is test function"); }, //function literal sample_regexp:/normal/gi, //regure expression literal sample_array:[1,1,9], // array literal obj2:{ sample_string:"this is nested object" } } //実験 console.log(obj1.sample_number + 15);//20 console.log(obj1.sample_regexp.test(obj1.sample_string));//true console.log(obj1.sample_array.find((num)=> {return num > 8}));//9 console.log(obj1.obj2.sample_string);//this is nested object var val1= obj1.sample_function; val1();//this is test function console.log(obj1);//{sample_string: "normal val", sample_number: 5, sample_regexp: /normal/gi, sample_array: Array(3), sample_function: ƒ, …}
カスタムコンストラクタ関数
Javascriptにはクラスがないので、クラスをインスタンスするためのコンストラクタ、というより、Objectを作成する関数という扱いなのか?そこがちょっとよくわからなかった。
var Person = function (name) { this.name = name; this.say = function () { return "I am " + this.name; }; }; val John = new Person("john"); John.say();// I am John
コンストラクタにnewをつけ忘れると
コンストラクタは只の関数なので、newをつけずとも呼べてしまうが、その場合コンストラクタ内部でのthisはグローバルオブジェクト(window)を指してしまう
//※上記のPersonカスタムコンストラクタ関数を流用しています var ken = Person("ken"); ken.say();//Uncaught TypeError: Cannot read property 'say' of undefined console.log(ken)//undefined window.say();//I am ken say();//I am ken
初期化中のオブジェクトにプロパティを追加していると思いきや、グローバル変数を作ってるという事態になりかねない。対策としては
- strictモード
- コンストラクタ内で別のオブジェクトリテラルを返す
- コンストラクタ内でthisを使わない
- thisの型を検査し、適切に自オブジェクトをnew付きで呼び出す(自己呼び出しコンストラクタ)
のどれかが対策としては推奨される
配列リテラル記法
配列も組み込みコンストラクタではなくリテラルを使うべき。理由は数値型を単発で与えた時の挙動が特殊なため
var arr1 = new Array(3); //空の、長さ3の配列を作成 var arr2 = [3];//要素が 3 一つの配列を作成 arr1//[empty x 3] arr2//[3] var arr3 = new Array(3.14);//長さに小数点は採用できない・・・(エラー) //Uncaught RangeError: Invalid array length
JSON
JSONでは関数や正規表現リテラルは使えないが、配列と文字だけを扱うならオブジェクトリテラルとして解釈可能。
JSONってweb apiとかで帰ってくる値でよく見る気がするが、そのままオブジェクトリテラルとして解釈できるのに驚いた。
例:WEB APIから住所を取得
最寄駅を取得可能なハートレイルズ様のAPIを利用しました。郵便番号はGoogle日本法人のオフィス(〒106-6126)にしました。
http://geoapi.heartrails.com/api/json?method=getStations&postal=1066126
{"response":{"station":[{"name":"\u516d\u672c\u6728","kana":"\u308d\u3063\u307d\u3093\u304e","line":"\u6771\u4eac\u30e1\u30c8\u30ed\u65e5\u6bd4\u8c37\u7dda","y":35.662799,"x":139.731151,"postal":"1060032","prev":"\u795e\u8c37\u753a","next":"\u5e83\u5c3e","prefecture":"\u6771\u4eac\u90fd","distance":328.0940048843225}]}}
こちらの取得結果をevalでjavascriptで評価して見ます*1
var json_for_eval = '{"response":{"station":[{"name":"\u516d\u672c\u6728","kana":"\u308d\u3063\u307d\u3093\u304e","line":"\u6771\u4eac\u30e1\u30c8\u30ed\u65e5\u6bd4\u8c37\u7dda","y":35.662799,"x":139.731151,"postal":"1060032","prev":"\u795e\u8c37\u753a","next":"\u5e83\u5c3e","prefecture":"\u6771\u4eac\u90fd","distance":328.0940048843225}]}}' eval('var nearestStation = ' + json_for_eval); nearestStation.response.station[0].name;//六本木 nearestStation.response.station[0].line;//東京メトロ日比谷線
ただしJSONではオブジェクトリテラルでは表現可能な関数、正規表現のリテラルは記載できません。
あとevalを使ってJSONをパースするのはアンチパターンなのでJSON.parseを利用するのがベターでしょう。
正規表現リテラル
リテラルを使う場合はコンストラクタで必要なエスケープが一部不要。簡潔性のため積極的にリテラルを使うべき。
ただし正規表現リテラルのオブジェクトは構文解析時にしか作られないため、実行時に組み立てるようなものはリテラルではなくコンストラクタを使うべき。
*1:evalは引数の文字列ををjavascriptとして解釈して実行しようとする関数です