JavaScript中級TIPS



## 文字列リテラル

HTMLを含む文字列を生成する際に便利なため、囲む時はシングルクォート`'hoge'`がよい

## セミコロン

末尾にセミコロンをつけなくても解釈してくれるが、バグを生む可能性があるのでセミコロンはつけるように習慣化する

ES6のclass記法のメソッド末尾にはセミコロン不要

## 同値比較

基本的に`===`をつかう。`==`だと寛容過ぎる解釈のため、バグを生むことがある。

## 短絡評価

hogeFuncの引数にtrue相当の値が入ってきた場合、
`||`の右側は読まれない。

hogeFuncの引数にfalse相当の値が入ってきた場合、
（`false`, `null`, `undefined`, `NaN`, `""`, `0`）
`||`の右側を読みにいく。

```javascript
function hogeFunc(e){
    e || console.log('piyo');
}
hogeFunc(1); // 何も出力されない。もし短絡評価がなければ右側も評価されるのでpiyoが出力される
hogeFunc(); // piyoが出力される
```

こういう使い方も


```javascript
function hogeFunc(e){
    var hoge = e || 1;
    console.log(hoge);
}
hogeFunc(5); // 5
hogeFunc(); // 1
```


## for文

```javascript
for(let i = 0, j = 0; i < 3; i++, j+=2){ // カンマで複数追加もできる
  console.log(i,j);
}
```

`for...in`はインデックス番号やキー名を取り出すだけなので、連想配列やオブジェクトを走査するときだけに使う。不便。

> [追記] 20160808
｢for...in列挙遅すぎ問題｣「prototype汚染列挙問題」等が存在しますので、現代的なJavaScriptにおいてはそもそも for...in 自体を使わない方が安全です。

一方、ES6の`for...of`は値を返してくれるので便利。

`Array.prototype.keys()`と`Array.prototype.entries()`も使えばもっと便利

```javascript
let arr1 = ['a','b'];
let arr2 = ['あ','い','う'];
// ...iterable
// イテラブルなオブジェクトの値を順次取り出す
let margeArr = [...arr1, ...arr2]; // 配列の結合もできる

for(let val of margeArr){
  console.log(val);
	// "a"
	// "b"
	// "あ"
	// "い"
	// "う"
}
for(let val of margeArr.keys()){
  console.log(val);
	// 0
	// 1
	// 2
	// 3
	// 4
}
for(let [i, val] of margeArr.entries()){
  console.log(i, val);
    // 0 "a"
    // 1 "b"
    // 2 "あ"
    // 3 "い"
    // 4 "う"
}
```

配列操作の詳細はこちら
http://qiita.com/mo4_9/items/2968fea172c028d58aec


## 型

|型|具体例|引数の渡し方|
|---|---|---|---|
|プリミティブ|boolean, number, string, symbol(ES6), null, undefined|値渡し|
|その他|object|参照渡し|

### プリミティブ型

- **boolean, number, string, symbol(ES6)**
オブジェクトとして振舞おうとした際に、バックグラウンドでそれぞれの型に応じたラッパーオブジェクトが生成される。
（ちなみにES6からプリミティブ型の明示的なラッパーオブジェクトの作成はサポートされなくなった為、Symbolはnewできない）

- **null, undefined**
ラッパーオブジェクトなし。常にプリミティブ型。


> 参考
[javascript ラッパーオブジェクト](http://qiita.com/lrf141/items/eaa13cc22ead21ddff0b)
[ES6で追加された新しいプリミティブ値Symbolのメモ](http://yokotakenji.me/log/programming/js/es6/4482/)

### null と undefined の違い

`null`はエンジニアが意図的にセットしないと出会すことはない。
`undefined`はエンジニアのミスで発生する。

初心者はざっくりと上記の認識でok
あとは以下のような地雷を踏んだとき、その都度覚えていけばいい

```javascript
// #hogeがDOMに存在しない状態で
console.log( document.getElementById('hoge') ); // null
console.log( 'hoge'.match(/a/) ); // null
```

`null`：定義済み（存在している）だが、値や型がない
`undefined`：未定義（存在していない）


>参考
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/null

### 型変換

`-（マイナス）`は数値演算子にしかないので、Stringの`'1'`に`- 0`すると`'1'`がNumberに暗黙で型変換（キャスト）される。`+（プラス）`はStringの連結にも使うのでNumberへの型変換はおこなわれない。

```javascript:暗黙的型変換
'1' - 0 // 1 (Number)
'1' + 0 // '10' (String)
```

しかし上記はパッと見わかりにくいので、使わないほうがいい。
代替案として`parseInt()`と`Number()`
さらに`parseInt()`のほうが柔軟に処理してくれるので便利と言える

```javascript:parseInt()とNumber()
parseInt('1') // 1
parseInt('1px') // 1
Number('1') // 1
Number('1px') // NaN -> Not-A-Numberの略でnumber型
```

> 参考
[型変換のいろいろ](http://qiita.com/zawascript/items/a25eaf7a222ac3671275)


## JSON

ごちゃっとしたデータはJSONにまとめる

変換ツール
http://shancarter.github.io/mr-data-converter/

整形ツール
https://chrome.google.com/webstore/detail/json-viewer/gbmdgpbipfallnflgajpaliibnhdgobh


## 関数

JavaScriptにおける関数は[第一級オブジェクト](https://ja.wikipedia.org/wiki/%E7%AC%AC%E4%B8%80%E7%B4%9A%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88)である。
型は「 **[[Call]] を持つ Object 型** 」であり、関数型は存在しない。

> 参考
[まさに忍者...JavaScriptの関数は第一級オブジェクト](http://maeharin.hatenablog.com/entry/20130308/javascript_function_ninjya)
[12.5.6 The typeof Operator – ECMA-262 6th Edition](http://www.ecma-international.org/ecma-262/6.0/#sec-typeof-operator)


## 即時関数

`!`を先頭につけるとシンプルになる。小ネタ。

```javascript
!function hoge() {
  console.log('hoge');
}();
```

ES6からはブロックスコープのマスキングが不要だったりするので使用頻度は減りそうだが、以下のようなケースでは使用する必要あり。

・名前付き関数式で再帰呼び出し
・Function.prototype.call() で this 値を変更

```javascript:StrictModeでグローバルオブジェクトを渡す
'use strict';
(function () {
  console.log(this);
}.call(this));
```

> 参考
[Function.prototype.call()](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Function/call)
[JavaScript, 即時関数でthisを指定して引数も受け取る](http://blog.walfo.jp/immediate-function-call-this/)
[ES2015(ES6)新構文：アロー関数(Arrow function)](http://analogic.jp/arrow-function/)
[ES2015(ES6)の即時関数は短く書けるしletならそもそも不要](http://iwb.jp/es2015-es6-immediate-function-let/)



## Class

クラス名 -> 名詞
メソッド名 -> 動詞

なるべく細かく外部ファイルに切り分ける
1ファイル100行以内くらいが理想


### new演算子

オブジェクトのインスタンスを返却しなさい！とコンストラクタに命令する演算子。
自動的に`return`しているということ。

### this

```javascript:よくあるハックself=this;
class class1 {
  func1(){
    // ここでのthis=class1オブジェクト
    const self = this;
		
    img.addEventListener('load', function(){
      // ここでのthis=img
    }, false);
  }
}
```


## argumentsオブジェクト

関数呼び出しの際に引数のチェックがないのでargumentsオブジェクトで管理する。
ES6だと可変長引数を容易に配列に格納できる。

```javascript
function f(x, ...aiu) {
  console.log(x, aiu); //　1 ["a", "i", "u"]
  
  // 引数の値を取得
  for(let i = 0; i < arguments.length; i++){
    console.log(arguments[i]);
  }
  
  // エラーハンドリング
  if(arguments.length != 2){
    throw new Error('引数の数が不正です');
  }
  
  // 可変長引数の値を取得
  for(let arg of aiu){
    console.log(arg);
  }

}

f(1, 'a', 'i', 'u');
```

引数が多い場合は、引数に名前をつけるとわかりやすい

```javascript
function person(opts = {}){ // 初期値の設定
  const name = opts.name;
  const age = opts.age;

  console.log(name,age);
}

person ({
  name:'bob',
  age:30
});
```

※ES6前提なら可変長引数だけで十分。argumentsは不要。


## bind

thisを束縛する

```javascript
function sum (val1,val2){
  console.log(this.val + val1 + val2);
}
let obj1 = {val: 1};
let obj2 = {val: 2};

let obj1Sum = sum.bind(obj1); // thisだけを指定
let obj2Sum = sum.bind(obj2,2,2); // thisと引数を指定

obj1Sum(1,1); // 3
obj2Sum(); // 6
```

thisをnullにして、引数のみを束縛する

```javascript
function sum(x,y,z){
  console.log(x+y+z);
}

let sumA = sum.bind(null,1);
sumA(2,3); // 6
```


## get / set

functionの部分をget/setにする

```javascript
let human = (() => {
  let _name;
  return { // クロージャ
    get name(){
      return `名前は${_name}です`;
    },
    set name(val){
      _name = val;
    }  
  }
})(); // 即時実行

human.name = 'steve';
human._name = 'jobs';
console.log(human.name);
console.log(human._name);
```

## Ajax

#### Ajax通信
http://qiita.com/mo4_9/items/22eaf3bf469b8c272df7

#### Deferred
http://qiita.com/mo4_9/items/67763587e6f0f7306ca4


## イベント

#### イベントの伝播
http://qiita.com/mo4_9/items/f05cb7b0518b4a7dbd5d

#### カスタムイベント
http://qiita.com/mo4_9/items/2ac77bdc7399600bc2d4


## クロージャ

http://qiita.com/mo4_9/items/baa7fc28aafb04517d57


> 参考
[ES6 チートシート](http://postd.cc/es6-cheatsheet/)
[JavaScriptの理解を深めた人がさらにもう一歩先に進むための本](https://www.amazon.co.jp/JavaScript%E3%81%AE%E7%90%86%E8%A7%A3%E3%82%92%E6%B7%B1%E3%82%81%E3%81%9F%E4%BA%BA%E3%81%8C%E3%81%95%E3%82%89%E3%81%AB%E3%82%82%E3%81%86%E4%B8%80%E6%AD%A9%E5%85%88%E3%81%AB%E9%80%B2%E3%82%80%E3%81%9F%E3%82%81%E3%81%AE%E6%9C%AC-%E4%BA%94%E5%8D%81%E5%B5%90%E8%82%87-ebook/dp/B01HUNYZNW/ref=sr_1_fkmr0_1?s=digital-text&ie=UTF8&qid=1470646442&sr=1-1-fkmr0&keywords=JavaScript%E3%81%AE%E7%90%86%E8%A7%A3%E3%82%92%E6%B7%B1%E3%82%81%E3%81%9F%E4%BA%BA%E3%81%8C%E3%81%95%E3%82%89%E3%81%AB%E3%82%82%E3%81%86%E4%B8%80)