JavaScript データ型

###JavaScriptのデータ型

ここで紹介するのは以下の六つのプリミティブ型

* undefined
* null
* Boolean
* Number
* String
* Symbol

###Undefined
Undefined型には「undefined」というリテラル値のみ。
var又はletで変数を宣言して、初期化されていない状態は「undefined」になります。

```javascript
let messge;
console.info(message);//undefined
console.info(name);//例外
```

宣言されていない変数に対して行える操作はtypeofのみ

```javascript
let name;
console.info(typeof name);//undefined
console.info(typeof age);//undefined
```
ここはちょっと要注意、
宣言されて初期化していない変数と宣言されていない変数にtypeof操作すると両方とも[undefined]になります。

###Null
Null型もUndefined型と同じ、「null」というリテラル値のみ。
「null」というのはオブジェクトを指していないことを表します

```javascript
let letNull = null;
console.info(typeof letNull);//object、見ての通り「null」はオブジェクトです
```

※「undefined」も「null」から派生しているが、違う物なので。以下のプログラムを見れば分かると思う。

```javascript
console.info(undefined == null);//true
console.info(undefined === null);//false
```

###Boolean

Boolean型以外のデータ型をBoolean型に変換する際のルール

String型：空文字以外は「true」
Number型：0以外は「true」(マイナスとインフィニティも含まれる)
Object型：null以外は「true」
Undefined型：undefinedは「false」、N/Aは「true」

###Number
整数の変数は基本的に十進数のリテラルで定義するのですが、十進数以外のリテラルでも定義可能
八進数の場合は必ず0から始まる、その後八進数の数字を続く

```javascript
let num1 = 55;//整数
let num2 = 070;//八進数の「70」と認識され十進数の56をセットされる
let num3 = 079;//9が八進数ではないので、0を無視して十進数の79をセット
let num4 = 08;//上記と同様、0を無視して十進数の8をセット
```

だが厳格モードではプレフィックスの「0」がsyntaxエラーになるため「0o(八進数)」、「0x(十六進数)」で定義しないといけない。

```javascript
'use strict';
let num1 = 55;//整数
console.log(num1);
let num2 = 0o70;//八進数、十進数のの56でセット
console.log(num2);
let num3 = 0o79;//9が八進数ではないので、エラー
console.log(num3);
let num4 = 0o8;//上記と同様、エラー
console.log(num4);
let num5 = 0xA;//十六進数、十進数の10でセット
console.log(num5);
```

浮動小数点数を定義するときはこうなります

```javascript
let floatNum1 = 1.1;
let floatNum2 = 0.1;
let floatNum3 = .1;  //有効ですがお勧めしない
```

ECMAScriptでは常に浮動小数点数を整数に変換しようとするので、下記の定義では整数として処理される

```javascript
let floatNum4 = 1.;  //小数点以降はないので、整数の1として処理
let floatNum5 = 10.0; //小数点以降は0なので、整数の10として処理
```

浮動小数点数は算術計算の際下記のようなの精度上の問題があります、これは全部ではないので要注意

```javascript
console.log(0.1+0.1+0.1);  //0.30000000000000004
console.log(1+0.1+0.1);    //1.2000000000000002
console.log(1+0.05+0.05+0.05);  //1.1500000000000001
```
これはECMAScriptだけの問題ではなく、IEEE 754標準を利用する他言語にも同じ問題が存在する

####Numberによる数値変換

```javascript
console.log(Number(true));              // 1
console.log(Number(false));             // 0
console.log(Number(5));                 // 5
console.log(Number(null));              // 0
console.log(Number(undefined));         // NaN
console.log(Number("11"));              // 11
console.log(Number("-11"));             // -11
console.log(Number("11.1"));            // 11.1
console.log(Number("011"));             // 11
console.log(Number("0xA"));             // 10
console.log(Number(""));                // 0
console.log(Number("11a"));             // NaN

let objToNum1 = new Object();
objToNum1.valueOf = () => "10";
objToNum1.toString = () => "20";
console.log(Number(objToNum1));         // 10

let objToNum2 = new Object();
objToNum2.valueOf = () => "10a";
objToNum2.toString = () => "20";
console.log(Number(objToNum2));         // NaN

let objToNum3 = new Object();

objToNum3.toString = () => "20";
console.log(Number(objToNum3));          // 20

let objToNum4 = new Object();
console.log(Number(objToNum4));         // NaN
```
Numberでオブジェクトを変換する際はまずvalueOfの値で変換する、valueOfがない場合はtoStringの値で変換する、両方とも存在しない場合はNanになります。

####parseIntによる数値変換

```javascript
console.log(parseInt("   1234blue")); // 1234 
console.log(parseInt("")); // NaN 
console.log(parseInt(" 0xA")); // 10
console.log(parseInt(22.5)); // 22 
console.log(parseInt("70")); // 70
console.log(parseInt("0xf")); // 15
console.log(parseInt("f",16)); // 15
console.log(parseInt("fl",16)); // 15、「l」が有効な16進数ではないため無視
```
parseIntでは先頭のスペースが無視され、最初の数字又は「+ -」から解析していく、文字列の最後又は数字以外の文字まで終了。後続の数字以外の文字は皆無視される。

####parseFloatによる数値変換

```javascript
console.log(parseFloat(" 1234blue")); // 1234
console.log(parseFloat(" 0xA")); // 0 
console.log(parseFloat(" 22.5")); // 22.5 
console.log(parseFloat(" 22.34.5")); // 22.34 
console.log(parseFloat(" 0908.5")); // 908.5 
console.log(parseFloat(" 3.125e7")); // 31250000
```
parseFloatでは先頭の「0、スペース」が無視される、二番目の小数点から以降は無視される。十進数のみ処理するのでそれ以外は「0」


###String

```javascript
let num = 10; 
console.log(num.toString()); // "10" 
console.log(num.toString(2)); // "1010" 
console.log(num.toString(8)); // "12" 
console.log(num.toString(10)); // "10" 
console.log(num.toString(16)); // "a"
```
数値のtoString関数を使って10進数以外の文字列を得る事が可能。

```javascript
console.log(String(null)); // "null" 、toStringを利用できないのでこうする必要がある
console.log(String(undefined)); // "undefined"  、toStringを利用できないのでこうする必要がある
```

###Symbol

唯一の標識を定義するためのデータ型、例えばObjectに絶対に重複する事のないプロパティを定義したい時はSymbolを使うとよい。
Symbolは絶対に重複することのないプロパティ名だと考える方が分かりやすいかと。

Symbolの定義は

```javascript
let s1 = Symbol();
let s2 = Symbol("s2");  //パラメータはコメントみたいな物だから、特に気にしなくてもいい
let gs1 = Symbol.for("global symbol"); //グローバルSymbolレジストリリスト内で利用可能なシンボルを生成します、既に存在したらそれを返す

let symbolObj = {
　[s1]:'普通のシンボル',
　[s2]:'パラメータ付きのシンボル'
};
symbolObj[gs1]='グローバルシンボル';
console.log(symbolObj);//{Symbol(): "普通のシンボル", Symbol(s2): "パラメータ付きのシンボル", Symbol(global symbol): "グローバルシンボル"}
```

シンボルはコンストラクタとして使用することはできない

```javascript
let b = new Boolean();
let n = new Number();
let s = new String();
let sym = new Symbol();//type errorになります
let mySymbol = Symbol();//このようにシンボルを定義する
```

組込シンボルに関しては[ここから参照](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Symbol)