JavaScript再入門

# クォーテーションはシングル？ダブル？
違いはないよう。
シングルを採用することの方が多い。

# 関数？メソッド？
オブジェクトのプロパティはメソッド。
そうでないものは関数。
のよう。

```js
obj.hoge();  // (オブジェクトの)メソッド
hoge();  // 関数
```

# セミコロンがあったりなかったりする
なくても動く。
が、絶対つけた方がいい。

書き方によっては、誤訳する可能性あり？

# 文字列の結合は
様々な言語を触っていると、つい忘れがちなのでメモ。

「+」　でつなげるのが一番いい。
参考：[文字列の結合方法による速度差](https://qiita.com/ampersand/items/0322e0820badf2c020be)

# スコープについて
## ブロックスコープはない
```js
var i = 1;
for (i = 0; i<4; i++) {
}

console.log(i); // 4
```

ただし、下記のletで実現が可能。

## 関数スコープ
関数の中で定義された変数は、その中でしか参照できない。

**ただし関数がネストしている場合、
子の関数は親の関数の変数を参照できる。**

# var、let、const
varとletはスコープの違い。
varは関数スコープ、letはブロックスコープ。

理由がない限り、letを使っていく方が良い。

constは名前の通り、定数。ブロックスコープ。
ただし、オブジェクトのkeyは保護されないので、全くの不変ではない。

```js
const HOGE = { key: 1 };
HOGE.key = 2;  // これはできてしまう
```

# レキシカル？
評価のたびに変わるものではなく、定義時に決まるもの。
静的なものと言えるかもしれない。

# グローバルオブジェクト
JavaScriptのコードはオブジェクトに格納されていなければならない。

ので、
何かコードを書けば、実はそれはグローバルオブジェクトに格納された扱いになる。

ブラウザならそれは「window」だし、
node.jsの場合は「global」になる。

# strictモード
いくつかの機能を制限することで、厳密なコードが書ける。
どんどん使った方がいい。

スクリプト単位、関数単位で書けるが、
スクリプト単位だと連結等で弊害があるかもしれないので、「関数単位」が良い。

```js
function hoge() {
  'use strict';  // 必ず最初に
  ...
}
```

strictモードは

・エラーではないが、落とし穴になるようなコードはエラーに
・最適化が困難なものを修正
・将来的なキーワードなどは禁止

といったことを保証してくれる模様。

# NaN、undefined、null
||説明|判別方法|備考|
|:--|:--|:--|:--|
|NaN|非数<br>(結果の存在しない演算結果)|isNaN(NaN)||
|undefined|何もない状態|ES5以降：<br>(x === undefined)<br><br>ES5以前：<br>(typeof x === 'undefined')|returnしない関数はundefinedを返す|
|null|返すものがない|(null === null)||

## 条件文等の判定について
参考：[[JavaScript] null とか undefined とか 0 とか 空文字('') とか false とかの判定について](https://qiita.com/phi/items/723aa59851b0716a87e3)

nullやundefinedを同時に処理したいなら

```js
if (hoge) {
```

のような書き方もできる。
しかし上記の場合、空文字、0、falseも条件に入らなくなるので注意。

# eval
文字列をJavaScriptの式として評価する。

```js
eval("2+2");
```

# thisが参照するもの
|thisを書いた場所|参照するもの|
|:--|:--|
|グローバル|グローバルオブジェクト|
|単純な関数内(非strict)|グローバルオブジェクト|
|単純な関数内(strict)|undefined|
|アロー関数内|関数の外のthis|
|オブジェクトのメソッド内|そのオブジェクト|
|コンストラクタ|そのオブジェクト|

## bind
オブジェクト内に単純な関数が記載されていた場合、
その呼び出し方によってthisの内容が異なる。

そんな場合にはbindを使ってthisを拘束できる。

```js:困った例
var hoge = {
  fuga: function () {
    return this;
  }
};

hoge.fuga();  // オブジェクトのthisなので、thisはオブジェクト自身となりhogeになる

var myFuga1 = hoge.fuga;
myFuga1();  // myFugaはただの関数になるので、thisがグローバルオブジェクト

var myFuga2 = myFuga1.bind(hoge);// hogeをthisとして拘束
myFuga2();  // thisはhoge
```

# 引数の型や数について
JavaScriptの引数は、

・型をチェックしない
 →typeof演算子を使う

・引数の数をチェックしない
 →引数が足りない場合は未定義、多い場合は無視される

・関数の呼び出しに使う引数は任意の数で良い(定義を気にしなくて良い)

# argumentsオブジェクト
関数はargumentsという配列のようなオブジェクトを参照できる。
動的引数などに使える。

```js
let func = function (x) {
  console.log(x);
  console.log(arguments[0]);
  console.log(arguments[1]);
  console.log(arguments[2]);
};

func(2,3,4); // 2234
```

# デフォルトの引数
```js
function hoge(a, b = 1) {
  return a + b;
}

hoge(2); // 3
```

# アロー関数
単純な関数を省略した記載方法。
thisやargumentsを拘束しないという効果もある。

```js
() => {...}
// ↑
// 同じ
// ↓
function () {...}
```

## もっと短縮する
・仮引数が存在する場合、引数を囲む括弧は省略できる
・処理がreturnの一文で済む場合、ブロックとreturnは省略できる
・短縮構文でオブジェクトリテラルを返す場合は、括弧で囲む必要がある

```js
(x) => { return x; }
// ↑
// 同じ
// ↓
x => x;
```

```js
var func1 = x => { key: x };
func1(1);  // undefined

var func2 = x => ({ key: x });　　//　これが正しい
```

## レスト引数
アロー関数内でargumentsは使えない模様。

ので、レスト引数で対応すれば良い。

```js
(...args) => {
  console.log(args);
}
```

# class
クラスを定義する方法は、class文(宣言)とclass式の二つがある。
どちらもstrictモードで実行される。

## class文
### 構文
```js
class MyClass [extends] {
}
```

```js
class MyClass extends BaseClass {
  constructor () {
　　　　　　　　// super()は親クラスのコンストラクタ
    // コンストラクタ内でのみ使える(thisの使用前に呼ぶ必要がある)
    super();

　　　　　　　　ｔｈｉｓ.name = 'Takashi';
  }
}
```

### 静的メソッド
静的メソッドはインスタンス化しなくても呼ぶことが可能だが、インスタンス化していると呼べない。

```js
class MyClass {
  static hoge () {
    ...
  }
}

MyClass.hoge();
```

### クラス変数
ES6だとできないらしい。
以下のような感じでやるしかない。

```js
class Hoge {
  constructor() {
    this.hoge = 1;
  }
}
```

## class式
class式は
・クラス名を省略できる
・再定義、再宣言ができる
・型エラーをスローしない
・typeofはfunctionを返す

### 構文
```js
var myClass = class [className] [extends] {...};
```

```js
var Hoge = class {
  constructor () {}
  one () { return 1; }
};

var hoge = new Hoge();
hoge.one();
```

```js:内部でクラスを参照したい場合は、クラス名をつける
var Hoge = class NamedHoge () {
  constructor () {}
  one () { return NamedHoge.name; }
}
```
# Function
## call、apply
参考：[Javascriptのcall/apply関数のプロっぽい使い方 〜 JSおくのほそ道 #014](https://qiita.com/hosomichi/items/155af03120a330fd4437)

例えば、二つの配列をマージしたいけど、
Array.prototype.pushの引数に配列は渡せない。
いくつかやり方はあるけど、普通の脳内だとループは免れない。

```js:ダメな私の脳内
let hoge = [1, 2, 3];
let fuga = [4, 5, 6];

fuga.forEach(value => { hoge.push(value); });
```

けどそんなの美しくない。
そんな時に↓

```js:例：二つの配列をマージ
let hoge = [1, 2, 3];
let fuga = [4, 5, 6];

// hogeに対して、fuga配列を引数としてpushを実行するよー
Array.prototype.push.apply(hoge, fuga);
```

上記例は以下を実行しているイメージ。

```js
let hoge = [1, 2, 3];

hoge.push(4, 5, 6);
```

配列で渡せないなら、applyの引数に配列を渡すという仕様を利用しようジャマイカ。
ということだ。

# Object
もの。
プロパティを持つことで、様々な性質を持つオブジェクトとして表現できる。
連想配列として使える。

## 生成
```js
var obj = new Object();

var obj = {[key1: value1, [key2: value2]...]};
```

関数も定義できる。

## プロパティへのアクセス
```js
var obj = new Object();

obj.hoge = 0;
obj['hoge'] = 1;
```

## Getter、Setter
カプセル化や、追加処理を書いたりできる。

```js
var obj = {
  hoge: '',
  get hoge() { 
    return this.hoge;
  },
  set hoge(val) {
    this.hoge = val;
  }
};
```

実装されていないgetter、ないしsetterにはアクセスできない(エラーが発生)

## プロパティの削除
```js
delete obj.hoge;
```

## ループで順番にアクセス
```js
for (val in obj) {
・・・
}
```

```js
Object.keys(obj).forEach(key => {
  console.log(obj[key]);
});
```

## コンストラクタメソッド
使いそうなものを抜粋。

|メソッド|説明||
|:--|:--|:--|
|Object.assign(target, ...sources)|targetにsourcesをコピーした結果を返す||
|Object.keys(obj)|プロパティのkeyを、文字列の配列で返す|key配列を取得してそれでループとかよくする|
|Object.values(obj)|プロパティの値を、配列で返す||

## instanceof
オブジェクトが自身のプロトタイプに、コンストラクタのprototypeオブジェクトを持っているか。

```js
var obj = {...};

if (obj instanceof Obj) {
...
}
```

# Array
配列のこと。

## 生成
```js
var arr = [];
var num = [1, 2];
```

## 要素の取得
```js
var num = [1, 2];

var zero = num[0]; // 1
```
## 要素数を知りたい
```js
var len = arr.length;
```

## ループで順番にアクセス
### for
```js
let arr = [1, 2];

for (let i= 0; i < arr.length; i++) {
...
}
```

### for in
配列のkeyを抽出。

```js
let arr = [1, 2];

for (let index in arr) {
  console.log(arr[index]);
}
```

### for of
配列の値を抽出。

```js
let arr = [1, 2];

for (let val of arr) {
  console.log(val);
}
```

### Array.forEach
```js
let arr = [1, 2];

arr.forEach((element, index, thisArr) => {
  // elementは処理中の要素
  // indexは処理中の要素番号（省略可）
  // thisArrは処理対象の配列自身（省略可）
});
```
#### forEachでbreakとかcontinueしたい
https://www.deep-rain.com/programming/javascript/778

|〜したい|方法|備考|
|:--|:--|:--|
|breakしたい|arr.some使え|someは、引数に指定したcallbackでtrueを返せば即座に処理終了する|
|continueしたい|returnを書く||
|returnしたい|無理||

## メソッド
|メソッド|説明|備考|
|:--|:--|:--|
|arr.filter(() => {...})|callbackがtrueを返した要素のみで構成された配列を生成し、返す。||
|arr.find((element, index, thisArr) => {...})|callbackが真を返した要素をすぐに返す<br>見つからなければundefind。||
|arr.findIndex((element, index, thisArr) => {...})|callbackが真を返した要素のインデックスをすぐに返す<br>見つからなければ-1。||
|arr.includes(search)|特定の要素が含まれているか調べ、booleanで返す。||
|arr.indexOf(search)|特定の要素が含まれているか調べ、最初の要素のインデックスを返す。<br>見つからなければ-1。||
|arr.reduce((pre, element, index, thisArr) => {...})|callbackが返した結果をpreに累積する||
|arr.map((element, index, thisArr) => {...})|callbackで返した値を配列に詰めて、結果に返す||
|arr.slice(begin[, end])|インデックスbeginから、インデックスendの手前まで返す||
|srr.some((element, index, thisArr) => {...})|callbackで返した値がtrueなら即座にtrueを返してくれる||

# JSON
## メソッド
|メソッド|説明|
|:--|:--|
|JSON.parse(str)|strを解析して、JSONに相当するObjectを返す|
|JSON.stringfy(js_value)|JavaScriptの値を、JSON文字列に変換して返す|

# prototype
継承元のオブジェクトみたいなもの。
継承先のオブジェクトは、暗黙の参照が可能となる。

メソッドの共通化などに用いられる。

```js
var Man = function () { this.name = ''; };

var Takashi = new Man();
Man.prototype.help = function () { alert('help!!'); };

Takashi.help(); // help!!
```

# 正規表現
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/RegExp

# try...catch
```js
try {
  // throw '好きな文字列';
} catch(e) {
  // eは例外オブジェクト
} finally {
  ...
}
```

# exportとimport
外部モジュール等から、関数、オブジェクト、プリミティブをエクスポート、インポートするために使用。

## 名前付きエクスポートとインポート
```js:my-module.js
function hoge() {...};
const fuga = 1;

export {hoge, fuga};
```

```js
import {hoge, fuga} from 'my-module';

console.log(hoge());
console.log(fuga);
```

## デフォルトエクスポートとインポート
インポート時に特に指定がなければ、デフォルトエクスポートの値が呼ばれる。

```js:my-module.js
export default function() {...};
```

```js
import hoge from 'my-module';

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