ES6の構文じゃなくて、あえてそれ以前のJavaScriptの基礎を押さえる

# ES6でいいのでは？
ES6の`class`等は、本来あった文法のシンタックスシュガー。なので、ES6の便利な書き方じゃないJavaScriptを押さえて、**JS使えます!!**って言えるようになりたい。

この記事では、**オブジェクト・関数・スコープチェーン(クロージャー)**について記載します。

# JavaScriptのオブジェクト
一般的なプログラミング言語で使われるすべての**モノ**を表す文脈で使用される場合と、**Objectオブジェクト**のインスタンス(生成元のオブジェクトのプロパティを継承したオブジェクト)として使われる場合がある。
前者はいいとして、後者は以下のようになる。

```javascript
var obj = {
  name: 'objectName',
  getObj: function() {
    console.log(this.name);
  }
}
      
console.log(obj.name); // objectName
obj.getObj(); // objectName
```

この変数に代入している`{}`が**Objectオブジェクト**の生成。`new Object()`で生成するのと同じ(シンタックスシュガー)。オブジェクト自身には、プロパティ`name`やメソッド`getObj`を定義することができる。

```javascript
var obj1 = {};
var obj2 = new Object();
console.log(typeof(obj1)) // object
console.log(typeof(obj2)) // object
```

# 関数について
## 関数もオブジェクトの仲間
JavaScriptの関数は**第一級オブジェクト**である。(これ言ってみたかった)
第一級オブジェクト＝生成、代入、演算などが制限なく行える対象 by wiki
... ちょっと難しいが、`1`や`2`などの数値、`a`や`b`などの文字列などのリテラルと言われる対象のこと。ここで大事なのは関数もオブジェクトなので、**変数に自由に代入したりできる**ということだけ。

```javascript
var foo = function() { console.log('foooooo'); }
foo() // foooooo
```

## 通常の関数呼び出しと、new付きの関数呼び出し
定義した関数を呼び出すときに、`new`をつけるかつけないかで処理が大きく変わる。

```javascript
var testFunc = function() {
  this.name = 'foo';
}
var obj1 = new testFunc();
var obj2 = testFunc();
console.log(obj1); // testFunc {name: 'foo'}
console.log(obj2); // undefined
```

`obj2`の場合は`new`がないので、ただの関数呼び出しになる。returnがない関数の戻り値は`undefined`なので`undefined`エラーになってしまう。
一方、`obj1`の場合はインスタンスが生成されていることがわかる。これは`new`したときに以下のような暗黙の処理が入ることによる。

```javascript
var testFunc = function() {
  // var this = {}
  this.name = 'foo';
  // return this;
}
```

コメントアウトした部分が暗黙の処理にあたる。
`this`[^1]オブジェクトが内部で定義され、そのオブジェクトに`name`プロパティがセットされて、`this`オブジェクトを返却するという処理を行ってくれると考えると(個人的には..)わかりやすい。

[^1]: `this`については別途まとめようかと。

# スコープチェーンについて
JavaScriptのイケてる**クロージャー**を理解するためには**スコープチェーン**を理解する必要がある。＝**プログラミングの裏側で何が起こってるか**を意識する必要がある。
まず、JavaScriptを実行すると、グローバルスコープ上にオブジェクトの最上位存在であるGlobalオブジェクトが自動で生成される。例えば、webブラウザのconsoleで実行した場合はwindow[^2]オブジェクトがグローバルオブジェクトになる。グローバル変数の定義=windowオブジェクトのプロパティ定義である。

[^2]: 何となく、昔JavaScript界隈でよく聞いたDOMを思い出して、ちょっと調べた。document.getElementById的な。数多くあるライブラリでもうすっかり見なくなったが。。DOM=DocumentObjectModelの略で、windowオブジェクト->documentオブジェクトの下にhtmlタグとかが存在して、それらの文章をツリー上に表現したものらしい。documentもwindowオブジェクトのプロパティの一部。

```javascript
var foo = 'foo';
foo === window.foo; //true
```

次に、関数を呼び出す度に自動で生成されるオブジェクトが**Callオブジェクト**で、関数内のローカル変数・引数・親Callオブジェクトのアドレスなどを管理[^3]する。
このCallオブジェクトをチェーンのように連結したリストは、Globalオブジェクトを末端にし、Callオブジェクトが生成されるたびに伸びていく。
変数などを探索する場合は、Globalオブジェクトと逆の先端から探索して最初に見つかった値を返却する。このリストが**スコープチェーン**といわれる。


[^3]: メモリ管理はヒープ領域で行っていて、ガベージコレクションする言語とのこと。なので、クロージャーとか使えるのかな？

```javascript
// Globalオブジェクトが生成される #1
var prop1 = 'global';
var prop2 = 'global';  

// outer関数用のCallオブジェクトが生成される #2
function outer() {
  var prop1 = 'outer';
  
  // inner関数用のCallオブジェクトが生成される #3
  function inner() {
    var prop3 = 'inner';
    
    console.log(prop1); // outer #3→#2に存在するため
    console.log(prop2); // global #3→#2→#1に存在するため
    console.log(prop3); // inner #3に存在するため
  }
  
  inner();
  console.log(prop1); // outer #3→#2に存在するため
}  
  
outer();
```

上記のサンプルでスコープチェーンを確認すると、Globalオブジェクト(#1)、outerオブジェクト用のCallオブジェクト(#2)、innerオブジェクト用のCallオブジェクト(#3)の順でリストが生成され、#3→#2→#1の順で変数の値を探索していき、値があればその値を返却する。ない場合は`ReferenceError`。

# クロージャーについて
スコープチェーンがわかればクロージャーを(たぶん)理解したようなもの。
クロージャーとは、自身(関数)を定義している関数の中にローカル変数の参照があるもの。ローカル変数は通常、関数呼び出し後に破棄されるが、クロージャーはローカル変数を**参照し続ける**ことが可能。ローカル変数の参照を関数内に閉じ込める(closure)ということ。
先ほどのサンプルのinner関数もクロージャーといえる。が、わかりづらいのでよくあるカウントアップを記載する。

```javascript
var counterFunc = function() {
  var count = 0;
  return function() {
    count++;
    console.log(count);
  };
};

var counter = counterFunc();
counter(); // 1
counter(); // 2
counter(); // 3
```

`return`以下の即時関数内に、`counterFunc`のローカル変数`count`を閉じ込める。`counter`変数内に`counterFunc`を代入すると、グローバル変数`counter`が`counterFunc`を通して`count`を参照し続けるので、Glovalオブジェクトがある限り参照され続けるので値が破棄（ガベージコレクション）されず残り続ける。

# prototypeについて
オブジェクトはプロトタイプをコピーしたものを元に作成され、すべてのオブジェクトはプロトタイプを参照している。プロトタイプで作成されたメソッドはオブジェクトが継承することができる。
オブジェクト指向言語のメソッドに近く、ES6の`class`もこれを元にしている。prototypeを使うメリットは主に、メソッドを作るよりメモリ使用率が少なくなる[^4]こと。
名前はかっこいいが、わかりにくい概念ではなさそう[^5]なので使い方のみ記載。

```javascript
  Object.prototype.sum = function(arg1, arg2){
    return arg1 + arg2;
  }
  var foo = {}
  console.log(foo.sum(1,2));
```

[^4]: インスタンス生成時はプロパティやメソッド分のメモリを確保するが、prototypeだと参照だけを持つのでその分が節約になる。

[^5]: やっていくうちに難しいと感じたらまとめ直す予定です。

# 最後に
JavaScriptはふわっとしか触ってこなかったので、自分なりにまとめるのは勉強になりました。得意な方のツッコミお待ちしてます。
次は`this`とか、関数巻き上げみたいな特殊(?)なものをまとめる予定です。

2019/11/7
[続きっぽいもの]
(https://qiita.com/qeema/items/42d4458ba3ddf5d686da)書きました。

# 特に参考にしたサイトなど
- https://developer.mozilla.org/ja/docs/Web/JavaScript
- [何となくJavaScriptを書いていた人が一歩先に進むための本](https://www.amazon.co.jp/%E4%BD%95%E3%81%A8%E3%81%AA%E3%81%8FJavaScript%E3%82%92%E6%9B%B8%E3%81%84%E3%81%A6%E3%81%84%E3%81%9F%E4%BA%BA%E3%81%8C%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/B01F0N36ES)