Javascriptでコーディングする際のポイント
1. プリミティブ型は値渡し、オブジェクト型は参照渡し
var user = { "name" : "サンプルユーザー" }; var copy_user = user; copy_user.name = "更新ユーザー" //Object {name: "更新ユーザー"} user //Object {name: "更新ユーザー"}
このように参照元に変更が伝播する。
これが原因で意図しないバグが出るとかよく聞く話。
2. for in は使わない
Object.prototype.bag = "プロトタイプを汚染"; var user = {}; user.name = "SAMPLEユーザー"; for(var key in user){console.log(user(key))} //SAMPLEユーザー , プロトタイプを汚染
プロトタイプが汚染されているとプロトタイプチェーンぬよって こんなバグが発生する。
これのよくある回避方法は hasOwnProperty を使った以下の方法
for(var key in user){ if ( user.hasOwnProperty(key)) console.log(key) }//SAMPLEユーザー
ただ if文 が入るのでネストが深くなる。
ついでに ほぼ影響はないだろうけど全プロパティに評価が実行される問題もある。(速度にほとんど影響はでないだろうけど...)
なので こっちを使う。
Object.keys(user).forEach(function(key){console.log(key)})
こっちの方がスッキリしてるし何より Cool!!
え....for i ?
....知らない子ですね
3. Object型のディープコピー
Object型変数のディープコピーメソッドはネイティブには存在しない。
JSONを使って複製する方法はあることにはあるが、実は完全なディープコピーでは無かったりする。
var user = {}; user.call = function(){console.log("hogehoge")}; user.call() //hogehoge var copy_user = JSON.parse(JSON.stringify(user)); copy_user.call(); //copy_user.call is not a function(…)
このようにfunctionが破壊されてしまっている。
多分ネイティブのみでディープコピーをしようとすると自前でメソッドを実装するしかない。
残念ながら、そんな労力を払う気にはならないので、JQueryの$.extendを使って解決する。
var user = {}; user.call = function(){console.log("hogehoge")}; user.call(); //hogehoge var copy_user = $.extend(true,{},user); copy_user.call();//hogehoge
ちなみにコピーなので変更による伝播は無い。
copy_user.call = function(){console.log("メソッド書き換え")}; user.call(); //hogehoge copy_user.call(); //メソッド書き換え
3. == と ===
== の比較演算子は恐ろしい挙動をとる。
23 == "23" //true null == undefined //true 0 == ''" //true false == '0' //true false == 0 //true
...なんでだよと突っ込みたくなる。
一方 === では
23 == "23" //false null == undefined //false 0 == '' //false false == '0' //false false == 0 //false
どちらが安全なコーディングかは一目瞭然。
とりあえず == を使っているようなら === に書き換えることを お勧めする。
4. グローバル変数の削減
グローバル変数の宣言はアプリケーションで一つのみに制限することが最も良い。
var Main = {}; Main.UserModel = {......} Main.UserController = {.....}
このようにグローバル変数を一つに限定し、
以降 実装に必要な変数は全てグローバル変数のプロパティとして宣言すればいい。
そうすることでグローバル変数の問題から開放されストレスの無いコーディングが可能になる。
注意点としてはグローバル変数から全プロパティにアクセス可能なため
外部からアクセスされたくないメソッド、変数がある場合はクロージャ等で外部からアクセスできないようにする必要がある。