LoginSignup
29
30

More than 5 years have passed since last update.

JavaScriptのコーディングポイント【ES5まで】

Last updated at Posted at 2016-03-18

随時更新。
*ES5までのコーディングポイントです。

プリミティブ型は値渡し、オブジェクト型は参照渡し

プリミティブ型以外は参照元に変更が伝播する。

var user = { "name" : "サンプルユーザー" };
var copy_user = user;

copy_user.name = "更新ユーザー" //Object {name: "更新ユーザー"}
user //Object {name: "更新ユーザー"}

for in は基本的に使わない

for in はprototypeが汚染されていた場合に以下の様なバグを引き起こす。

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ユーザー

けどネストが深くなるし、綺麗じゃない。
なので、Object.keysを利用したループを使う。

Object.keys(user).forEach(function(key){console.log(key)})

オブジェクトのディープコピー

JavaScriptでは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

== と ===

JavaScriptの == 演算子は不安定なので可能な限り使わない。

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

一応 == は undifind判定で使ったりはする。
とりあえず == を使っているようなら === に書き換えることを お勧めする。

グローバル変数の削減

グローバル変数を一つに限定し、
以降 実装に必要な変数は全てグローバル変数のプロパティとして宣言する。

var Main = {};
Main.UserModel = {......}
Main.UserController = {.....}

関数内で引数を参照

関数内で自身に渡された引数を参照したい場合 arguments を参照する。

arguments はすべての関数内で利用可能なローカル変数です。arguments オブジェクトを使うことにより、関数内で関数の引数を参照できます。このオブジェクトは、関数に渡された各引数に対する入力を含みます。最初の入力の添え字は 0 から始まります

argumentsはlengthプロパティのみをもつObjectであるためArrayのように扱うには一旦Arrayに変換する必要がある。

var avg = function(){
    var stack = 0;
    Array.prototype.slice.call(arguments).forEach(function(num){
        stack += num;
    });

    return stack/arguments.length
}

avg(20,10,30) //20

Arrayメソッドを適切に扱う

Arrayオブジェクトの処理はforEachだけではなく
処理に合った適切なメソッドを利用する。

  • 一つでも条件を満たすか判定
['10','20','30'].some(function(value){
  return value.match(/^1/);
})
//⇒true
  • 全ての条件を満たすかを判定
['10','20','30'].every(function(value){
  return value.match(/0/);
})
//⇒true
  • 左から順番に処理をした結果を返す
['10','20','30'].reduce(function(before, after){
  return before+after;
})
//⇒102030
  • 右から順番に処理をした結果を返す
['10','20','30'].reduceRight(function(before, after){
  return before+after;
})
//⇒302010
  • 指定の処理を行い、結果を新規配列で返す
var result = ['10','20','30'].map(function(value){
  return (+value)+1
})
//⇒[11, 21, 31]
  • 条件を満たしたもののみ抽出し、新規配列を返す
var result = ['10','20','30'].filter(function(value){
  return (+value) >= 20;
});

番外編

処理には直接関わらないイディオム的なもの。

複数の変数定義で var を省略

複数の変数定義は , で繋げることで var を省略することができる。
最終定義で必ず ; 入れる必要がある。
※ lintを入れるとエラーになるケースもあるので注意

var a = new Date(),
    b = [],
    c = {};

null ガード

null or undefined をガードする。
ただし変数自体が未定義の場合はエラーを返すため注意。

var user = {},
    name,
    type = '男性';

user.name = name || 'ゲスト'; //ゲスト
user.type = type || '女性'    //男性
29
30
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
29
30