JavaScriptで引っ掛かりがちな箇所を凝縮して解説する

# JavaScriptで引っ掛かりがちな箇所を凝縮して解説する
## オブジェクトすなわち連想配列
JavaScriptは基本型(`string`, `number`)以外のオブジェクトは全て連想配列として扱えます。
※ `string` と `String`, `number` と `Number` の違いについてコメントで指摘頂き追記しました。

```js
array = new Array(1, 2, 3)
// ええんやで
array.a = 'A'
array.a; // -> A

function func() {}
// ええんやで
func.b = 'B';
func.b; // -> B
```

## オブジェクトとしての関数
JavaScriptでは関数は `Function` 型のオブジェクトです。(まあ型の概念はないのですが)
Javaの `Consumer` のように変数に格納もできますし、関数の引数として渡すこともできます。(よくコールバックとして使われる)

```js
// 以下2つは同義
function myFunc() { console.log('Hi'); }
var myFunc = function() { console.log('Hi'); };

typeof myFunc; // -> function
myFunc.constructor === Function; // -> true
myFunc.__proto__ === Function.prototype; // -> true

var array = [];
array.push(myFunc);
array[0](); // -> Hi

function executeTwice(func) {
  func();
  func();
}
executeTwice(myFunc); // -> Hi Hi
```
## プロトタイプチェーン
全てのオブジェクトは `.__proto__` というプロパティを持っており、これは `.constructor.prototype` と同じです。(実は昔はなかった)
この `__proto__` 直下にあるプロパティは全てオブジェクトから直接アクセスできます。(コードを見たほうが早い)

```js
var obj = new Object();
Object.prototype.something = 'something';
obj.__proto__ === Object.prototype; // -> true
obj.__proto__.something; // -> something
obj.something; // -> something
obj.constructor === Object // -> true
// オマケ
Object.constructor === Function; // -> true

// やはり直接オブジェクトがもっているプロパティが優先される
({ something: 'another' }).something; // -> another
```
さて

```js
function Class() {
  this.something = 'Something';
}
// どのオブジェクトにもObject型のプロパティ prototype は必ず存在する
// よって prototype の初期化は不要
Class.prototype.hello = {
  console.log('Hello!');
};
var instance = new Class();
// これらと同義
// -> var instance = new(Class);
// -> var instance = new Class;
instance.hello(); // -> Hello!
```
を実行すると何が起こるのでしょう。

1. オブジェクトが生成されます。このオブジェクトを以降 `object` とします。
1. `object.__proto__ = Class.prototype` とする。
1. `this` を `object` として `Class` 関数が実行される。
1. `Class` の返り値があればそれを、なければ `object` を返す。
1. `instance` に代入される。

前述の `__proto__` と併せて分かることは、JavaScriptはなんちゃってクラス機構をもっているということです。
## グローバルスコープ
グローバルスコープの変数は `window` オブジェクトのプロパティとしてアクセスできます。

```js
// グローバルスコープ
var a = 'something';
a; // -> something
window.a; // -> something
var prop = 'a';
window[prop]; // -> something
this.a; // -> something
```
## `NaN` と `null` と `undefined`
* `NaN` - `Number` 型のオブジェクトとして扱われているが、数字でないことを示す。`NaN` を含む計算式の答えは必ず `NaN` になる。
* `null` - 明示的に何もないことを示すときに使う。
* `undefined` - プロパティが存在しない場合に定義されていないことを伝えるもの。

```js
(Number('1') + 2); // -> 3
Number('Oops!'); // -> NaN

var array = [1, 2, 3];
array[100]; // <- undefined
delete array[0];
array[0]; // <- undefined
```

## 参照エラー
以下の場合参照エラーが発生します。

* スコープ直下の存在しない変数を参照。
* `undefined`, `null` の存在しないプロパティを参照。

```js
var obj = {};
// これらは全部 undefined
obj.undef;

// これらは全部参照エラー
undef;
obj.undef.undef;
(function() { undef; })();

// グローバル変数が存在するかどうか確認したい場合
if (window.jQuery) {}
```

## 比較演算子
基本形(`number`, `string`)以外のオブジェクト"同士"は、ポインタで比較されます。つまり左右の変数が同じ場所に格納しているデータを指し示している場合のみ真を返します。

```js
var array1 = [1, 2, 3];
var array2 = [1, 2, 3];
var obj1 = { a: 'A' };
var obj2 = { a: 'A' };
array1 == array2; // -> false
obj1 == obj2; // -> false
obj1.a == obj2.a; // -> true
obj1 == "[object Object]"; // -> true
```

* `a == b` - 型をどちらかに統一してから比較を実行します。
* `a === b` - 型をどちらかに統一してから比較を実行します。

```js
// string は Date に変換できない
// Date は string に変換できる
new Date() == "Fri May 19 2017 23:44:07 GMT+0900 (JST)";
// つまりこれは
// (new Date()).toString() === "Fri May 19 2017 23:44:07 GMT+0900 (JST)"
// と同義

// Date と文字列の比較、つまり偽
new Date() === "Fri May 19 2017 23:44:07 GMT+0900 (JST)"; // -> false
```
## `this` について
まず、3つ例外があります。

1. グローバルスコープでの `this` は `window` を示す。
1. 関数を `new` した場合、その関数の中の `this` は `new` で生成したオブジェクト。
1. 関数内の `this` は `.call(context, ...args)`, `.apply(context, args)`, `.bind(context)` で `context` に変更できます。

ではそれ以外はというと、非常に伝え辛いのですが
ざっくり結論: `context.method()` という形で関数が呼ばれた場合は `context`、それ以外は `undefined`.

```js
var context = {
  method: function() {
    return this;
  }
};

context.method(); // <- context と同義

var something = context.method;
// ただし、これは window.something() として扱われる
something(); // <- よってこれは window と同義
```
下3行をご覧いただくと、関数を別の変数に入れて実行すると `this` の内容が変わってしまっています。
要するに `context.method` 関数で `context` を取得するために `this` を使うのは、思わぬ副作用に繋がるので良くないということですね。
## 即時関数
関数を生成して、変数に代入する間もなくその場で実行するという手法です。よく変数を隠蔽(or グローバル汚染回避)するために使われます。

```js
(function() {
  var text = 'Cannot access me outside of this function';
  console.log(text);
})()
```

## 並行処理
並"列"処理は「Web Worker」などでggってみてください。
`setTimeout` や `setInterval` を使うと簡単に並行処理を実装できます。

```js
window.setTimeout(function() {
  // 処理1
}, 10); // 0 でもいいが念の為 10

//処理2
```
## コメント欄より: リテラルと Object の違い (Thanks to @mpyw)
文字列リテラル(`string`)と文字列オブジェクト(`String`)は違うという指摘を頂きました。今まで知らなかった...。
`new String(str)` で文字列を生成するとオブジェクト扱いのようです。(`number` と `Number` も同様)

```js
"a" == "a"; // -> true 
new String("a") == new String("a"); // -> false
typeof "a" // -> string
typeof new String("a") // -> object
"a" instanceof String // -> false
new String("a") instanceof String // -> false
```
String型はオブジェクトになるので、参照渡しになります、が、文字列オブジェクトには破壊的メソッドが存在しないので、確かめる方法といえば前述した連想配列として使うことくらいですかね。

```js
objStr = new String("a");
objStr2 = objStr
objStr.a = 'A';
objStr2.a; // -> A
```

## 後書き
私が初めてJavaScriptを学んだのは小学生の頃で「[とほほのWWW入門](http://www.tohoho-web.com/www.htm)」がきっかけでした。
懐かしく思って最近見に行くとまだサイトは残っているばかりか、いつの間にかナウいコンテンツ(AngularJSなど)まで拡充していますね。