JavaScript入門したときの備忘録

## はじめに
Android JavaエンジニアがReact Nativeを見据えてJavaScript入門した際の備忘録。
ECMA2015(ES2015/ES6)前提。

## 参考になった資料
- Mozilla Developer Network
  https://developer.mozilla.org/ja/docs/Web/JavaScript

- 改訂新版JavaScript本格入門 ~モダンスタイルによる基礎から現場での応用まで (技術評論社)
  http://gihyo.jp/book/2016/978-4-7741-8411-1
  他言語との比較を意識した説明が多くてわかりやすい。

## オブジェクト
JavaScriptではキー名と値のペアで構成された連想配列がオブジェクトとなる。
(別途、コレクションとしての機能を充実させたMapオブジェクトもある)

定義例 (キー名:値)

```js
var obj = {
  key1:value1,
  key2:value2,
  ...
}
```

使用例 (ドットまたはブラケット)

```js
obj.key1
obj['key1']
```

関数の戻り値なんかで匿名もよく利用される。

```js
return {key1:value1, key2:value2};
```

## プロトタイプ
オブジェクトはなんらかのプロトタイプをもつ。("Object"のはnull)
プロトタイプは動的に変更可能。

- 基本
以下のようにしておくと、Getter, Setterはchildのprototpyeの参照先のメソッドになるので、メモリを節約できる。
プロトタイプは子が使う汎用的な関数を定義しておく。

```js
function ParentClass(str){
  this.myString = str;
}

ParentClass.prototype = {
  setString: function(str){
    this.myString = str;
  },
  getString: function(){
    return(this.myString);
  }
}

var child = new ParentClass("hello");
```

プロパティの宣言はコンストラクタで！
メソッドの宣言はプロトタイプで！

- 関連プロパティ
  - "prototype" : 生成先のプロトタイプとなるオブジェクト。
  - "\_\_proto\_\_" : newで生成した時、コンストラクタの"prototype"へのアドレスを格納する。
    => Object.createで作るときは、親の.prototypeを引数で指定する。
    生成時点では空オブジェクト。
    Objectの"\_\_proto\_\_"はnull。

- プロトタイプチェーン
  - メンバを探す際は、"\_\_proto\_\_"がnullになるまで、プロトタイプを辿っていく。

## クラス
JavaScriptはプロトタイプベースのオブジェクト指向言語で、Javaのような"クラス"はない。
ないが、ES2015からクラスっぽく書けるシンタックスシュガーが用意された。

```js
class Hoge extends Piyo{
  constructor(firstName, lastName){  //コンストラクタ, 名前固定
    super();  //親コンストラクタ
  
    this.firstName = firstName;
    this.lastName = lastName;
  }
  
  //Getter
  get firstName(){
    return this.firstName;
  }
  
  //Setter
  set firstName(firstName){
    this.firstName = firstName;
  }
  
  //メソッド
  func1(){
  }
  
  //スタティックメソッド
  static func2(){
  }
}
```

## 関数
- 宣言

  ```js

  function 関数名(引数, ...){
    return 戻り値;
  }
  
  //またはFuctionオブジェクトから
  var f = new Fuction(引数, ..., 本体);
  ```
  
- 関数自身もデータ型の一つ
  他の関数の引数として渡せる

- 引数
  JavaScriptの関数は引数チェックしない
  引数の数も型も自由。
  デフォルト値を設定しとくと、省略された際に使われる。

- 必須 or オプションの指定
  必須の引数はデフォルト値に例外起こす関数を入れておく。
  省略可能な引数は名前に"o_"や"opt_"をつけとくとわかりやすい。

- argumentsが呼び出し時の引数を保持する
  argumentsは引数管理用のArrayもどき。Argumentオブジェクト。
  arguments.lengthで引数の数を調べたりできる。
  
## アロー関数
  関数を簡略化して書ける。
  アロー関数内のthisは呼び出し元のオブジェクトを示す。
  
  - 基本
  
    ```js

    (引数,...) => {...関数本体...};
    ```
  - 本体が1文なら{}とreturn省略

    ```js
    (x,y) => x * y;
    ```
  - 引数が１つなら()省略
    
    ```js
    result = r => r * r / Math.PI;
    ```
  - 引数がなければ()は残す
    
    ```js
    result = () => console.log("hoge");
    ```

## 変数スコープ
- varなし : グローバルスコープ
- var : ローカル変数、宣言された関数内全体で有効
- let : ブロックスコープ
- グローバルオブジェクト
  - 関数に属さないトップレベルの変数や関数を管理するオブジェクト
  - グローバル変数/関数はグローバルオブジェクトのプロパティになる
- Callオブジェクト
  - function生成時に自動的に作られるオブジェクト(Activation Objectともいう)
  - 関数内のローカル変数は、このオブジェクトのプロパティになる
- スコープチェーン
  - 変数の定義を探す際に、内側から
  - Callオブジェクト->Callオブジェクト->...->グローバルオブジェクトのリストを辿って解決する。

## クロージャ
- 関数内関数を外に出して保持する。
- 匿名関数が有効である間はローカル変数が保持される。(例ではcounter)

```js
function hoge (x){
  var counter = x;
  
  return function(){  //*
    return ++counter;
  }
}

var cl = hoge(1);   //*の関数をクロージャとして取り出す
console.log(cl());  //2
console.log(cl());  //3
console.log(cl());  //4
```

## モジュール
基本的にファイル単位でモジュール化する。
privateやpublicの概念はなく、基本非公開。
exportしたオブジェクトのみ他のモジュールに公開される。

- export  
exports.hoge = hoge; でpublicに。変数、定数、関数、オブジェクト。
exportしないと非公開。
モジュール内の要素が一つだけであれば、defaultのエクスポートを利用できる。
デフォルトモジュールの要素はクラス名や関数名が不要になる。

default exportの例

```js:Area.js
export default class {
  ...
}
```

```js
import Area from './Area'
```

- import  
 import {hoge} from './filename'
 hoge:要素名
 filename:拡張子を抜いたパス

## 比較
"=="だと型変換後に比較
"==="だと型変換なしで厳密に比較

## イテレータ
for...in : オブジェクトのプロパティ名を順不同で取り出す
for...of : オブジェクトのプロパティの値を取り出す

## Promise
非同期処理を同期処理のように簡潔に書ける。

```js
var p1 = new Promise(
    function(resolve, reject) {
      resolve(val)  //成功, thenの第一引数が呼ばれる
      or
      reject()  //失敗, thenの第二引数またはcatchが呼ばれる
    });

p1.then(
    function(val) {
      
    })
  .catch(
    function(reason){
    
    });
  );
```

rejectした場合、thenの第二引数か、catchが呼ばれる。

連結すると便利。

```js
p1.then(...).then(...).then(...)....then(...);
```

## 分割代入
オブジェクトのあるプロパティだけを取得し、そのまま変数として使える。

```js
state = { hoge:'aaa', piyo:'bbb'};
let { hoge } = this.state; //let hoge = this.state.hoge; なイメージ。

console.log(hoge);  //aaa
```

## 名前空間
グローバル変数をグローバルスコープのオブジェクト配下にすることで、名前空間に属しているように振る舞い、名前の衝突を防ぐ。

```js
var Sample = Sample || {};  //Sampleが未定義なら。

Smaple.hoge = 'Hello';
Sample.func = function(){
  ...
}
```

## おわりに
また更新するかも。