2.JavaScriptデータの種類

# null、undefined、ブール値 

>警告: 記事は機械翻訳があるため、学習メモとして保存、学習参考用のみ

## nullとundefined 

### 概要 

「null」と「undefined」はどちらも「ない」という意味で使われています。ある変数を「undefined」や「null」に代入しても、正直言って文法的な効果はほとんど変わりません。

```javascript 
var a = undefined ;
//あるいは 
var a = null ;
``` 

上記のコードでは、変数`a`はそれぞれ`undefined`と`null`として割り当てられており、この2つの効果はほぼ等価 。

`if`文では、それらは自動的に`false`に変換され、等しい演算子(`==`)でさえ、直接両者が等しいことを報告します。

```javascript 
if( !undefined) 
console.log('undefined is false');
} 
// undefined is false 

if( !null){ 
console.log('null is false');
} 
// null is false 

undefined == null 
// true 
``` 

このコードを見ると、両者の行動がいかに似ているかがわかります。グーグル社が開発したJavaScript言語の代替言語であるDart言語は、「null」のみで「undefined」はありません!

意味も使い方も似ているのに、なぜこのような値を二つ同時に設定するのかというと、複雑さが余計に増してしまい、初心者が困るのではないでしょうか。これは歴史的な理由が関係しています。

1995年にJavaScriptが誕生したとき、最初はJavaのように無を表す「null」しかありませんでした。C言語の伝統によれば、`null`は自動的に`0`に変換されます。

```javascript 
Number(null) // 0 。
5 + null // 5 
``` 

上のコードでは、`null`が数字になると、自動的に0になります。

JavaScriptの設計者Brendan Eichはそれだけでは不十分だと言いましたまずJavaScriptの最初のバージョンでは`null`はJavaのようにオブジェクトとして扱われていましたが、Brendan Eichは「無」を表す値はオブジェクトでない方が良いと考えていました。第二に、当時のJavaScriptにはエラー処理の仕組みがありませんでした。Brendan Eichは、「null」が自動的にゼロになると、エラーを発見するのが容易ではないと考えていました。

そこで彼はundefinedを作りました違いはこう 。「null」は「空」を表す対象で、数値になると「0」になります。「undefined」は「ここでは定義されていない」を表す元の値で、数値に変換すると「NaN」となります。

```javascript 
Number(undefined) // NaN 
5 + undefined // NaN 
``` 

### 使い方と意味 

「null」と「undefined」については、次のように理解することができます。

`null`は空の値を表します。つまり、ここでの値は空 。関数を呼び出したとき、あるパラメータが何の値も設定されていない場合、`null`を入力し、そのパラメータが空であることを示します。例えば、ある関数がエンジンから出されたエラーを引数として受け取り、実行中にエラーが発生しなければ、その引数が`null`と入ってきて、エラーが発生していないことを示します。

「undefined」は「未定義」を意味します。以下は「undefined」に戻る典型的な場面 。

```javascript 
変数は宣言されていますが、代入はありません。
var i ;
i // undefined 

//関数を呼び出したとき、提供すべきパラメータが提供されていません。
function f(x){ 
return x ;
} 
f() // undefined 

//オブジェクトには値付けの属性がありません。
var o = new Object() ;
o.p // undefined 

//関数の戻り値がない場合、デフォルトでundefinedを返します。
function f(){} 
f() // undefined 
``` 

## ブール値 

ブール値は「true」と「false」の2つの状態を表します。「true」を「true」、「false」を「false」というキーワードで表します。ブール値はこの2つだけ 

次の演算子はブール値を返します。

-前置論理演算子:` !`(ノット )
-等しい演算子:`===`,` !==`, `, ` != `
-比較演算子 :`>`,`>=`,`<`,`<=`

JavaScriptはある位置がブール値であることを予期している場合、その位置にある値を自動的にブール値に変換します。変換規則では次の6つの値を除いて`false`に変換されます。

- ' undefined ' 
- `null 
- `false 
- 0 
- `NaN 
- `""`または`''`(空文字列) 

ブル値はプログラムフローの制御によく使われますが、一例を見てみましょう。

```javascript 
if(''){ 
console.log('true');
} 
出力はありません
``` 

上のコードでは、`if`コマンドの後の判定条件はブール値になると予想されているので、JavaScriptは自働的に空の文字列をブール値`false`に変換します。

なお、空の配列(`[]`)と空のオブジェクト(`{}`)に対応するブール値は、どちらも`true` 。

```javascript 
if([]){ 
console.log('true');
} 
// true 

if({}){ 
console.log('true');
} 
// true 
``` 

データタイプ変換についての詳細は、データタイプ変換の章を参照してください。

## リンク参照 

−アクセルrauschmayer、[categorizing values in javascript] (http://www.2ality.com/2013/01/categorizing-values.html)

# 数値 

## 概要 

### 整数と浮動小数点数 

JavaScriptの内部には、すべての数字が64ビットの浮動小数点数として保存されています。 から、`1`は`1.0`と同じ数 。

```javascript 
1 === 1.0 // true 
``` 

つまりJavaScript言語の基本には整数は存在せず、すべての数字は小数(浮動小数点数64ビット) 。紛らわしいことに、いくつかの演算は整数でしかできません。この場合、JavaScriptは自動的に64ビットの浮動小数点を32ビットの整数に変換して演算を行います。

浮動小数点数は正確な値ではないので、小数の比較や演算には注意が必要 。

```javascript 
0.1 + 0.2 。
// false 

0.3 / 0.1 
// 2.99999999999996 

(0.3 - 0.2) ===(0.2 - 0.1) 。
// false 
``` 

### 数値精度 

国際標準IEEE 754によると、JavaScriptの浮動小数点数の64バイナリビットは、左端から、このように構成されています。

−1位:記号のビット,`0`は正数,`1`は負数を表します
- 2位から12位まで(全11位):指数部門 
- 13位から64位まで(全部で52桁):小数部分(つまり有効数字 )

符号ビットは数の正負を、指数部は数の大きさを、小数部は数の精度を決定します。

指数部には11個のバイナリビットがあり、0から2047までの範囲があります。IEEE 754では、指数部の値が0から2047(2つの端点を含まない)の場合、有効数字の1桁目はデフォルトで常に1であり、64ビット浮動小数点数には格納されません。つまり,有効数字はこのとき常に`1.xx…xx`の形で、ここで`xx.. 。xx`の部分は64ビットの浮動小数点数に格納され、最長で52ビットになります。そのため、JavaScriptの有効数字は最長53バイナリビット 。

``` 
(-1)^符号位置* 1.xx …xx * 2^指数部分 
``` 

上記の式は通常の場合(指数は0から2047の間)であり、JavaScript内での数の表現 。

つまり、絶対値が2の53乗以下の整数、つまり-2<sup>53</sup> + 1から2<sup>53</sup> - 1であれば正確に表現できます。

```javascript 
math.pow(2, 53) 
// 9007199254740992 

math.pow(2, 53) + 1 
// 9007199254740992 

math.pow(2, 53) + 2 
// 9007199254740994 

math.pow(2, 53) + 3 
// 9007199254740996 

math.pow(2, 53) + 4 
// 9007199254740996 
``` 

上のコードでは、2の53乗より大きくなると、整数演算の結果にエラーが発生し始めます。 から、2の53乗より大きい値は、精度を保つことができません。2の53乗は16桁の10進数なのでJavaScriptは15桁の10進数を正確に処理できます

```javascript 
math.pow(2, 53) 
// 9007199254740992 

//最後３つの数字、保存できません。
9007199254740992111
// 9007199254740992000 
``` 

上の例では、2を53乗以上にすると、余った有効数字(最後の3桁の`111`)は0になってしまいます。

### 数値範囲 

標準によれば、64ビット浮動小数点数の指数部の長さは11バイナリビットであり、指数部の最大値は2047(2の11乗から1を引く)であることを意味します。つまり、64ビットの浮動小数点数の指数部の値は最大2047で、半分を割って負の数を表すと、JavaScriptで表現できる数値の範囲は2<sup>1024</sup>から2<sup>-1023</sup>(開区間)となり、それ以上の数は表現できません。

2の1024乗以上の数があると「順方向オーバーフロー」が発生します。JavaScriptではその数を表すことができず、「Infinity」に戻ります。

```javascript 
math.pow(2,1024)// Infinity 。
``` 

2のマイナス1075乗(指数部の最小値であるマイナス1023と小数部の52桁)以下の数は、JavaScriptでは表現できない「負のオーバーフロー」となり、そのまま0を返すことになります。

```javascript 
math.pow(2, -1075) // 0 。
``` 

これは実際の例 

```javascript 
var x = 0.5 ;

for(var i = 0 ;i < 25 ;i++){ 
x = x * x ;
} 

x // 0 
``` 

上のコードでは、`0.5`を25回二乗すると、0に近づきすぎて表現可能な範囲を超えてしまうので、JavaScriptではそのまま0にします。

JavaScriptは`Number`オブジェクトの`MAX_VALUE`と`MIN_VALUE`属性を提供し、具体的に表すことができる最大値と最小値を返します。

```javascript 
Number.MAX_VALUE // 1.7976931348623157e+308 。
Number.MIN_VALUE // 5e-324 。
``` 

## 数値の表記法 

JavaScriptの数値にはいくつかの表現方法があり、例えば`35`(十進数)や`0xFF`(十六進数)のように文字通り表現することができます。

数値も科学的スコアリングルールで表すことができます。ここでは科学的スコアリングルールの例をいくつか紹介します。

```javascript 
123e3 // 123000 
123e-3 // 0.123 。
-3.1E+12 
.1e-23 
``` 

科学スコアリングルールでは、アルファベットの`e`または`e`の後に、その数値の指数を表す整数が続くことが許されています。

次の2つの場合は、JavaScriptが自動的に数値を科学的なスコアリング法で表現してくれますが、それ以外の場合は文字通り表現してくれます。

**(1)は小数点以下21桁以上の数字 。** 

```javascript 
1234567890123456789012
// 1.2345678901234568e+21

123456789012345678901
// 123456789012345680000 
``` 

**(2)小数点以下の0が5つ以上あります。** 

```javascript 
//小数点以下5箇以上のゼロにくっついています。
//は自動的に科学スコアリングルールになります。
0.0000003 // 3e-7 

//でなければ,字面のまま 
0.000003 // 0.000003 
``` 

## 数値の進数 

リテラルを使って直接数値を表現する場合、JavaScriptは整数を10進数、16進数、8進数、2進数の4つの進数で表現します。

-十進法:0のプリアンブルがありません。
-八進数:' 0o 'または' 0o 'の接頭辞を持つ数値、または' 0 'のプリアンブルを持ち、0-7までの8つのアラビア数字だけの数値 。
-十六進数:接頭辞`0x`または`0x`を持つ数 。
-二進法:接頭辞`0b`または`0b`の値があります。

デフォルトでは、JavaScript内部で8進数、16進数、2進数を自動的に10進数に変換します。いくつか例をご紹介します。

```javascript 
0xff // 255 
0o377 // 255 
0b11 // 3 
``` 

八進数、十六進数、二進数のうち、該当しない数字が出てくると間違えます。

```javascript 
0xzz //報錯
0o88 //エラー 
0b22 //エラー 
``` 

上のコードでは、16進数ではアルファベット`z`、8進数では数字`8`、2進数では数字`2`が現れるためエラーとなります。

通常、0が先行すると8進数とみなされますが、0の後に`8`と`9`が付くと10進数とみなされます。

```javascript 
0888 // 888 
0777 // 511 
``` 

プリアンブルの0は8進数を表しているため、扱いが混乱しがち 。ES5のシビアモードやES6では、この表記法は廃止されていますが、ブラウザでは従来のコードとの互換性のため、現在もこの表記法をサポートしています。

## 特殊数値 

JavaScriptにはいくつかの特別な数値があります。

### プラスゼロとマイナスゼロ 

前述しましたが、JavaScriptの浮動小数点数64ビットの中に、2進数ビットが記号ビット 。これは、任意の数に対応する負の値があることを意味し、`0`でさえ例外ではありません。

JavaScriptの内部には2つの`0`が存在します。1つは`+0`、もう1つは`-0` 。それらは等価 。

```javascript 
-0 === +0 // true 
0 === -0 // true 
0 === +0 // true 
``` 

ほとんどの場合、正のゼロと負のゼロが正常な`0`として扱われます。

```javascript 
+0 // 0 
0 // 0 
(-0).toString() // '0' 
(+0).toString() // '0' 
``` 

唯一違いがあるのは、`+0`か`-0`を分母とすると、返される値が等しくない場合 。

```javascript 
(1 / +0) === (1 / -0) // false 
``` 

このような結果になるのは、正の0で割ると`+Infinity`、負の0で割ると`-Infinity`となり、両者は等しくないから (Infinityについては後述)。

### NaN 

**(1)意味** 

「NaN」はJavaScriptの特殊な値で、「Not a Number」を意味します。主に文字列を数字の誤りに解析する場合に使われます。

```javascript 
5 - 'x' // NaN 
``` 

上記のコードが実行されると、文字列`x`は自動的に数値に変換されますが、`x`は数値ではないため、最終的に`NaN`となり、非数値(`NaN`)であることを示します。

また、いくつかの数学的な関数の演算結果に「NaN」が現れます。

```javascript 
math.acos (2) // NaN 
math.log (-1) // NaN 
math.sqrt (-1) // NaN 
``` 

`0`を`0`で割っても`NaN`になります。

```javascript 
0/0 // NaN
``` 

なお、`NaN`は独立したデータ型ではなく、特殊な数値であり、そのデータ型は依然として`Number`に属しており、`typeof`演算子を使ってはっきりと見ることができます。

```javascript 
typeof NaN // 'number' 
``` 

**(2)演算規則** 。

`NaN`はそれ自身を含め、いかなる値にも等しくありません。

```javascript 
NaN === NaN // false
``` 

配列の`indexOf`法は内部的に厳密な等価演算子を使用しているので、この法は`NaN`に対しては成立しません。

```javascript 
[NaN].indexOf(NaN) // -1 。
``` 

`NaN`はブール演算では`false`とされます。

```javascript 
Boolean(NaN) // false 
``` 

' NaN 'と(それ自身を含む)任意の数を計算すれば' NaN 'が得られます。
```javascript 
NaN + 32 // NaN 
nan-32 // NaN 
NaN * 32 // NaN 
NaN / 32 // NaN 
``` 

### Infinity 

**(1)意味** 

「Infinity」は「無限」という意味で、2種類のシーンを表します。1つは正の値が大きすぎて、あるいは負の値が小さすぎて、表すことができません;もう一つは0でない値を0で割ると「Infinity」になります。

```javascript 
//シーン1
math.pow(2,1024) 
インフィニティ //

シーン2 
0/0 // NaN
1/0 // Infinity 
``` 

上のコードでは、最初のシーンは1つの式の計算結果が大きすぎて、表現できる範囲を超えてしまったので、`Infinity`を返します。2つ目のシーンは、0を0で割るとNaNになり、0で割るとInfinityに戻ります。

Infinityは正負の区別があって、Infinityは正の無限を表し、-Infinityは負の無限を表します。

```javascript 
Infinity === -Infinity // false

1 / -0 // -Infinity 
-1 / -0 // Infinity 
``` 

上のコードでは、ゼロでない正の数を−0で割ると−Infinityになり、負の数を−0で割るとInfinityになります。

JavaScriptはオーバーフロー(overflow)、アンダーフロー(underflow)、0で割り切れてもエラーを返さないため、単純な計算でエラーを返すことはほとんどありません。

' Infinity 'は(' NaN 'を除く)すべての値より大きく、' -Infinity 'は(' NaN 'を除く)すべての値より小さい 。

```javascript 
Infinity > 1000 // true 
-Infinity < -1000 // true 
``` 

「Infinity」は「NaN」と比べて、いつも「false」を返します。

```javascript 
Infinity > NaN // false 
-Infinity > // false

Infinity < NaN // false > 。
-Infinity < NaN // false > 
``` 

**(2)演算規則** 。

「Infinity」の四則演算は無限の数学的計算規則に合っています。

```javascript 
5 * Infinity // Infinity
5 -Infinity // -Infinity 
Infinity / 5 // Infinity 
5 / Infinity // 0 
``` 

0に「Infinity」をかけると、「NaN」に戻ります。0をInfinityで割ると、0が戻ります。「Infinity」を0で割ると、「Infinity」に戻ります。

```javascript 
0 * Infinity // NaN 
0 / Infinity // 0 
Infinity / 0 // Infinity 
``` 

「Infinity」に「Infinity」を足したり掛けたりしても、また「Infinity」が返ってきます。

```javascript 
Infinity + Infinity // Infinity 
Infinity * // Infinity 
``` 

Infinityを引いたり、Infinityで割ったりすると、NaNになります。

```javascript 
Infinity - Infinity // NaN 
Infinity / Infinity // NaN 
``` 

「Infinity」と「null」を計算すると、「null」は0になります。「0」と計算するのと同じ 。

```javascript 
null * Infinity // NaN 
null / Infinity // 0 
Infinity / null / Infinity 
``` 

「Infinity」と「undefined」で計算すると、返ってくるのは「NaN」 。

```javascript 
undefined + Infinity // NaN 
undefined-infinity // NaN 
undefined * Infinity // NaN 
undefined / Infinity // NaN 
Infinity / undefined // NaN 
``` 

数値に関するグローバルなアプローチ 

### parseInt( )

**(1)基本的な使い方** 

parseInt法は文字列を整数に変換するのに使われます。

```javascript 
parseInt('123') // 123 
``` 

文字列の先頭にスペースがある場合、そのスペースは自動的に削除されます。

```javascript 
parseInt(' 81') // 81 
``` 

「parseInt」の引数が文字列でない場合は、いったん文字列に変換してから変換します。

```javascript 
parseInt(1.23) // 1 。
//に等しい 
parseInt('1.23') // 1 
``` 

文字列が整数に変換されるときは、1文字ずつ順番に変換されますが、数字に変換できない文字に出会うと、それ以上は進みません。

```javascript 
parseInt('8a') // 8 
parseInt('12**') // 12 
parseInt('12.34') // 12 
parseInt('15e2') // 15 
parseInt('15px') // 15 
``` 

上記のコードでは、`parseInt`の引数はすべて文字列なので、文字列の先頭が数字に変換できる部分だけを返します。

文字列の最初の文字が数字に変換できない場合(数字に続く記号は除く)は`NaN`を返します。

```javascript 
parseInt('abc') // NaN 
parseInt('.3') // NaN 
parseInt('') // NaN 
parseInt('+') // NaN 
parseInt('+1') // 1 
``` 

よって`parseInt`の戻り値は10進数の整数か`NaN`の2つしかありません

文字列が' 0x 'や' 0x 'で始まる場合、' parseInt 'はそれを16進数で解きます。

```javascript 
parseInt('0x10') // 16 
``` 

文字列が`0`で始まる場合は、それを10進数で解きます。

```javascript 
parseInt('011') // 11 
``` 

自動的に科学的スコアリングに変換される数字に対して、parseIntは科学的スコアリングの表現方法を文字列として扱うため、おかしな結果をもたらします。

```javascript 
parseInt(1000000000000000000000.5) // 1 。
//に等しい 
parseInt('1e+21') // 1 

parseInt(0.0000008) // 8 。
//に等しい 
parseInt('8e-7') // 8 
``` 

**(2)進変換** 。

`parseInt`メソッドはまた、2つ目のパラメータ(2から36の間)を受け入れ、解析された値の進数を表し、その値に対応する10進数を返します。デフォルトでは、`parseInt`の2つ目の引数は10 。デフォルトでは、10進から10進 。

```javascript 
parseInt('1000') // 1000 
//に等しい 
parseInt('1000', 10) // 1000 
``` 

次は進数を指定する数を変換する例 。

```javascript 
parseInt('1000', 2) // 8 
parseInt('1000', 6) // 216 
parseInt('1000', 8) // 512 
``` 

上のコードでは、二進法、六進法、八進法の`1000`は、それぞれ、十進法の8、216、512に等しい 。これは、「parseInt」の方法で進数の変換ができることを意味します。

2つ目の引数が数値でない場合は、自動的に整数に変換されます。この整数は2から36の間でなければ意味のある結果を得られず、それ以上であれば`NaN`を返します。2つ目の引数が`0`、`undefined`、` null`の場合は無視します。

```javascript 
parseInt('10', 37) // NaN 
parseInt('10', 1) // NaN 
parseInt('10', 0) // 10 
parseInt('10', null) // 10 
parseInt('10', undefined) // 10 
``` 

進数の指定に意味のない文字を含む文字列の場合は、最上位ビットから変換可能な数値のみを返します。最高位が変換できない場合は、そのまま`NaN`を返します。

```javascript 
parseInt('1546', 2) // 1
parseInt('546', 2) // NaN 
``` 

バイナリでは`1`は意味のある文字で`5`、`4`、`6`は無意味な文字なので1行目は1、2行目は`NaN`を返します

前述したように、`parseInt`の1つ目の引数が文字列でない場合は、先に文字列に変換されます。これは意外な結果をもたらします

```javascript 
parseInt(0 x11,36) // 43 。
parseInt(0 x11,2) // 1 。

//に等しい 
parseInt(String(0x11), 36) 
parseInt(String(0x11), 2) 

//に等しい 
parseInt('17', 36) 
parseInt('17', 2) 
``` 

上のコードでは、16進数の0x11を17に変換してから文字列に変換します。そして、文字列`17`を36進数や2進数で解読し、結果`43`と`1`を返します。

この処理は、8進数のプレフィックスである0については、特に注意が必要 。

```javascript 
parseInt(011, 2) // NaN 

//に等しい 
parseInt(String(011), 2) 

//に等しい 
parseInt(String(9), 2)
``` 

上のコードでは1行目の`011`が最初に文字列`9`に変換されます。`9`はバイナリの有効文字ではないので`NaN`を返します。parseInt('011', 2)`を直接計算すると、'011'は2進数として扱われ、3が返されます。

JavaScriptでは「0」というプレフィックスが付いた数字を8進数として扱うことができなくなり、「0」を無視する必要があります。しかし、互換性を保つために、ほとんどのブラウザにはこのような規定がありません。

### parseFloat( )

parseFloat法は文字列を浮動小数点数に変換する方法 。

```javascript 
parseFloat('3.14') // 3.14 
``` 

文字列が科学的スコアリングルールに従っていれば、それに応じた変換が行われます。

```javascript 
parseFloat(' 14e-2') // 3.14 
parseFloat('0.0314E+2') // 3.14 
``` 

浮動小数点に変換できない文字が文字列に含まれている場合は、後戻りはせず、すでに変換された部分に戻ります。

```javascript 
parseFloat('3.14more non-digit characters') // 3.14 
``` 

' parseFloat 'メソッドは、文字列プリアンブルのフレームを自動的にフィルタリングします。

```javascript 
parseFloat('\t\v\r12.34\n ') // 12.34
``` 

引数が文字列でない場合は、文字列に変換してから変換します。

```javascript 
parseFloat([1.23]) // 1.23 。
//に等しい 
parseFloat(String([1.23])) // 1.23 。
``` 

文字列の最初の文字が浮動小数点数に変換できない場合は`NaN`を返します。

```javascript 
parseFloat([]) // NaN 
parseFloat('FF2') // NaN 
parseFloat('') // NaN 
``` 

上記のコードの中でも特に注目すべきは`parseFloat 'が空文字列を`NaN 'に変換すること 

これらの特徴により、parseFloatの変換結果はNumber関数とは異なります。

```javascript 
parseFloat(true) // NaN 
Number(true) // 1 

parseFloat(null) // NaN 
Number(null) // 0 。

parseFloat('') // NaN 
Number('') // 0 

parseFloat('123.45#') // 123.45 
Number('123.45#') // NaN 
``` 

### isNaN( )

`isNaN手法は、ある値が`NaN`であるかどうかを判定するのに使われます。

```javascript 
isNaN(NaN) // true 
falseさん(123)// false 
``` 

ただし、「isNaN」は数値に対してのみ有効で、他の値が入ってくると先に数値に変換されてしまいます。例えば、文字列が入ってきたときに、文字列が先に「NaN」に変換され、最後に「true」が返ってくるので要注意 。つまり、' isNaN 'は' true 'の値であり、' NaN 'ではなく文字列である可能性があります。

```javascript 
isNaN('Hello') // true 
相当します
isNaN(Number('Hello')) // true 
``` 

同様にオブジェクトと配列に対しても`isNaN`は' true 'を返します。

```javascript 
({}) // true 
//に等しい 
isNaN(Number({})) // true 

isNaN(['xzy']) // true 
//に等しい 
isNaN(Number(['xzy'])) // true 
``` 

ただし、空の配列や数値メンバが1つしかない配列に対しては、`isNaN`は`false`を返します。

```javascript 
([]) // false 
([123]) // false 
(['123']) // false 
``` 

上記のコードが`false`を返す理由は、これらの配列がNumber関数によって数値に変換できるから 。「データタイプ変換」の章を参照してください。

 から、「isNaN」を使う前に、データタイプを判断しておくとよいでしょう。

```javascript 
function myIsNaN(value){ 
return typeof value === 'number' && isNaN(value);
} 
``` 

より確実に「NaN」を判断する方法は、「NaN」が自分と等しくない唯一の値であることを利用して判断すること 。

```javascript 
function myIsNaN(value){ 
return value !value ;
} 
``` 

### isFinite( )

`isFinite`メソッドは、ある値が正常な値であるかどうかを示すブール値を返します。

```javascript 
isFinite(インフィニティ)// false 
isFinite(-Infinity) // false 
isFinite(NaN) // false 
isFinite(undefined) // false 
isFinite(null) // true 
isFinite(-1) // true 
``` 

' Infinity '、' -Infinity '、' NaN '、' undefined 'は' false 'を返しますが、' isFinite 'は' true 'を返します。

## リンク参照 

- dr .アクセルrauschmayer、[how numbers are encoded in javascript] (http://www.2ality.com/2012/04/number-encoding.html)
−humphry、[/ javascriptでnumberの一部は下限](https://segmentfault.com/a/1190000000407658)

# 文字列 

## 概要 

定義します

文字列とは、1つもしくは2つの括弧の中に0個以上の文字が並んだもの 。

```javascript 
'abc'
"abc"
``` 

1つの括弧文字列の中には、2つの括弧を使うことができます。2つの括弧文字列の中には、1つの括弧を使うことができます。

```javascript 
'key = "value"'
"It's a long journey"
``` 

どちらも正当な文字列 

単括弧文字列の内部に単括弧を使う場合は、内部の単括弧の前に逆スラッシュをつけてエスケープする必要があります。括弧文字列の中に括弧を入れる場合も同じ 。

```javascript 
'Did she say \'Hello\'?'
// "Did she say 'Hello'?"

"Did she say \"Hello\"?"
// "Did she say "Hello"?"
``` 

HTML言語の属性値は二重引用符を使用しているため、JavaScript言語の文字列は一重引用符のみを使用することを約束している項目が多くあります。もちろん、カギカッコだけでも十分 。重要なのは、文字列を1つのカギカッコで表現したり、2つのカギカッコで表現したりしないスタイルにこだわること 。

文字列はデフォルトで1行までしか書けないので、複数行に分けるとエラーが発生します。

```javascript 
'a
b
c'
// SyntaxError: Unexpected token ILLEGAL
``` 

文字列を3行に分割したコードでJavaScriptがエラーを起こします

長い文字列を複数の行に分割しなければならない場合は、行の末尾にフリップを使います。

```javascript 
var longString = 'Long \
long \
long \
string';

longString
// "Long long long string"
``` 

このコードは、フリップをつけることで、1行に書かれていた文字列を複数の行に分けて書くことができることを示しています。ただし、アウトプットするときは単行行のままなので、同じ一行に書いたのと同じことになります。他の文字(スペースなど)が入っていてはいけません。そうしないとエラーが発生します。

連接演算子(`+`)は、複数の文字列を連接することができます。長い文字列を複数行に分割して書くと、出力するときも連接します。

```javascript 
var longString = 'Long ' 
+ 'long ' 
+ 'long ' 
+ 'string' ;
``` 

複数行の文字列を出力したい場合、複数行の注釈を利用する変則的な方法があります。

```javascript 
(function () { /*
line 1
line 2
line 3
*/}).toString().split('\n').slice(1, -1).join('\n')
// "line 1
// line 2
// line 3"
``` 

先の例では、出力される文字列は複数行 。

### 変換標識

\は文字列内に特殊な意味を持ち、特殊な文字を表すため、エスケープとも呼ばれます。

逆スジで表現する特殊な文字には、次のようなものがあります。

- `\0`: null (`\u0000`) 。
- `\b`:バックキー(`\u0008`) 。
- `\f`:ページ替え(`\u000C`) 。
- `\n`:改行(`\u000A`) 。
- `\r`:エンターキー(`\u000D`) 
- `\t`:表を作ります(`\u0009`)
- `\v`:垂直タブ(`\u000B`) 。
- `\'`:カギカッコ(`\u0027`) 。
- `\"`:カギカッコ(`\u0022`) 。
- `\\`:逆斜棒(`\u005C`) 。

これらの文字の前に斜めの棒がついているのは、特別な意味を表しています。

```javascript 
console.log('1\n2')
// 1
// 2
``` 

上のコードでは、`\n`は改行を表していますが、出力時に2行に分かれています。

フリップには、3つの特殊な使い方があります。

(1) `\HHH` 

3つの八進数(`000`から`377`)が続くことで文字を表します`HHH`はUnicodeの符号点に対応します例えば`\251`は著作権記号を表しますこの方法では256文字しか出力できません

(2) `\xHH` 

`\x`は16進数(`00`から`FF`)が2つ続き、1文字を表します。`HH`は、例えば`\xA9`のようなUnicodeの符号点に対応して著作権記号を表します。この方法では256文字しか出力できません

(3) `\uXXXX` 

' \u 'の後に続く4つの16進数(' 0000 'から' FFFF ')は文字を表します。`XXXX`対応文字のUnicode符号点、例えば`\u00A9`は著作権記号を表します。

3つの特殊な文字の例を紹介します

```javascript 
'\251' // "©"
'\xA9' // "©"
'\u00A9' // "©"

'\172' === 'z' // true
'\x7A' === 'z' // true
'\u007A' === 'z' // true
``` 

特殊でない文字の前に逆スラッシュを使うと、逆スラッシュが省略されます。

```javascript 
'\a'
// "a"
``` 

上記のコードでは、`a`は通常の文字であり、前にフリップをつけることは特に意味がなく、自動的に省略されます。

文字列の通常の内容の中に逆スラッシュを含める必要がある場合、その前にもう1つの逆スラッシュを追加して、自分自身をエスケープする必要があります。

```javascript 
"Prev \\ Next"
// "Prev \ Next"
``` 

### 文字列と配列 

文字列は文字配列として扱うことができるので、配列の括弧演算子を使ってある位置の文字(位置番号は0から)を返すことができます。

```javascript 
var s = 'hello' ;
s[0] // "h" 
s[1] // "e" 
s[4] // "o" 

//文字列に直接括弧演算子を使います。
'hello'[1] // "e" 
``` 

括弧内の数字が文字列の長さを超えていたり、括弧内がまったく数字でない場合は「undefined」を返します。

```javascript 
'abc'[3] // undefined 
'abc'[-1] // undefined 
'abc'['x'] // undefined
``` 

しかし、文字列と配列の類似性はそれだけ 。実際には、文字列の中の一つの文字を変えることはできません。

```javascript 
var s = 'hello';

delete s[0];
s // "hello"

s[1] = 'a';
s // "hello"

s[5] = '!';
s // "hello"
``` 

上記のコードは、文字列内の1文字を変更したり削除したりすることはできず、これらの操作は黙々と失敗することを示しています。

### length属性 

`length`属性は文字列の長さを返します。この属性も変更できません。

```javascript 
var s = 'hello';
s.length // 5

s.length = 3;
s.length // 5

s.length = 7;
s.length // 5
``` 

上のコードは文字列の`length`属性は変更できませんが、エラーは発生しません。

## 文字セット 

JavaScriptはUnicode文字セットを使用します。JavaScriptエンジン内では、すべての文字がUnicodeで表記されています。

JavaScriptはUnicodeで文字を保存するだけでなく、プログラム内で直接Unicodeの符号点を使用して文字を表現することができます。例えば`\u00A9`は著作権記号 

```javascript 
var s = '\u00A9';
s // "©"
``` 

コードを解析するとき、JavaScriptはその文字がリテラル形式なのかUnicode形式なのかを自動的に認識します。ユーザーに出力すると、すべての文字がリテラルに変換されます。

```javascript 
var f\u006F\u006F = 'abc';
foo // "abc"
``` 

上のコードでは、1行目の変数名「foo」がUnicode形式表現で、2行目がリテラル形式表現 。JavaScriptが自動的に認識します

各文字はJavaScript内部で16ビット(2バイト)のutf-16形式で保存されていることも知っておく必要があります。つまりJavaScriptの単位文字長は16ビット、つまり2バイトで固定されています。

しかし、utf-16には2種類の長さがあります:符号点が' U+0000 'から' U+FFFF 'の間の文字の長さは16ビット(2バイト) 。符号点が`U+10000`から`U+10FFFF`の間の文字の場合、長さは32ビット(4バイト)であり、最初の2バイトは`0xD800`から`0xDBFF`の間であり、後の2バイトは`0xDC00`から`0xDFFF`の間である。例えば、ヤード時` u + 1 d306対応の文字を` `𝌆、`それ书いutf—16が` xd834 xdf06 `。

JavaScriptのutf-16のサポートは不完全であり、歴史的な理由から2バイトの文字しかサポートしておらず、4バイトの文字には対応していません。これは、JavaScriptの最初のバージョンがリリースされたとき、Unicodeのコードポイントは`U+FFFF`にしか割り当てられていなかったため、2バイトで十分だったから 。その後、Unicodeに含まれる文字はますます増え、4バイトの符号化が登場した。しかし、JavaScriptの標準はこの時点 でに固まっており、文字の長さを2バイトに統一していたため、4バイトの文字を認識することができなかった。そのバイト4文字で1クォーターの`𝌆`、ブラウザーが正確な認識である文字、しかしjavascript識別できない、これは二つの文字。

```javascript 
'𝌆'.length // 2
``` 

と上のコードのうち、javascript `𝌆`の长さを2ではなく1。

まとめると、JavaScriptは符号点が' U+10000 'から' U+10FFFF 'の間の文字を2文字(' length 'プロパティ2)と見なします。この点を考慮して処理しなければなりません。つまり、JavaScriptが返す文字列の長さが正しくない可能性があります。

## Base64トランスコード 

テキストの中に印刷できない記号が含まれている場合があります。ASCIIコードの0から31までの記号が印刷できない場合は、Base64コードを使って印刷できる文字に変換します。別の場面では、バイナリデータをテキスト形式で渡す必要がある場合には、Base64でエンコードすることもできます。

Base64とは,任意の値を0 ~ 9,A ~ Z, a-z, `+`, `/`の64文字からなる印刷可能な文字に変換できる符号化方法 。主な目的は、暗号化ではなく、特殊な文字が出ないようにすること、プログラムの処理を簡単にすること 。

JavaScriptネイティブはBase64に関連する2つの手法を提供しています。

- `btoa()`:任意の値をBase64に変換します
- `atob()`: Base64コードを元の値に変換します。

```javascript 
var string = 'Hello World!' ;
btoa(string) // "SGVsbG8gV29ybGQh" 
atob('SGVsbG8gV29ybGQh') // "Hello World!"
``` 

なお、これら2つの方法は非ASCIIコードの文字には適しておらず、エラーが発生します。

```javascript 
btoa('こんにちは')//報錯
``` 

非ASCII文字をBase64に変換するには、トランスコードのプロセスを間に挿入し、この2つの方法を使います。

```javascript 
function b64Encode(str){ 
return btoa(encodeURIComponent(str)) 。
} 

function b64Decode(str){ 
return decodeURIComponent(atob(str));
} 

// "JUU0JUJEJUEwJUU1JUE1JUJE"
b64Decode('JUU0JUJEJUEwJUU1JUE1JUJE') // "こんにちは"
``` 

## リンク参照 

- Mathias Bynens, [JavaScript」s internal character encoding: ucs-2 or utf-16 か?](http://mathiasbynens.be/notes/javascript-encoding)
−mathias bynens、[aフリーproblem javascript has] (http://mathiasbynens.be/notes/javascript-unicode)
−mozilla developerネットワーク、[window . btoa] (https://developer.mozilla.org/en-us/docs/web/api/window.btoa)

# 対象 

## 概要 

### 生成方法 

オブジェクト(object)はJavaScript言語の中心概念であり、最も重要なデータ型 。

対象とは何 か?簡単に言うと、オブジェクトは「キーと値のペア」の集合であり、でたらめな複合データの集合 。

```javascript 
var obj = {
  foo: 'Hello',
  bar: 'World'
};
``` 

上のコードでは括弧がオブジェクトを定義し変数objに値を与えます変数objはオブジェクトを指しますこのオブジェクトには2つのキー値ペア(2つの「メンバ」とも呼ばれます)が含まれており、1つ目のキー値ペアは`foo: 'Hello'`で、`foo`は「キー名」(メンバの名前)、文字列`Hello`は「キー値」(メンバの値) 。キー名とキー値はコロンで区切ります。2つ目のキー値ペアは`bar: 'World'`で、`bar`はキー名、`World`はキー値 。2つのキー値ペアはコンマで区切られています。

### キー名 

オブジェクトのキー名はすべて文字列 (ES6ではSymbol値もキー名として使えるようになりました)ので、カギカッコをつけてもつけなくても構いません。上のコードは次のようにも書けます。

```javascript 
var obj = {
  'foo': 'Hello',
  'bar': 'World'
};
``` 

キー名が数値の場合は、自動的に文字列に変換されます。

```javascript 
var obj = {
  1: 'a',
  3.2: 'b',
  1e2: true,
  1e-2: true,
  .234: true,
  0xFF: true
};

obj
// Object {
//   1: "a",
//   3.2: "b",
//   100: true,
//   0.01: true,
//   0.234: true,
//   255: true
// }

obj['100'] // true
``` 

上のコードでは、オブジェクト「obj」のすべてのキー名が数値のように見えますが、実は自動的に文字列に変換されています。

キー名が名前を識別する条件を満たしておらず(1文字目が数字だったり、スペースや演算子が含まれていたり)、数字でもない場合は、カギカッコを入れないとエラーが発生します。

```javascript 
// error
var obj = {
  1p: 'Hello World'
};

// not error
var obj = {
  '1p': 'Hello World',
  'h w': 'Hello World',
  'p+q': 'Hello World'
};
``` 

上のオブジェクトの3つのキー名は、いずれも名前の条件を満たしていないので、カギカッコをつける必要があります。

オブジェクトの各キー名はプロパティ(property)とも呼ばれ、そのキー値はどのようなデータ型でもよいの 。ある属性の値が関数の場合、その属性は一般に「メソッド」と呼ばれ、関数のように呼び出すことができます。

```javascript 
var obj = {
  p: function (x) {
    return 2 * x;
  }
};

obj.p(1) // 2
``` 

オブジェクト`obj`の属性`p`は関数を指しています

属性の値がオブジェクトのままの場合はリンク参照となります。

```javascript 
var o1 = {};
var o2 = { bar: 'hello' };

o1.foo = o2;
o1.foo.bar // "hello"
``` 

上のコードでは、オブジェクト`o1`の属性`foo`がオブジェクト`o2`を指しているので、`o2`の属性を連鎖的に参照することができます。

オブジェクトの属性間はコンマで区切られており、最後の属性の後にはtrailing commaを付けても、付けなくても構いません。

```javascript 
var obj = {
  p: 123,
  m: function () { ... },
}
``` 

上のコードでは`m`属性の後のコンマはあってもなくても構いません

プロパティは動的に作成でき、オブジェクト宣言時に指定する必要はありません。

```javascript 
var obj = {};
obj.foo = 123;
obj.foo // 123
``` 

上記のコードでは、objオブジェクトのfoo属性に直接値を付けると、実行時にfoo属性が生成されます。

### 対象の引用 

異なる変数名が同じオブジェクトを指している場合、それらはすべてそのオブジェクトへの参照、つまり同じメモリアドレスを指しています。1つの変数を修正すると、他のすべての変数に影響を与えます。

```javascript 
var o1 = {};
var o2 = o1;

o1.a = 1;
o2.a // 1

o2.b = 2;
o1.b // 2
``` 

上記のコードでは、`o1`と`o2`は同じオブジェクトを指しているので、どちらかの変数に属性を追加すれば、もう一方の変数がその属性を読み書きすることができます。

このとき、ある変数の元のオブジェクトへの参照をキャンセルしても、別の変数には影響しません。

```javascript 
var o1 = {};
var o2 = o1;

o1 = 1;
o2 // {}
``` 

上記のコードでは、`o1`と`o2`は同じオブジェクトを指しています。そして、`o1`の値が1になります。このとき、`o2`は影響を受けません。`o2`は元のオブジェクトを指しています。

ただし、このような参照は、2つの変数が同じ元の型の値を指している場合に限定されます。変数はすべて値のコピー 

```javascript 
var x = 1;
var y = x;

x = 2;
y // 1
``` 

上のコードでは、`x`の値が変わっても`y`の値は変わらないので、`y`と`x`は同じメモリアドレスを指しているわけではありません。

### 式 か 文 か?

行の先頭が括弧である場合それは式なのか文なのかという問題が生じます

```javascript 
{foo: 123 }
``` 

JavaScriptエンジンがこのコードを読むと2つの意味があります1つ目はこれが式でfoo属性を持つオブジェクトを表しているということ 2つ目はコードのブロックを表す文でタグ`foo`が入っていて式`123`を指しています

このような曖昧さを避けるため、JavaScriptエンジンでは、このような状況に遭遇した場合、オブジェクトなのかコードブロックなのか特定できず、一律にコードブロックとして解釈します。

```javascript 
{console.log(123)} // 123 
``` 

上の文はコードのブロックであり、コードのブロックとして解釈しなければ実行できません。

対象として解釈する場合は、括弧の前に丸括弧を入れるとよいでしょう。丸括弧の中は、式にしかならないので、必ず大括弧は対象としてしか解釈できません。

```javascript 
({foo: 123}) //正しい 
({console.log(123)}) //エラー 
``` 

この違いは`eval`文(文字列の値を求める役割)に最もよく反映されます。

```javascript 
eval('{foo: 123}') // 123 
eval('({foo: 123})') // {foo: 123} 
``` 

上のコードで括弧がない場合、`eval`はコードのブロックだと理解します。丸括弧を入れると、対象として理解します。

## 属性の操作 

属性の読み込み 

オブジェクトの属性を読み取るには、ドット演算子と四角括弧演算子の2つの方法があります。

```javascript 
var obj = {
  p: 'Hello World'
};

obj.p // "Hello World"
obj['p'] // "Hello World"
``` 

上のコードはそれぞれ点の演算子と角括弧の演算子を採用して、属性`p`を読み取ります。

カギカッコ演算子を使う場合、キーネームをカギカッコ内に入れておかないと変数として扱われてしまうので注意が必要 。

```javascript 
var foo = 'bar' ;

var obj ={ 
foo: 1 
bar: 2 
} ;

obj.foo // 1 
obj[foo] // 2 
``` 

上のコードでは、オブジェクトの`obj`の`foo`属性を参照する場合、点演算子を使用すれば、`foo`は文字列 。括弧を使ってカッコを使わない場合「foo」は変数で文字列「bar」を指します

括弧演算子の内部では、式を使用することもできます。

```javascript 
obj['hello' + ' world' ]
obj[3 + 3] 
``` 

テンキーは括弧を入れなくてもいい 。文字列に変換されます。

```javascript 
var obj = {
  0.7: 'Hello World'
};

obj['0.7'] // "Hello World"
obj[0.7] // "Hello World"
``` 

上のコードでは、オブジェクト`obj`のテンキー`0.7`は、カッコをつけてもつけなくても、自働的に文字列に変換されます。

なお、数値キー名にはドット演算子は使用できません(小数点扱いになるため)。

```javascript 
var obj = {
  123: 'hello world'
};

obj.123 // 报错
obj[123] // "hello world"
``` 

上のコードの1つ目の式は、数値キー名`123`に対して点演算子を使用し、結果エラーを返します。2つ目の式は括弧演算子を使っています

### 属性の割り当て 

点演算子や角括弧演算子は値を読み出すだけでなく値を割り当てるのにも使えます

```javascript 
var obj ={} ;

obj.foo = 'Hello' ;
obj['bar'] = 'World' ;
``` 

上のコードでは、点演算子と角括弧演算子を使い分け、属性に値を与えています。

JavaScriptでは属性の「ポストバインディング」が可能 。いつでも属性を追加することができます。

```javascript 
var obj = {p: 1} ;

//等価 

var obj ={} ;
obj.p = 1 ;
``` 

### 属性の閲覧 

あるオブジェクトの全ての属性を見るために、` object.keysメソッドを使うことができます。

```javascript 
var obj ={ 
key1: 1 
key 2:2 
} ;

object.keys (obj);
// ['key1', 'key2' ]
``` 

### 属性の削除:deleteコマンド 

「delete」コマンドはオブジェクトの属性を削除するために使われ、削除に成功すると「true」と返されます。

```javascript 
var obj = {p: 1} ;
object.keys (obj) // ["p"]

delete obj.p // true 
obj.p // undefined 
object.keys (obj) //[] 。
``` 

上のコードで、`delete`コマンドはオブジェクトの`obj`の`p`属性を削除します。削除後、再度読み込むと「p」属性は「undefined」に戻り、「object.keys」メソッドの戻り値には属性が含まれなくなります。

なお、存在しないプロパティを削除した場合、「delete」はエラーを返さず、「true」が返されます。

```javascript 
var obj ={} ;
delete obj.p // true 
``` 

上記のコードでは、オブジェクト`obj`は`p`属性を持っていませんが、`delete`コマンドはそのまま`true`を返します。よって、`delete`コマンドの結果、ある属性が存在すると認めることはできません。

ただ1つ、「delete」コマンドが「false」を返す場合、その属性は存在し、削除できません。

```javascript 
var obj = Object.defineProperty({}, 'p', {
  value: 123,
  configurable: false
});

obj.p // 123
delete obj.p // false
``` 

上記のコードでは、オブジェクトの`obj`の`p`属性は削除できませんので、`delete`コマンドは`false`を返します(` object.defineproperty `メソッドについては、「標準ライブラリ」のObjectオブジェクトの章をご覧ください)。

なお、`delete`コマンドはオブジェクト自身の属性のみを削除することができ、継承された属性を削除することはできません(継承についてはオブジェクト指向プログラミングの項を参照)。

```javascript 
var obj ={} ;
delete obj.tostring // true 
obj.tostring // function toString() {[native code]}
``` 

上記のコードでは、`toString`はオブジェクトの`obj`継承の属性であり、`deleteコマンドは`true`を返しますが、この属性は削除されずにそのまま残っています。この例では、たとえ`delete`が`true`を返しても、属性は値を読み出すことができます。

### 属性は存在しますか:in演算子

`in`演算子はオブジェクトがある属性を含んでいるかどうかをチェックします(キー値ではなくキー名をチェックします)。含まれている場合は`true`、含まれていない場合は`false`を返します。左側が属性名を表す文字列で右側がオブジェクト 

```javascript 
var obj = {p: 1} ;
'p' in obj // true 
'toString' in obj // true 
``` 

`in`演算子の問題は、どの属性がオブジェクト自身のものでどの属性が継承されたものかを識別できないこと 。上記のコードのようにオブジェクトの`obj`自体は`toString`属性を持っていませんが`in`演算子は`true`を返します

その場合、オブジェクトの「hasOwnProperty」というメソッドを使って、オブジェクト自身の属性かどうかを判断します。

```javascript 
var obj ={} ;
if ('toString' in obj){ 
console.log(obj.hasownproperty ('toString')) // false 
} 
``` 

属性的遍歴:for… inループ 

`for …in`ループはオブジェクトの全ての属性を巡回します。

```javascript 
var obj = {a: 1, b: 2, c: 3} ;

for (var i in obj){ 
    console.log('キー名:',i);
    console.log('キー値:',obj[i]);
} 
//キー名:a 。
//キー値:1 。
//キーネーム:b 。
//キー値:2 。
//キー名:c 。
//キー値:3 。
``` 

`for …in`ループの使い方の注意点は2つあります。

-それはオブジェクトのすべてのenumerable属性をトラバースし、トラバースできない属性はスキップします。
-オブジェクト自身の属性をトラバースするだけでなく、継承する属性もトラバースします。

例えば、オブジェクトはすべて`toString`属性を受け継ぎますが、`for…in`ループはこの属性を通過しません。

```javascript 
var obj ={} ;

// toString属性は存在します
obj.tostring () {[native code]}

for (var p in obj){ 
console.log(p);
} //出力がありません
``` 

上記のコードでは、オブジェクトの`obj`は`toString`属性を継承しています。これはデフォルトで「トラバース不可」になっているため、in`循環トラバースします。オブジェクト属性のトラバース可能性については、標準ライブラリの章のObjectの章を参照されたい。

継承された属性がトラバース可能であれば、' for…in`循環は遍歴します。 が、一般的には、対象自身の属性だけを遍歴したいので、`for…in`の場合は、「hasOwnProperty」メソッドと組み合わせて、ループ内である属性がオブジェクト自身の属性かどうかを判断します。

```javascript 
var person = {name: 'さん'};

for (var key in person){ 
    if (person.hasownproperty (key)){ 
        console.log(key) ;
    } 
} 
// name 
``` 

## withフレーズ 。

`with`フレーズのフォーマットは以下の通り 。

```javascript 
with(対象){ 
語句 ;
} 
``` 

この機能は、同じオブジェクトの複数の属性を操作する際に、いくつかの書きやすさを提供します。

```javascript 
例1 
var obj ={ 
p1: 1 。
2: 2 。
} ;
with (obj){ 
p1 = 4 ;
p2 = 5 ;
} 
//に等しい 
obj.p1 = 4 ;
obj.p2 = 5 ;

例2 
with (document.links[0]){
console.log(href);
console.log(title) 。
console.log(style);
} 
//に等しい 
console.log(document.links[0].href);
console.log(document.links[0].title);
console.log(document.links[0].style);
``` 

なお、「with」ブロック内に変数の付値操作がある場合は、現在のオブジェクトに既に存在する属性でなければなりません。

```javascript 
var obj ={} ;
with (obj){ 
p1 = 4 ;
p2 = 5 ;
} 

obj.p1 // undefined 
p1 // 4 
``` 

上のコードでは、オブジェクト`obj`は`p1`属性を持っていません。`p1`に値を付けることはグローバル変数`p1`を作ることになります。オブジェクト`obj`の属性`p1`を定義し、それを`with`ブロック内で操作するのが正しい書き方 。

なぜなら、`with`ブロックはスコープを変えず、その内部は現在のスコープのままだから 。これは「with」文の大きな問題点の1つで、結びつける相手が明確でないこと 。

```javascript 
with (obj){ 
console.log(x);
} 
``` 

単に上のコードのブロックを見ているだけでは、`x`がグローバル変数なのか、オブジェクトの`obj`の属性なのかは判断できません。これはコードの除算とモジュール化に非常に不利で、コンパイラもこのコードを最適化することができません。実行時に判断することになり、実行速度が遅くなります。そこで、「with」文ではなく、「with」の代わりに仮変数を使うことをお勧めします。

```javascript 
with(obj2.obj2.obj3){ 
console.log(p1 + p2);
} 

//と書くことができます
var temp = obj1.obj2.obj3 。
console.log(temp.p1 + temp.p2) 。
``` 

## リンク参照 

- dr .アクセルrauschmayer、[object properties in javascript] (http://www.2ality.com/2012/10/javascript-properties.html)
−lakshan perera、[revisiting javascript objects] (http://www.laktek.com/2012/12/29/revisiting-javascript-objects/)
- Angus Croll [The Secret Life of JavaScript] primitives] (http://javascriptweblog.wordpress.com/2010/09/27/the-secret-life-of-javascript-primitives/)
Axel Rauschmayer氏 [javascript』s s deprecated with statement and why it」](http://www.2ality.com/2011/06/with-statement.html)

# 関数 

関数は繰り返し呼び出すことができるコードのブロック 関数は入力された引数も受け取り、それぞれの引数には固有の戻り値があります。

## 概要 

### 関数の宣言 

JavaScriptには関数を宣言する3つの方法があります。

** (1) functionコマンド** 。

functionコマンド宣言コードのブロックは、関数 。「function」コマンドの後には関数名が付いています。関数名の後には1対の括弧が付いています。関数体は括弧の中に入れます。

```javascript 
function print(s){ 
console.log(s) ;
} 
``` 

上のコードには「print」という関数が付いていて、後で「print()」という形式を使って、対応するコードを呼び出すことができます。これを関数の宣言(Function Declaration)と言います。

**(2)関数の式 **

「function」コマンドで関数を宣言するだけでなく、変数の付値という書き方もできます。

```javascript 
var print = function(s){ 
console.log(s) ;
} ;
``` 

これは匿名関数を変数に与えますこのとき、この匿名関数は関数式(Function Expression)とも呼ばれます。代入文の等号の右側には式しか置かないから 。

関数式で関数を宣言する場合、`function`コマンドの後に関数名を付けません。関数名を加えると、その関数名は関数体の内部でのみ有効であり、関数体の外部では無効 。

```javascript 
var print = function x(){
  console.log(typeof x);
};

x
// ReferenceError: x is not defined

print()
// function
``` 

上のコードは関数式に関数名`x`を入れています。この`x`が使えるのは関数の内部だけで、関数の式そのものを指します。この書き方の有用性は2つあり、1つは関数本体内で自分自身を呼び出すことができること、もう1つはエラー除去(エラー除去ツールが関数呼び出しスタックを表示するとき、関数名が表示され、ここでは匿名関数であることを表示しなくなります)を容易にすること 。そのため、次のような形式で関数を宣言することもよくあります。

```javascript 
var f = function f() {};
``` 

関数の式は文の終わりにセミコロンを付けて、文の終わりを示す必要があります。関数の宣言は、終わりの括弧の後にセミコロンを付けません。要するに、この二つの関数を宣言する方式は、違いがとても細かくて、ほぼ等価だと考えることができます。

** (3) Functionコンストラクタ** 。

関数を宣言する3つ目の方法は「コンストラクタ」 。

```javascript 
var add = new Function(
  'x',
  'y',
  'return x + y'
);

// 等しい
function add(x, y) {
  return x + y;
}
``` 

上のコードでは、コンストラクタは3つの引数を受け入れます。最後の引数を除いては、add関数の「関数体」 。

任意の数の引数をコンストラクタに渡すことができます。最後の引数だけが関数体として扱われます。

```javascript 
var foo = new Function(var foo) 。
'return "hello world" ;' 
) ;

//に等しい 
function foo(){ 
return 'hello world' ;
} 
``` 

' Function 'コンストラクタは' new 'コマンドを使わずに全く同じ結果を返すことができます。

要するに、この関数宣言の仕方は非常に非直感的で、ほとんど使われていません。

関数の繰り返し宣言 

同じ関数が何度も宣言されると、後の宣言が前の宣言を上書きしてしまいます。

```javascript 
function f(){ 
console.log(1);
} 
f() // 2 

function f(){ 
console.log(2);
} 
f() // 2 
``` 

上のコードでは、次の関数宣言は前の関数をカバーしています。また、関数名の向上(以下参照)により、前回の宣言はいつでも無効になるので注意が必要 。

### 括弧演算子、return文、再帰 

関数の呼び出しには、括弧演算子を使います。括弧の中に、関数の引数を入れます。

```javascript 
function add(x, y){ 
return x + y ;
} 

add(1, 1) // 2 
``` 

上のコードでは関数名の後に括弧が付いていれば関数が呼び出されます

関数体の中の`return`文は、returnを意味します。JavaScriptエンジンは`return`文に遭遇すると、その後ろにある式の値を返すので、後に文が残っていても実行されません。つまり、`return`文に付いている式は、関数の戻り値 。' return '文は必須ではありません。それがなければ関数は何の値も返さず、' undefined 'を返します。

関数はそれ自身を呼び出すことができます。これを再帰(recursion)といいます。フィボナッチ数列を再帰的に計算するコード 

```javascript 
function fib(num) {
  if (num === 0) return 0;
  if (num === 1) return 1;
  return fib(num - 2) + fib(num - 1);
}

fib(6) // 8
``` 

上のコードでは、fib関数の内部で再びfibを呼び出し、フィボナッチ数列の6番目の要素は8であることを計算します。

### 第一等市民 

JavaScriptでは関数を値として扱い、他の値(数値、文字列、ブール値など)と同じような位置づけにします。値が使えるところには関数が使えます。例えば、変数や対象の属性に値を与えたり、引数として他の関数に入ってきたり、関数の結果として返ってきたりします。関数はあくまで実行可能な値であり、それ以外に特別なことはありません。

関数は他のデータ型と同等であるため、JavaScript言語では関数のことを「第一級市民」と呼びます。

```javascript 
function add(x, y) {
  return x + y;
}

// 
var operator = add;

// 
function a(op){
  return op;
}
a(add)(1, 1)
// 2
``` 

### 関数名のアップグレード 

JavaScriptエンジンでは関数名を変数名と同一とするため、「function」コマンドで関数を宣言すると、関数全体が変数宣言のようにコードの先頭に上がってきます。したがって、次のコードはエラーを返しません。

```javascript 
f() ;

function f(){} 
``` 

上のコードは宣言前に関数`f`を呼び出しているように見えますしかし実際には「変数リフティング」により関数`f`がコードの先頭に上がっています呼び出しの前に宣言されていますしかし、代入文で関数を定義すると、JavaScriptはエラーを返します。

```javascript 
f() 。
var f = function (){};
// TypeError: undefined is not a function 
``` 

上のコードは下の形式と同じ 。

```javascript 
var f ;
f() ;
f = function(){}; 
``` 

上のコードの二番目の行、`f`を呼び出す時、`f`は宣言されただけで、まだ値を割り当てていません。`undefined`に等しいので、エラーが発生します。

なお、以下の例のように、`function`コマンドと`var`代入文で同じ関数を宣言する場合、関数の向上があるため、最後に`var`代入文の定義が採用されます。

```javascript 
var f = function(){ 
console.log('1');
} 

function f(){ 
console.log('2');
} 

f() // 1 
``` 

上の例では、表面上は後に述べる関数`f`は、前のvar代入文をカバーすべき が、関数の上昇があるので、実際にはその逆 。

## 関数の属性と仕様 

### name属性 

関数の「name」属性関数の名前を返します。

```javascript 
function f1() {}
f1.name // "f1"
``` 

変数の付値によって定義された関数の場合、`name`属性は変数名を返します。

```javascript 
var f2 = function () {};
f2.name // "f2"
``` 

しかし、これは変数の値が匿名関数である場合に限ります。変数の値が名前付き関数の場合、「name」属性は「function」キーワードの後の関数名を返します。

```javascript 
var f3 = function myName() {};
f3.name // 'myName'
``` 

上記のコードでは、`f3.name`は関数の名前を返します。なお、真の関数名は' f3 'であり、' myName 'という名前は関数の内部でのみ使用できます。

`name`属性の1つの用途は、引数関数の名前を取得すること 。

```javascript 
var myFunc = function () {};

function test(f) {
  console.log(f.name);
}

test(myFunc) // myFunc
``` 

上のコードでは、関数`test`内部に`name`属性を通し、入ってくるパラメータが何の関数かを知ることができます。

### length属性 

関数の「length」属性は、関数が予測している引数の数、すなわち関数の定義内の引数の数を返します。

```javascript 
function f(a, b) {}
f.length // 2
``` 

上のコードは空関数`f`を定義しており、そのlength属性は定義時のパラメータの個数 。いくら引数が入力されても、`length`属性は2になります。

「length」属性は、オブジェクト指向プログラミングの「メソッドオーバーロード」を可能にするために、定義時と呼び出し時のパラメータの違いを判定する仕組みを提供します。

### toString( )

関数の`toString()`メソッドは関数のソースコードを表す文字列を返します。

```javascript 
function f() {
  a();
  b();
  c();
}

f.toString()
// function f() {
//  a();
//  b();
//  c();
// }
``` 

上記の例では、関数`f`のtoString()`メソッドは、改行を含む`f`のソースコードを返します。

これらのネイティブ関数に対して、`toString()`メソッドは`function (){[native code]}`を返します。

```javascript 
Math.sqrt.toString()
// "function sqrt() { [native code] }"
``` 

上記のコードの中で、` math.sqrt()`はJavaScriptエンジンが提供するネイティブ関数で、`toString()`メソッドはネイティブコードのヒントを返します。

関数内の注釈を返すこともできます。

```javascript 
function f() {/*
これは一つ 
複数行の注釈があります
*/}

f.toString()
// "function f(){/*
//これはこちら 
//複数行の注釈があります
// */}"

``` 

これを利用して、変則的に複数行の文字列を実装することができます。

```javascript 
var multiline = function (fn){ 
var arr = fn.toString().split('\n');
return arr.slice(1, arr.length-1).join('\n');
} ;

function f(){/* 
これは一つ 
複数行の注釈があります
*/} 

multiline(f) 
// "これはこれ 
//多行注釈"
``` 

上記の例では、関数`f`の内部に複数行の注釈がありますが、`toString()`メソッドで`f`のソースコードを取得した後、最初と最後の2行を取り除くと、複数行の文字列になります。

## 関数ドメイン 

定義します

スコープ(scope)とは変数が存在する範囲のこと 。ES5の仕様では、JavaScriptには2つのスコープしかありません。一つはグローバルスコープで、プログラム全体に変数が常に存在し、どこでも読み込むことができます。もう一つは関数スコープで、変数は関数内にしか存在しません。ES6はブロックレベルのスコープを追加しました。

トップ関数の場合、関数の外側で宣言されている変数がグローバル変数(global variable)であり、これは関数の内側で読み取られます。

```javascript 
var v = 1 ;

function f(){ 
console.log(v);
} 

f( )
// 1 
``` 

上のコードは関数`f`が内部的にグローバル変数`v`を読めることを示しています

関数の内部で定義された変数を、外部からは読み取れないものを「ローカル変数」(local variable)と呼びます。

```javascript 
function f(){ 
var v = 1 ;
} 

v // ReferenceError: v is not defined
``` 

上のコードでは、変数`v`は関数の内部で定義されているので、局所変数であり、関数以外では読み取れません。

関数内で定義された変数は、そのスコープ内に同名のグローバル変数を上書きします。

```javascript 
var v = 1 ;

function f(){ 
var v = 2 ;
console.log(v);
} 

f() // 2 
v // 1 
``` 

上記のコードでは、変数`v`は関数の外側と内側の両方で定義されています。その結果、関数の内部定義では、局所変数`v`がグローバル変数`v`をカバーします。

varコマンドの場合、局所変数は関数内で、他のブロック内でのみ宣言され、すべてグローバル変数となります。

```javascript 
if (true){ 
var x = 5 ;
} 
console.log(x);// 5 
``` 

上記のコードでは、変数`x`は条件判定ブロック内で宣言されており、その結果はグローバル変数となり、ブロックの外から読み取ることができます。

### 関数内の変数の上昇 

グローバルドメインと同様に、関数ドメイン内でも「変数の上昇」現象が起こります。' var 'コマンド宣言された変数は、変数宣言がどの位置にあっても関数体の頭の部分まで引き上げられます。

```javascript 
function foo(x) {
  if (x > 100) {
    var tmp = x - 100;
  }
}

// 等同于
function foo(x) {
  var tmp;
  if (x > 100) {
    tmp = x - 100;
  };
}
``` 

関数自体のスコープ 

関数自体も値であり、作用域を持っています。そのスコープは変数と同じで、それが宣言されるときのスコープであり、実行されるときのスコープとは関係ありません。

```javascript 
var a = 1;
var x = function () {
  console.log(a);
};

function f() {
  var a = 2;
  x();
}

f() // 1
``` 

上記のコードでは、関数`x`は関数`f`の外部で宣言されているので、そのスコープは外層に結び付けられており、内部変数`a`は関数`f`の内部に値を取りませんので、`2`ではなく`1`を出力します。

つまり、関数が実行されたときにあるスコープは、定義されたときのスコープであって、呼び出したときのスコープではありません。

間違いやすいのは、関数Aが関数Bを呼び出すときに、関数Bが関数Aの内部変数を参照しないことを考えていないこと 。

```javascript 
var x = function () {
  console.log(a);
};

function y(f) {
  var a = 2;
  f();
}

y(x)
// ReferenceError: a is not defined
``` 

上のコードは関数`x`を引数として、関数`y`を入力します。しかし、関数`x`は関数`y`の外側で宣言され、ドメインは外層と結び付けられているため、関数`y`の内部変数`a`が見つからず、エラーが発生します。

同様に、関数体の内部で宣言された関数、ドメインは関数体の内部に結合されます。

```javascript 
function foo(){ 
var x = 1 ;
function bar(){ 
console.log(x);
} 
return bar ;
} 

var x = 2 ;
var f = foo() ;
f() // 1 
``` 

上記のコードでは関数「foo」は関数「bar」を内部宣言しており、barのスコープは関数「foo」をバインディングしています。" foo "の外側で" bar "を取り出して実行するとき変数" x "は" foo "の外側の" x "ではなく" foo "の内側の" x "を指しますこのメカニズムこそが、後述する「閉包」という現象を構成しているの 。

## パラメータ 

### 概要

関数を実行するときに、外部のデータが必要になることがあります。外部のデータによって異なる結果が得られます。

```javascript 
function square(x){ 
return x * x ;
} 

square(2) // 4 
square(3) // 9 
``` 

上の式の`x`がスクエア関数のパラメータ 。実行するたびにこの値を与えなければ結果は得られません

### パラメータの省略 

関数の引数は必要ありません。JavaScriptでは引数を省略できます。

```javascript 
function f(a, b){ 
return a ;
} 

f(1, 2, 3) // 1 
f(1) // 1 
f() // undefined 

f.ength // 2 
``` 

上記のコードの関数「f」は2つのパラメータを定義していますが、JavaScriptは実行時にいくつのパラメータを提供しても(提供しなくても)エラーは発生しません。省略したパラメータの値は「undefined」となります。なお、関数の「length」属性は実際に入ってくるパラメータの数とは関係なく、関数が入ると予想されるパラメータの数のみを反映します。

ただし、前のパラメーターだけを省略して、後ろのパラメーターを残しておくことはできません。上位パラメータを省略しなければならない場合は、明示的に`undefined`を入れます。

```javascript 
function f(a, b){ 
return a ;
} 

f(, 1) // SyntaxError: Unexpected token,(…)
f(undefined, 1) // undefined 
``` 

上のコードでは、1つ目のパラメータを省略するとエラーが発生します。

### 渡し方 

引数が元の型の値(数値、文字列、ブール値)の場合はpasses by valueで渡します。これは、関数の内部でパラメータ値を変更することは、関数の外部には影響しないことを意味します。

```javascript 
var p = 2 ;

function f(p){ 
p = 3 ;
} 
f(p) ;

p // 2 
``` 

上記のコードでは、変数`p`は元の型の値であり、関数`f`は値を渡す形で入ってきます。したがって、関数内では、`p`の値は元の値のコピーであり、いくら修正しても元の値には影響しません。

ただし、関数パラメータが複合型の値(配列、オブジェクト、その他の関数)の場合は、パス・バイ・パス(pass by reference)で渡されます。つまり、入ってくる関数の元の値のアドレスなので、関数内でパラメータを変更すると元の値に影響が出ます。


```javascript 
var obj = {p: 1} ;

function f(o){ 
o.p = 2 ;
} 
f(obj) ;

obj.p // 2 
``` 

上のコードでは引数オブジェクトobjのアドレスを入力関数`f`にしますしたがって、関数内で`obj`の属性`p`を修正すると元の値に影響します。

なお、関数内でパラメータオブジェクトの属性を変更するのではなく、パラメータ全体を置き換えた場合、元の値には影響しません。

```javascript 
var obj =[1, 2, 3] ;

function f(o){ 
o =[2, 3, 4] ;
} 
f(obj) ;

obj //[1, 2, 3] 。
``` 

上記のコードでは、関数`f()`の内部で、パラメータオブジェクト`obj`が全体として別の値に置き換えられています。この場合、元の値には影響しません。これは、形式パラメータ(`o`)の値は実際にはパラメータobjのアドレスであり、新たに`o`に値を付けることでo`が別のアドレスを指すことになり、元のアドレスに保存された値は当然影響を受けないから 。

### 同名のパラメータ 

同名のパラメータがあれば、最後に出てきた値を取ります。

```javascript 
function f(a, a){ 
console.log(a) ;
} 

f(1, 2) // 2 
``` 

上記のコードでは、関数`f()`には2つの引数があり、引数名はどちらも`a` 。値をとるときは、後ろのaを基準にします。後ろのaは値がないか省略されていても、それを基準にします。

```javascript 
function f(a, a){ 
console.log(a) ;
} 

f(1) // undefined 
``` 

関数`f()`を呼び出すとき、2つ目の引数が与えられていないので、`a`の取り方は`undefined`になります。このとき、最初の`a`の値を取得する場合は、`arguments`オブジェクトを使用します。

```javascript 
function f(a, a){ 
console.log(arguments[0]);
} 

f(1) // 1 
``` 

### argumentsオブジェクト 

**(1)定義** 。

JavaScriptでは関数が不定数の引数を持つことができるため、関数本体内で全ての引数を読み込む仕組みが必要 。これがargumentsというオブジェクトの由来 。

' arguments 'オブジェクトは関数実行時のパラメータを全て含んでいます' arguments[0] 'が1つ目のパラメータ' arguments[1] 'が2つ目のパラメータ'など このオブジェクトは関数体の中でのみ、使用することができます。

```javascript 
var f = function (one){ 
console.log(arguments[0]);
console.log(arguments[1]);
console.log(arguments[2]);
} 

f(1, 2, 3) 
// 1 
// 2 
// 3 
``` 

通常モードでは、`arguments`オブジェクトは実行中に修正できます。

```javascript 
var f = function(a, b){ 
arguments[0] = 3 ;
arguments[1] = 2 ;
return a + b ;
} 

f(1, 1) // 5 
``` 

上記のコードでは、関数`f()`の呼び出し時に入ってくる引数が、関数内で`3`と`2`に修正されています。

厳密モードでは、`arguments`オブジェクトは関数パラメータと連働しません。つまり、`arguments`オブジェクトの修正は、実際の関数パラメータには影響しません。

```javascript 
var f = function(a, b){ 
'use strict' ;厳しいモードをオンにします。
arguments[0] = 3 ;
arguments[1] = 2 ;
return a + b ;
} 

f(1, 1) // 2 
``` 

上のコードの中で、関数の内部は厳格なモードで、この時`arguments`オブジェクトを修正して、真のパラメータ`a`と`b`に影響しません。

`arguments`オブジェクトの`length`属性によって、関数呼び出し時にいくつのパラメータを持っているかがわかります。

```javascript 
function f(){ 
return argumens.length;
} 

f(1, 2, 3) // 3 
f(1) // 1 
f() // 0 
``` 

**(2)と配列の関係 **

`arguments`は配列に似ていますがオブジェクト 配列固有の手法(例えば`slice`や`forEach`)は、`arguments`オブジェクト上では使えません。

`arguments`オブジェクトに配列法を使わせる場合、真の解決法は`arguments`を真の配列にすること 。次は2つの一般的な変換方法 。`slice`方法と新しい配列を1つずつ埋めていきます。

```javascript 
var args = Array.prototype.slice.call(arguments);

// 或
var args = [];
for (var i = 0; i < arguments.length; i++) {
  args.push(arguments[i]);
}
``` 

**(3)カリ属性 **

' arguments 'オブジェクトは' callee '属性を持ち、元の関数を返します。

```javascript 
var f = function(){ 
console.log(argumens.callee === f);
} 

// true 
``` 

` argumens.callee 'によって、関数自体を呼び出すことができます。この属性はシビアモードでは無効になっているためお勧めできません。

## 関数のその他の知識 

閉包 

JavaScriptの特徴である閉包(closure)は、多くの高度なアプリケーションが閉包に依存しています。

閉包を理解するには、まず変数スコープを理解しなければなりません。先述したように、JavaScriptにはグローバルドメインと関数ドメインという2つのドメインがあります。関数の内部からグローバル変数を直接読み取ることができます。

```javascript 
var n = 999 ;

function f1(){ 
console.log(n);
} 
f1() // 999 
``` 

関数`f1`がグローバル変数`n`を読み取ります

しかし、通常、関数の内部で宣言されている変数を関数の外部から読み取ることはできません。

```javascript 
function f1(){ 
var n = 999 ;
} 

console.log(n) 
// Uncaught ReferenceError: n is not defined (
``` 

上記のコードでは、関数`f1`の内部宣言変数`n`は、関数以外では読み取れません。

いろいろな理由で、関数内の局所変数を求める必要がある場合 。普通はできませんが、変則的な方法でしかできません。それは、関数の内部に、もう一つの関数を定義すること 。

```javascript 
function f1(){ 
var n = 999 ;
function f2(){ 
console.log(n);// 999 
} 
} 
``` 

上記のコードでは、関数`f2`は関数`f1`の内部にあります。このとき、`f1`の内部のすべての局所変数は、`f2`に対して可視 。しかし逆はいけません。`f2`の内部の局所変数は、`f1`には見えません。これはJavaScript特有の「チェーンスコープ(chain scope)」構造で、子オブジェクトが親オブジェクトの変数を1段階ずつ上に探していきます。親対象のすべての変数は子対象に対して可視であり、逆は成り立たないの 。

「f2」が「f1」の局所変数を読み取れるのなら、「f2」を戻り値にすれば、「f1」の外側から内部変数を読み取れるのではないでしょうか!

```javascript 
function f1(){ 
var n = 999 ;
function f2(){ 
console.log(n);
} 
return f2 ;
} 

var result = f1() ;
result() ;// 999 
``` 

関数`f1`の戻り値が関数`f2` が、`f2`が内部変数`f1`を読み取れるので、外部から`f1`の内部変数を得ることができます。

閉包とは関数`f2`、つまり、他の関数の中の変数を読み取れる関数のこと 。JavaScript言語では、関数内の副関数のみが内部変数を読み取れるため、閉包は単に「関数内に定義された関数」と理解することができます。閉包の最大の特徴は、生まれた環境を「覚える」ことができること 。例えば、`f2`は生まれた環境`f1`を覚えるので、`f2`から`f1`の内部変数を得ることができます。本質的には、閉包は関数の内部と関数の外部を結ぶ橋 。

閉包の最大の用途は2つあります。1つは外側の関数の中の変数を読み込むこと 。もう1つは変数を常にメモリに保持すること 。次の例を見てください。閉包は、内部変数が前回呼び出したときの演算結果を記憶するようにします。

```javascript 
function createIncrementor(start){ 
return function(){ 
return start++;
} ;
} 

var inc = createIncrementor(5);

inc() // 5 
inc() // 6 
inc() // 7 
``` 

「start」は関数「createIncrementor」の内部変数 閉包によって`start`の状態が保持され、それぞれの呼び出しは前回の呼び出しに基づいて計算されます。ここからわかるように、閉包`inc`は関数`createIncrementor`の内部環境が常に存在しています。従って、閉包は関数内のスコープのインタフェースと見ることができます。

なぜ閉包は外層関数の内部変数を返すことができるのでしょうか?閉包(上の例の`inc`)が外層変数(`start`)に使われてしまい、外層関数(`createIncrementor`)がメモリから解放されないから 。閉包がゴミ回収機構によって消去されない限り、外側の関数によって提供される実行環境も消去されず、その内部変数は閉包が読み取るための現在値を常に保持します。

閉包の別の用途は、オブジェクトのプライベート属性とプライベートメソッドをカプセル化すること 。

```javascript 
function Person(name) {
  var _age;
  function setAge(n) {
    _age = n;
  }
  function getAge() {
    return _age;
  }

  return {
    name: name,
    getAge: getAge,
    setAge: setAge
  };
}

var p1 = Person('木三');
p1.setAge(25);
p1.getAge() // 25
} 

``` 

上のコードでは、関数`Person`の内部変数`_age`が、閉包`getAge`と`setAge`によって、オブジェクト`p1`を返すプライベート変数になります。

なお、外側の関数が実行されるたびに新たな閉包が生成され、この閉包が外側の関数の内部変数を保持するため、メモリの消費が大きくなります。そのため、閉包を悪用してはいけません。さもなければ、ウェブページの性能に問題が発生します。

### すぐに呼び出す関数式(IIFE) 。

JavaScriptの構文では、括弧`()`が関数名に続き、関数を呼び出すことを意味します。例えば、`print()`は`print関数を呼び出すことを意味します。

場合によっては、関数を定義した直後に、その関数を呼び出す必要があります。このとき、関数の定義の後に括弧を入れてはいけません。構文的な誤りが発生します。

```javascript 
function(){ /* code */ }();
// SyntaxError: Unexpected token (
``` 

このエラーの原因は、「function」というキーワードが文にも式にもなるから 。

```javascript 
//語句 
function f(){} 

//式 
var f = function f(){} 
``` 

式として使う場合は、関数を定義したまま括弧を入れて呼び出すことができます。

```javascript 
var f = function f(){return 1}();
f // 1 
``` 

上記のコードでは、関数が定義されたときに括弧を入れて呼び出すとエラーが発生しません。その理由は「function」を式とし、エンジンが関数を値として扱うから 。この場合、間違いを返すことはありません。

構文解析の曖昧さを避けるため、JavaScriptでは「function」というキーワードが行頭に出てきたら、すべて文として解釈するようになっています。そのため、行頭が「function」というキーワードになっているのを見たエンジンは、この段落はすべて関数の定義であり、括弧で終わるべきではないと勘違いしてしまいます。

関数が定義されてすぐに呼び出される解決策は、「function」を行頭に出さず、エンジンがそれを式として理解すること 。一番簡単なのは、括弧の中に入れること 。

```javascript 
(function(){ /* code */ }());
// 或
(function(){ /* code */ })();
``` 

どちらも括弧で始まるので、エンジンは関数の定義文ではなく、式が続くと認識するので、ミスを避けることができます。これをimmediately-invoked Function Expression(即座に呼び出される関数式)、略してIIFEと呼びます。

なお、どちらも最後のセミコロンは必須 。セミコロンを省略して、IIFEが二つ続いていると間違えてしまうかもしれません。

```javascript 
ミスを返します
(function(){ /* code */ }())
(function(){ /* code */ }())
``` 

上のコードの2行の間にはセミコロンがありません。JavaScriptはそれらをつなげて解釈し、2行目を1行目のパラメータとして解釈します。

一般的には、インタプリタに関数の定義を式で処理させるどんな方法でも同じ効果が得られます。例えば、次の3つの書き方 。

```javascript 
var i = function(){ return 10; }();
true && function(){ /* code */ }();
0, function(){ /* code */ }();
``` 

さらに、次のように書いてもいいでしょう。

```javascript 
!function () { /* code */ }();
~function () { /* code */ }();
-function () { /* code */ }();
+function () { /* code */ }();

``` 

通常は匿名関数に対してのみ、このような「即座に実行する関数式」が使われます。その目的は2つあります:1つは関数に名前を付ける必要がなく、グローバル変数の汚染を回避すること 。2つ目は、IIFEの内部には個々のスコープが形成されており、外部からは読み取れないプライベートな変数をカプセル化することができます。

```javascript 
// 書き方1
var tmp = newData;
processData(tmp);
storeData(tmp);

// 2
(function () {
  var tmp = newData;
  processData(tmp);
  storeData(tmp);
}());
``` 

コードの書き方2は1よりも良い グローバル変数の汚染を完全に回避できます

## evalコマンド 

基本的な使い方 

`eval`コマンドは引数として文字列を受け取り、文として実行します。

```javascript 
eval('var a = 1;');
a // 1
``` 

上のコードは文字列を文として実行し変数`a`を生成します

パラメータ文字列が文として動作しない場合、エラーが発生します。

```javascript 
eval('3x') // Uncaught SyntaxError: Invalid or unexpected token
``` 

`eval`に置かれた文字列は、独自の存在意義を持つべきであり、`eval`以外のコマンドと併用してはいけません。例えば、次のコードはエラーが発生します。

```javascript 
eval('return;'); // Uncaught SyntaxError: Illegal return statement
``` 

`return`は単独では使用できないので、関数内で使用する必要があります。

`eval`の引数が文字列でない場合は、そのまま戻ります。

```javascript 
eval(123) // 123 
``` 

`eval`は独自のスコープを持たず、現在のスコープ内で実行されるため、現在のスコープの変数の値が修正される可能性があり、セキュリティに問題があります。

```javascript 
var a = 1;
eval('a = 2');

a // 2
``` 

上記のコードでは、`eval`コマンドが外部変数`a`の値を変更しています。このため、`eval`は安全リスクがあります。

このようなリスクを防ぐため、JavaScriptでは厳格なパターンを使えば、変数の内部宣言が外部ドメインに影響を与えないように規定しています。

```javascript 
(function f() {
  'use strict';
  eval('var foo = 123');
  console.log(foo);  // ReferenceError: foo is not defined
})()
``` 

上のコードの中で、関数`f`の内部は厳格なパターンで、この時`eval`の内部宣言の`foo`変数、外部に影響しません。

ただし、厳密なモードでも`eval`は現在のスコープの変数を読み書きすることができます。

```javascript 
(function f() {
  'use strict';
  var foo = 1;
  eval('foo = 2');
  console.log(foo);  // 2
})()
``` 

上のコードでは、厳しいモードでは`eval`の内部が外部変数に書き換えられていますが、セキュリティリスクは依然として残っています。

つまり、`eval`の本質は、現在のスコープの中に、コードを注入すること 。JavaScriptエンジンはセキュリティ上のリスクや実行速度の最適化に不利なため、一般的には推奨されていません。通常、「eval」はJSONデータの文字列を解析するのが一般的 が、正しくはネイティブの「json.parse」メソッドを使います。

### evalのエイリアス呼び出し 

前述したように`eval`は実行速度の最適化に役立ちません。さらに厄介なのは、エンジンが静的コード解析の段階で「eval」を実行しているのか見分けがつかない場合 。

```javascript 
var m = eval;
m('var x = 1');
x // 1
``` 

上のコードで変数`m`はevalの別名 静的コード解析フェーズでは、エンジンが認識できない`m('var x = 1')`は`eval`コマンドを実行します。

`eval`のエイリアスがコードの最適化に影響しないことを保証するために、JavaScriptの標準はすべてエイリアスを使用して`eval`を実行することを規定して、`eval`内部はすべてグローバルドメイン 。

```javascript 
var a = 1;

function f() {
  var a = 2;
  var e = eval;
  e('console.log(a)');
}

f() // 1
``` 

上のコードでは、`eval`は別名呼び出しなので、関数であっても、そのスコープはグローバルスコープなので、出力の`a`はグローバル変数 。すると、エンジンは`e()`が現在の関数スコープに影響を与えないことを確認し、最適化の際にその行を除外することができます。

`eval`のエイリアス呼び出しには様々な形がありますが、直接呼び出しでない限り、エイリアス呼び出しに該当します。エンジンは`eval()`の1つだけを直接呼び出しと見分けることができます。

```javascript 
eval.call(null, '...')
window.eval('...')
(1, eval)('...')
(eval, eval)('...')
``` 

これらの形式は`eval`の別名呼び出しであり、ドメインはグローバルドメイン 。

## リンク参照 

ベン・アルマン [Immediately-Invoked Function Expression] 。(iife)] (http://benalman.com/news/2010/11/immediately-invoked-function-expression/)
マーク・ダゲット [Functions] explained] (https://web.archive.org/web/20160911170816/http://markdaggett.com/blog/2013/02/15/functions-explained/)
−juriy zaytsev、[named function expressions demystified] (http://kangax.github.io/nfe/)
- Marco Rogers polotek, [What is the arguments object か?](http://docs.nodejitsu.com/articles/javascript-conventions/what-is-the-arguments-object)
- Juriy Zaytsev, [Global eval. What are the options か?](http://perfectionkills.com/global-eval-what-are-the-options/)
−アクセルrauschmayer、[evaluating javascript code via eval (and) new function ()] (http://www.2ality.com/2014/01/eval.html)

# 配列 

## 定義します

配列(array)とは、1組の値を順番に並べたもの 。それぞれの値の位置には(0から)番号が振られており、その配列全体は角括弧で表されています。

```javascript 
var arr = ['a', 'b', 'c'];
``` 

上のコードの`a`、`b`、`c`は配列を構成し、両端の括弧は配列のフラグ 。`a`は0番ポジション、`b`は1番ポジション、`c`は2番ポジション 。

定義時に値を付けることに加えて、配列は定義後に値を付けることもできます。

```javascript 
var arr =[] ;

arr[0] = 'a' ;
arr[1] = 'b' ;
arr[2] = 'c' ;
``` 

どんな種類のデータでも、配列に入れることができます。

```javascript 
var arr = [
  {a: 1},
  [1, 2, 3],
  function() {return true;}
];

arr[0] // Object {a: 1}
arr[1] // [1, 2, 3]
arr[2] // function (){return true;}
``` 

上の配列`arr`の3つのメンバーは、対象、配列、関数の順 。

配列の要素が配列のままであれば、多次元配列を形成します。

```javascript 
var a = [[1, 2], [3, 4]];
a[0][1] // 2
a[1][1] // 4
``` 

配列の本質 

配列は本質的に特別な対象 `typeof`演算子が返す配列の型は`object 

```javascript 
typeof [1, 2, 3] // "object"
``` 

上記のコードによると、`typeof`演算子は配列の型をオブジェクトとして認識します。

配列の特殊性は,キー名が整数の並び(0,1,2…)であること 。 。

```javascript 
var arr = ['a', 'b', 'c'];

Object.keys(arr)
// ["0", "1", "2"]
``` 

上記のコードでは、` object.keysメソッドは配列のすべてのキー名を返します。配列のキー名が整数の0、1、2であることがわかります。

配列メンバーのキー名が固定されているため(デフォルトでは常に0、1、2…) 。そのため、要素ごとにキー名を指定する必要はなく、オブジェクトのメンバーごとにキー名を指定しなければなりません。JavaScript言語では、オブジェクトのキー名はすべて文字列と決まっているので、配列のキー名も文字列 。数値で読めるのは、非文字列のキー名が文字列に変換されるから 。

```javascript 
var arr = ['a', 'b', 'c'];

arr['0'] // 'a' 
arr[0] // 'a' 
``` 

上のコードに数値と文字列をキー名にしており、その結果、配列を読み取ることができます。その理由は、数値キー名が自動的に文字列に変換されるから 。

なお、これは代入においても成立します。1つの値はいつも文字列に変換してからキー名として割り当てます。

```javascript 
var a = [];

a[1.00] = 6;
a[1] // 6
``` 

上記のコードでは、`1.00`を文字列に変換すると`1`なので、テンキー`1`で値を読み取ることができます。

前章で、オブジェクトには点構造(`object.key`)と角括弧構造(`object[key]`)の2種類のメンバを読み取る方法があると書きました。ただし、数値のキー名に点構造は使えません。

```javascript 
var arr = [1, 2, 3];
arr.0 // SyntaxError
``` 

`arr.0`の表記は正当ではありません。個々の数値を識別子(identifier)とすることはできません。よって、配列のメンバーは括弧`arr[0]`でしか表すことができません(括弧は演算子なので、数値を受け入れることができます)。

## length属性 

配列の`length`属性、配列のメンバの数を返します。

```javascript 
['a', 'b', 'c'].length // 3
``` 

JavaScriptは32ビットの整数を使用し、配列の要素数を保持します。つまり、メンバは4294967295個(2<sup>32</sup> - 1)まで 。つまり、「length」属性の最大値は4294967295になります。

配列である限り、必ず「length」属性があります。この属性は、キー名の最大整数に`1`を加えた動的な値 。

```javascript 
var arr = ['a', 'b'] ;
arr.length // 2 

arr[2] = 'c' ;
arr.length // 3 

arr[9] = 'd' ;
arr.length // 10 

arr[1000] = 'e' ;
arr.length // 1001 
``` 

上のコードによると、配列のテンキーは連続である必要はなく、`length`属性の値は常に最大の整数キーより`1`大きい 。また、配列が動的なデータ構造であることも示しています。

「length」属性は書き込み可能 。現在のメンバの数よりも小さい値を人為的に設定すると、その配列のメンバの数は自動的に`length`が設定した値まで減少します。

```javascript 
var arr = ['a', 'b', 'c'];
arr.length // 3 

arr.length = 2 ;
arr // ["a", "b"]
``` 

このコードは、配列の`length`属性が2に設定されている場合(つまり、最大の整数キーは1のみ)、整数キー2(値`c`)は配列から除外され、自働的に削除されることを示しています。

配列を空にする効果的な方法は、`length`属性を0にすること 。

```javascript 
var arr = ['a', 'b', 'c'];

arr.length = 0 ;
arr //[] 。
``` 

現在の要素の数よりも`length`が大きいように人為的に設定すると、配列のメンバの数はこの値まで増加します。

```javascript 
var a = ['a'] ;

a.ength = 3 ;
a[1] // undefined 
``` 

上記のコードは、「length」属性を配列数より大きく設定した場合、新たに読み込んだ位置が「undefined」に戻ることを示しています。

人為的に`length`を不正な値に設定すると、JavaScriptがエラーを返します。

```javascript 
//負の値を設定します。
[].length = -1 ;
// RangeError: Invalid array length 

//配列要素の数は2の32乗以上 。
[].length = math.pow(2, 32) ;
// RangeError: Invalid array length 

//文字列を設定します。
[].length = 'abc' ;
// RangeError: Invalid array length 
``` 

配列は本質的にオブジェクトなので、配列に属性を追加することができますが、これは`length`属性の値には影響しません。

```javascript 
var a =[] ;

a['p'] = 'abc' ;
a.length // 0 

a[2.1] = 'abc' ;
a.length // 0 
``` 

上のコードは配列のキーをそれぞれ文字列と小数に設定して、結果はいずれも`length`属性に影響しません。なぜなら、`length`属性の値は最大の数字キーに1を加えたものとなり、この配列には整数キーがないため`length`属性は`0のままとなります。

配列のキー名がオーバーレンジの数値を追加している場合、そのキー名は自動的に文字列に変換されます。

```javascript 
var arr =[] ;
arr[-1] = 'a' ;
arr[math.pow (2, 32)] = 'b' ;

arr.length // 0 
arr[-1] // "a" 
arr[4294967296] // "b" 
``` 

上のコードでは、配列`arr`に2つの不適法な数字キーを追加しましたが、`length`属性は変わりませんでした。これらの数字キーは文字列キー名になります最後の2行が値を取るのは、キー値を取るときにテンキー名がデフォルトで文字列になるから 。

## in演算子 

あるキー名の演算子`in`が存在するかどうかをチェックします。オブジェクトにも当てはまりますし、配列にも当てはまります。

```javascript 
var arr = ['a', 'b', 'c'];
2 in arr // true 
'2' in arr // true 
4 in arr // false 
``` 

上のコードは、配列にキー名`2`があることを示しています。キー名はすべて文字列なので、数値`2`は自動的に文字列に変換されます。

配列のある位置が空の場合`in`演算子は`false`を返します

```javascript 
var arr =[] ;
arr[100] = 'a' ;

100 in arr // true 
1 in arr // false 
``` 

上のコードでは、配列`arr`は1つのメンバ`arr[100]`だけで、他の位置のキー名は`false`を返します。

## for …inループと配列の移動 

`for …in`ループはオブジェクトだけでなく複数のグループをもトラバースすることができます。

```javascript 
var a =[1, 2, 3] 。

for (var i in a){ 
console.log(a[i]);
} 
// 1 
// 2 
// 3 
``` 

 が,`for…in`は数組のすべてのテンキーをトラバースするだけでなく、非テンキーもトラバースします。

```javascript 
var a =[1, 2, 3] ;
a.oo = true ;

for (var key in a){ 
console.log(key) ;
} 
// 0 
// 1 
// 2 
// foo 
``` 

上のコードは数群をトラバースする時、非整数キー`foo`もトラバースします。 から、`for…in`数組を遍歴します。

配列のトラバースは、`for`ループまたは`while」ループの使用が考えられます。

```javascript 
var a = [1, 2, 3];

// for loop
for(var i = 0; i < a.length; i++) {
  console.log(a[i]);
}

// while loop
var i = 0;
while (i < a.length) {
  console.log(a[i]);
  i++;
}

var l = a.length;
while (l--) {
  console.log(a[l]);
}
``` 

上のコードは3種類のトラバースで書かれています最後の方法は逆トラバースで、最後の元から最初の元へトラバースします。

配列の`forEach`法は、配列を遍在させることもできます。詳しくは標準ライブラリのArrayオブジェクトの章を参照してください。

```javascript 
var colors = ['red', 'green', 'blue'];
colors.forEach(function (color) {
  console.log(color);
});
// red
// green
// blue
``` 

## 配列の空き 

配列のある位置が空の元、つまり2つのコンマの間に何の値もないときは、その配列に空きがあるといいます。

```javascript 
var a = [1, , 1];
a.length // 3
``` 

上のコードによると、配列の空きは「length」属性に影響しません。この位置には値がありませんが、エンジンはこの位置が有効だと考えます。

ただし、最後の要素にコンマがついていても空きは生じません。つまり、このコンマがあってもなくても結果は同じなの 。

```javascript 
var a = [1, 2, 3,];

a.length // 3
a // [1, 2, 3]
``` 

上のコードでは、配列の最後のメンバーの後ろにコンマが付いていますが、これは`length`属性の値には影響しません。

配列の空きは読み取ることができ、`undefined`を返します。

```javascript 
var a =[,,,] 
a[1] // undefined 
``` 

`delete`コマンドを使用してメンバの配列を削除すると、空きが形成され、`length`属性には影響しません。

```javascript 
var a =[1, 2, 3] 
delete a[1] 

a[1] // undefined 
a.length // 3 
``` 

上のコードは`deleteコマンドで配列の2番目の要素を削除しました。この位置は空席となりますが`length`属性には影響しません。つまり、`length`属性は空きをフィルタリングしません。なので、「length」属性を使った配列トラバースには十分注意が必要 。

配列のある位置が空席であることと、ある位置が「undefined」であることは違います。空席の場合は、配列の`forEach`法、`for… 。in`構造、および' object.keys 'メソッドをトラバースすると、空席はスルーされます。

```javascript 
var a = [, , ,];

a.forEach(function (x, i) {
  console.log(i + '. ' + x);
})
// no output

for (var i in a) {
  console.log(i);
}
// no output

Object.keys(a)
// []
``` 

ある位置が「undefined」であれば、横断の際にスキップされることはありません。

```javascript 
var a = [undefined, undefined, undefined] ;

a. foreach (function (x, i) {a. foreach (function (x, i))} 
console.log(i + '. ' + x);
) ;
// 0. undefined 
// 1. undefined 
// 2. undefined 

for (var i in a){ 
console.log(i);
} 
// 0 
// 1 
// 2 

object.keys (a) 
// ['0', '1', '2']
``` 

つまり、空位とは配列がその要素を持っていないのでトラバースされないことを意味し、`undefined`は配列がその要素を持っていることを意味し、値は`undefined`なのでトラバースされないことを意味します。

## 配列のようなオブジェクト 

全てのキー名が正の整数または0であり、length属性を持つオブジェクトは配列に似ており、構文的には「配列に似たオブジェクト」(array-like object)と呼ばれます。

```javascript 
var obj = {
  0: 'a',
  1: 'b',
  2: 'c',
  length: 3
};

obj[0] // 'a'
obj[1] // 'b'
obj.length // 3
obj.push('d') // TypeError: obj.push is not a function
``` 

オブジェクトobjは配列のようなオブジェクト しかし、「配列に似たオブジェクト」は配列ではありません。なぜなら、それらは配列特有の手法を持っていないから 。オブジェクトの`obj`には配列の`push`メソッドがなく、このメソッドを使うとエラーが発生します。

「配列に似たオブジェクト」の根本的な特徴は、「length」属性を持っていること 。「length」属性があれば、このオブジェクトは配列に似ていると考えることができます。ただし、この「length」属性は働作値ではなく、メンバーが変わっても変化しません。

```javascript 
var obj = {
  length: 0
};
obj[3] = 'd';
obj.length // 0
``` 

上のコードはオブジェクト`obj`にテンキーが追加されていますが`length`属性は変更されていません。つまり`obj`は配列ではないということ 

典型的な「配列に似たオブジェクト」は関数の`arguments`オブジェクトであり、多くのDOM要素と文字列があります。

```javascript 
// argumentsオブジェクト 
function args() {return arguments} 
var arrayLike = args('a', 'b');

arrayLike[0] // 'a' 
arrayLike.length // 2 
arrayLike instanceof Array // false

DOM要素セット 
var . elts = document getelementsbytagname (' h3 ');
elts.length // 3 
elts instanceof Array // false 

//文字列 
'b' [1] // 'b' 
'abc'.length // 3 
'abc' instanceof Array // false 
``` 

上記のコードには3つの例がありますが、これらは全て配列ではありません(「instanceof」演算子は「false」を返します)。

配列の「slice」は、「配列に似たオブジェクト」を真の配列にすることができます。

```javascript 
var arr = Array.prototype.slice.call(arrayLike);
``` 

真の配列に変換することに加えて、「配列に類似したオブジェクト」が配列を使うもう一つの方法があります。それは、`call()`によって配列をオブジェクトの上に置くこと 。

```javascript 
function print(value, index) {
  console.log(index + ' : ' + value);
}

Array.prototype.forEach.call(arrayLike, print);
``` 

`arrayLike`は配列のようなオブジェクトを表しており、本来は配列の`forEach()`メソッドを使うことはできませんが、`call()`によって`forEach()`を`arrayLike`に接ぎ木して呼び出すことができます。

以下の例は、この手法を使って`arguments`オブジェクトの上で`forEach`メソッドを呼び出すもの 。

```javascript 
// forEachメソッド 
// forEach 
function logArgs() {
  Array.prototype.forEach.call(arguments, function (elem, i) {
    console.log(i + '. ' + elem);
  });
}

// for 
function logArgs() {
  for (var i = 0; i < arguments.length; i++) {
    console.log(i + '. ' + arguments[i]);
  }
}
``` 

つづりも類似の配列の対象であり、だからも用` array . prototype . foreach .コール`遍暦。

```javascript 
Array.prototype.forEach.call('abc', function (chr) {
  console.log(chr);
});
// a
// b
// c
``` 

この方法は、配列をそのまま使うネイティブな「forEach」よりも遅いので、「配列に似たオブジェクト」をまず真の配列に変換してから、配列を直接呼び出す「forEach」の方が良いでしょう。

```javascript 
var arr = Array.prototype.slice.call('abc');
arr.forEach(function (chr) {
  console.log(chr);
});
// a
// b
// c
``` 

## リンク参照 

−アクセルrauschmayer、[arrays in javascript] (http://www.2ality.com/2012/12/arrays.html)
−アクセルrauschmayer、[javascript: sparse arrays vs . dense arrays] (http://www.2ality.com/2012/06/dense-arrays.html)
- Felix Bohm [What They Didn」t Tell You About ES5」s Array]extras] (http://net.tutsplus.com/tutorials/javascript-ajax/what-they-didnt-tell-you-about-es5s-array-extras/)
—ジュリー・ザイチフ [How ECMAScript 5 still does not allow to subclass an]array] (http://perfectionkills.com/how-ecmascript-5-still-does-not-allow-to-subclass-an-array/)