Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save think49/6f721683a0b54760ce1d9111807a16ce to your computer and use it in GitHub Desktop.
Save think49/6f721683a0b54760ce1d9111807a16ce to your computer and use it in GitHub Desktop.
[JavaScript] Number 型に変換する方法まとめ

Number 型に変換する方法まとめ

ECMAScript 2017

ECMAScript とは JavaScript の根幹となる仕様の名称です。 型変換は ECMAScript 仕様に準じており、ここでは ECMAScript 2017 に沿った説明をしています。

数値リテラル (NumericLiteral)

ECMAScript 2017 では Number 型を表すリテラル表現として、NumericLiteral の文法を定義しており、NumericLiteral は更に次の4種類に分かれます。

'use strict';
/**
 * DecimalLiteral
 * 整数部分が「"0" のみ」もしくは「[1-9] で始まる10進数」となる10進数値
 */
console.log(0);      // 0
console.log(10);     // 10
console.log(1.234);  // 1.234

/**
 * BinaryIntegerLiteral
 * "0b" もしくは "0B" で始まる2進数値 (ES6 規定) ※IE11は未対応
 */
console.log(0b10); // 2
console.log(0B10); // 2

/**
 * OctalIntegerLiteral
 * "0o" もしくは "0O" で始まる8進数値 (ES6 規定) ※IE11は未対応
 */
console.log(0o10); // 8
console.log(0O10); // 8

/**
 * HexIntegerLiteral
 * "0x" もしくは "0X" で始まる16進数値
 */
console.log(0x10); // 16
console.log(0X10); // 16

8進数リテラルにはレガシーな書き方が一つあります。 (この記法は ES3 で仕様から取り除かれましたが、後方互換性の為に記述だけは残り、ES5 になって Strict Mode で使えなくなりました。)

<script>
/**
 * LegacyOctalIntegerLiteral
 * "0" から始まる数値は8進数として扱う
 */
console.log(010); // 8
</script>
<script>
'use strict';
010; // SyntaxError: Octal literals are not allowed in strict mode.
</script>

型変換 (Type Conversion)

ECMAScript では型変換の外側には出てこない内部命令をいくつか定義しています。

ToNumber

ToNumber は次の変換テーブル規則によって、Number 型に変換します。

引数の型 結果
Undefined NaN を返す
Null +0 を返す
Boolean 引数が true なら 1 を返し、引数が false なら +0 を返す
Number 引数をそのままの状態で返す(型変換をしない)
String 前後の空白文字を削除し、空文字ならば +0 を返す。NumericLiteral とほぼ同じ文法を持つ StringNumericLiteral を構文解析し、Number 値を返す(※)
Symbol TypeError 例外を投げる
Object ToNumber(ToPrimitive(arg, "number")) を呼び出す

StringNumericLiteralNumericLiteral はよく似ていますが、次の違いがあるようです。

NOTE2: Some differences should be noted between the syntax of a StringNumericLiteral and a NumericLiteral:

  • A StringNumericLiteral may include leading and/or trailing white space and/or line terminators.
  • A StringNumericLiteral that is decimal may have any number of leading 0 digits.
  • A StringNumericLiteral that is decimal may include a + or - to indicate its sign.
  • A StringNumericLiteral that is empty or contains only white space is converted to +0.
  • Infinity and -Infinity are recognized as a StringNumericLiteral but not as a NumericLiteral.

(日本語訳) StringNumericLiteralの構文とNumericLiteralの構文にはいくつかの違いがあります。

  • StringNumericLiteral には、先頭または末尾に空白文字もしくは行終端文字が含まれます(訳注: 先頭/末尾の空白文字及び行終端文字は取り除かれます)
  • 10進数の StringNumericLiteral は先頭に任意の数の 0 を持つことができます(訳注: StrDecimalLiteral のことです。通常の数値リテラルにおける DecimalLiteral では先頭に 0 を持つ10進数値を記述した場合、Strict Mode では SyntaxError 例外を返し、非Strict Mode では後方互換性の為の機能として8進数リテラルと解釈されます)。
  • 10進数の StringNumericLiteral には、符号を示す + または - が含まれます。
  • Infinity-InfinityStringNumericLiteral として認識されますが、NumericLiteral として認識されることはありません(訳注: Infinity はコード文中ではグローバル変数として定義されており、数値リテラル表現ではありません)。

Number(value)

ToNumber を呼び出す事で Number 型に変換する、最も基本的な関数です。 「暗黙の型変換」で Number 型に変換される時には、ToNumber が呼び出されます。 (整数値に変換する場合には ToInteger を使用するなど、機能別に多少の違いはありますが、ToInteger も初めの処理で ToNumber を呼び出しています)

'use strict';
console.log(Number('\n 1 \n'));     // 1 (先頭/末尾の空白文字及び行終端文字は無視されます)
console.log(Number(''));            // 0 (空文字には 0 を返します)
console.log(Number(undefined));     // NaN
console.log(Number(null));          // 0
console.log(Number(true));          // 1
console.log(Number(false));         // 0
console.log(Number(new Number(1))); // 1
console.log(Number({}));            // NaN
console.log(Number({valueOf: function (){ return 1; }}));   // 1
console.log(Number({valueOf: function (){ return '1'; }})); // 1
console.log(Number(Symbol()));      // TypeError: Cannot convert a Symbol value to a number

+arg

+ 演算子の前方に式(Expression)が存在しない場合、後続する式(Expression)を ToNumber によって、Number 型に変換します。 変換ルールは「Number」もしくは「ToNumber」の節を参照して下さい。

'use strict';
console.log(+''); // 0

parseInt (string, radix)

parseInt() は第一引数を ToString によって String 型に変換し、第二引数に与えられた基数を元に「N進数」の文字列として構文解析後、整数値の Number 型に変換します。

  • 第二引数に指定可能な基数の範囲は「2~36」です
  • 先頭の先頭/末尾の空白文字及び行終端文字は読み飛ばされます(ex: " 10" は "10" と解釈される)
  • 数値文字列に後続する「数値以外の文字列」は読み飛ばされます(ex: "10px" は "10" と解釈される)
  • 第二引数が省略され、先頭が "0x" もしくは "0X" で始まっている場合、16進数値として解釈されます
'use strict';
/**
 * 第二引数を指定した場合
 */
console.log(parseInt('10', 8));     // 8
console.log(parseInt('FF', 16));    // 255
console.log(parseInt('0x10', 10));  // 0
console.log(parseInt('Z0', 36));    // 1260
console.log(parseInt('10', 1));     // NaN
console.log(parseInt('10', 37));    // NaN

/**
 * 第二引数を省略した場合
 */
console.log(parseInt('\n 1 \n'));     // 1 (先頭/末尾の空白文字及び行終端文字は無視されます)
console.log(parseInt('0x10'));        // 16 (第二引数が省略され、先頭が "0x" の場合は16進数として解釈されます)
console.log(parseInt('1.234'));       // 1 (先頭の整数部分だけを Number 型に変換します)
console.log(parseInt(''));            // NaN
console.log(parseInt(undefined));     // NaN
console.log(parseInt(null));          // NaN
console.log(parseInt(true));          // NaN
console.log(parseInt(false));         // NaN
console.log(parseInt(new Number(1))); // 1
console.log(parseInt({}));            // NaN
console.log(parseInt({valueOf: function (){ return 1; }}));   // NaN
console.log(parseInt({valueOf: function (){ return '1'; }})); // NaN
console.log(parseInt({toString: function (){ return '1'; }})) // 1
console.log(parseInt(Symbol()));      // TypeError: Cannot convert a Symbol value to a number

parseInt() は機能的な誤解の多い関数です。 ES3 までの parseInt() は、第二引数が省略された状態で「0 から始まる数値文字列」を8進数として解釈する仕様でした。

console.log(parseInt('010'));  // 8 (ES3 では "0" から始まる数値は8進数として解釈された)

この仕様は多くの人が混乱した為、ES5 で「0 から始まる数値文字列」を10進数として解釈するよう修正が加えられました。 (合わせて、「0から始まる8進数リテラル表記」は Strict Mode で禁止されました)

console.log(parseInt('010'));  // 10 (ES5 では "0" から始まる数値も10進数として解釈される)

また、CSSで使われる単位付き数値文字列の単位を落として Number 型へ変換する用途として、parseInt() は良く使われていました。

console.log(parseInt('10px'));  // 10

これは期待通りに動作しますが、先述の「"0" から始まる数値」や「"0x" から始まる数値」の罠があった為、第二引数を必ず指定するよう注意が促されました。 しかしながら、CSSで扱われる px 等の多くの値は小数値を取ることが出来る仕様であり、parseInt() よりも parseFloat() がふさわしい事はあまり知られていないようです。 parseFloat() には基数変換機能がない為、第二引数指定漏れによる不具合が誘発されません

parseFloat (string)

parseFloat() は第一引数を ToString によって String 型に変換し、浮動小数点数値である Number 型の値を返します。

  • parseInt() と違い、小数を扱えます(整数も扱えます)
  • parseInt() と違い、基数変換機能はありません
'use strict';
console.log(parseFloat('\n 1 \n'));     // 1 (先頭/末尾の空白文字及び行終端文字は無視されます)
console.log(parseFloat('0x10'));        // 0 ("0x" で始まる文字を16進数として解釈しません)
console.log(parseFloat('1.234'));       // 1.234 (小数を正しく認識します)
console.log(parseFloat(''));            // NaN
console.log(parseFloat(undefined));     // NaN
console.log(parseFloat(null));          // NaN
console.log(parseFloat(true));          // NaN
console.log(parseFloat(false));         // NaN
console.log(parseFloat(new Number(1))); // 1
console.log(parseFloat({}));            // NaN
console.log(parseFloat({valueOf: function (){ return 1; }}));   // NaN
console.log(parseFloat({valueOf: function (){ return '1'; }})); // NaN
console.log(parseFloat({toString: function (){ return '1'; }})) // 1
console.log(parseFloat(Symbol()));      // TypeError: Cannot convert a Symbol value to a string

Number.parseInt (string, radix) (※ES6)

Number.parseInt()parseInt() と同じ関数を返します。 この関数は ECMAScript 2015 (ECMA-262 6th Edition) で定義されました。

Number.parseFloat (string) (※ES6)

Number.parseFloat()parseFloat() と同じ関数を返します。 この関数は ECMAScript 2015 (ECMA-262 6th Edition) で定義されました。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment