知らないとバグになる、JavaScriptがクセ者だと思う10の仕様

JavaScriptって、動きが想定外な時ってありませんか？
思い込みで動かしていて、なんかバグが出ていると思うと実はJavaScriptの仕様だったということがいくつかあります。

「JavaScriptめ！」と言ってしまいたくなる仕様（つまり、バグの温床になりそうな仕様）をリストアップしてみました。
頭に入れておくだけで、バグにならずに済むと思います。

## 1. 配列・オブジェクトが参照渡し
JavaScriptの配列・オブジェクトは値渡しではなく、参照渡し。
これを、知らないと痛い目を見る・・・

```JavaScript
var ary = [1,2,3,4,5,6];
var obj = {0:1,1:2,2:3,3:4,4:5,5:6};

ary2 = ary;
obj2 = obj;

ary2.splice(0,1);
delete obj2[0];

console.log(ary);  // 更新されている => [2, 3, 4, 5, 6]
console.log(obj); // 更新されている => {1: 2, 2: 3, 3: 4, 4: 5, 5: 6}
```

なので、値渡しでコピーしたい時に、forで回したり、JQueryで処理したりと色々あるが、個人的に落ち着いた方法はJSONにして、parseする方法

```JavaScript
ary3 = JSON.parse(JSON.stringify(ary));
obj3 = JSON.parse(JSON.stringify(obj));

ary3.splice(0,1);
delete obj3[0];

console.log(ary); // 更新されていない => [1, 2, 3, 4, 5, 6]
console.log(obj); // 更新されていない => {0:1, 1: 2, 2: 3, 3: 4, 4: 5, 5: 6}
```

## 2. オブジェクトがKeyで勝手にソートされる
Keyのつけ方を工夫しないといけない。

```JavaScript
var obj = {5:1,4:2,3:3,2:4,1:5,0:6};

console.log(obj); //{0: 6, 1: 5, 2: 4, 3: 3, 4: 2, 5: 1}
```

[参考：JavaScriptの配列がキー値で自動ソートされてしまう件](http://techblog.night-in-gale.com/javascript/267/)

## 3. テキスト置換（ .replace() )が１つ目の対象しか対応できない
JavascriptのString.replace() はglobalじゃない

```JavaScript
var test = 'abc_def_abc';
console.log(test.replace('abc','xyz')); // xyz_def_abc
```

正規表現にする

```JavaScript
console.log(test.replace(/abc/g,'xyz')); // xyz_def_xyz
```

## 4. ブラウザによって挙動が異なる
これは、コードレベルではないのでコメントだけ。
JavaScriptはブラウザによって挙動が異なることがある。

特にIE。
それ以外にもブラウザで異なるので注意が必要。

JavaScriptの仕様である ECMA Scriptに沿った組み方を意識しつつ、挙動を各ブラウザで確認する必要がある。

## 5. セミコロンの自動挿入
JavaScriptの緩い仕様。
文の終わりを示す、セミコロンを自動挿入してくれてしまう。

```JavaScript
var a = 1

//これは、以下になる
var a=1;
```

そうすると、return を改行してしまった時、

```
return
a

//これは、以下になる return がnull
return;
a;
```

お節介いらないので、セミコロンなければ、最初からエラー吐いて欲しい。

## 6. ローカル変数の宣言位置による仕様
あまり出くわさないけどやってしまいそうな仕様。

```JavaScript
var a = 'global';
var func = function() {
  alert(a);
  var a = 'local';
};
func(); // undefined

//これは以下と同じになるらしい
var func = function() {
  var a; //  undefinedで宣言
  alert(a);
  a = 'local';
};
```

何これ。

## 7. 日付処理の月が0から11
これは見た方が早い。

```JavaScript
var dt = new Date(); //今日が9月22日だったとすると
alert(dt.getMonth()); // 8
```

何これ。

## 8. オブジェクトと配列で削除方法が異なる
オブジェクトと配列は意識して使い分けなければならない、という当たり前のようで、よくエラーを起こしがちな所。

```JavaScript
var ary = [1,2,3,4,5,6];
var obj = {0:1,1:2,2:3,3:4,4:5,5:6};

ary.splice(3,1);  //削除される
obj.splice(3,1);  //errorになる

delete ary[3]; //削除されるがlengthは変わらない
delete obj[3]; //削除される
```

## 9. オブジェクトと配列のlength
オブジェクトと配列は意識して使い分けなければならない、その２
オブジェクト.lengthはundefinedになる

```JavaScript
var ary = [1,2,3,4,5,6];
var obj = {0:1,1:2,2:3,3:4,4:5,5:6};

console.log(ary.length); //6
console.log(obj.length); //undefined
console.log(Object.keys(obj).length); //6
```

なぜ、返してくれないのか。。。不親切だ。

また、こんな仕様もあるらしい。

```JavaScript
var arr = new Array();
arr[0] = "hello";
console.log(propertyNameList(arr).join()); // "0"

//無理やり10のindexに突っ込むと
arr[10] = "hello";

console.log(propertyNameList(arr).join()); // "0,10"

//えっ！
console.log(arr.length); // 11

arr.shift();

//ええっ!
console.log(arr.length); // 10
```

ほんと、やめてください。

## 10. function xxxx()  と var xxx = function(){} の違い
似ているからと言って同じだと思っていると痛い目を見るやつ。

```JavaScript
xx1();	//問題なし（function xx1()は先に読まれる
xx2();	//error（xx2 is not a function)
function xx1(){
	alert('go1');
}
var xx2 = function(){
	alert('go2');
}
```

まぁ、そもそも先に未定義functionをcallするというのは避けるとは思いますが、既存コードの改修などの時にやってしまった。少しの間、何が問題か見つけられずハマった。

参考記事：
http://d.hatena.ne.jp/sandai/20100427/p1
http://steps.dodgson.org/bn/2006/04/02/

JavaScriptはクセ者です、というお話でした。