BigInt
======

Baseline Widely available
-------------------------

This feature is well established and works across many devices and browser versions. It’s been available across browsers since September 2020.

* Learn more
* See full compatibility
* Report feedback
**`BigInt`** は、大きすぎて `number` プリミティブで表すことができない数を表現します。

解説
--

**BigInt 値**は、単に **BigInt** と呼ばれることもありますが、`bigint` プリミティブです。整数リテラルの末尾に `n` を追加するか、`BigInt()` コンストラクターを呼び出し、整数値または文字列値を与えることで生成することができます（ただし `new` 演算子なしで）。


```js
const previouslyMaxSafeInteger = 9007199254740991n;

const alsoHuge = BigInt(9007199254740991);
// 9007199254740991n

const hugeString = BigInt("9007199254740991");
// 9007199254740991n

const hugeHex = BigInt("0x1fffffffffffff");
// 9007199254740991n

const hugeOctal = BigInt("0o377777777777777777");
// 9007199254740991n

const hugeBin = BigInt(
  "0b11111111111111111111111111111111111111111111111111111",
);
// 9007199254740991n
```


BigInt はいくつかの点で Number と似ていますが、重要ないくつかの点が異なります。組み込みの `Math` オブジェクト内のメソッドでは利用できず、演算で Number の値と混ぜることができません。同じ型に統一する必要があります。ただし、BigInt を Number へ変換する際には精度が落ちることがあるので、相互に変換する場合には注意が必要です。

### 型情報

`typeof` の BigInt 値 (`bigint` プリミティブ) に対する評価値は、`"bigint"` となります。


```js
typeof 1n === "bigint"; // true
typeof BigInt("1") === "bigint"; // true
```


BigInt 値は `Object` でラップすることができます。


```js
typeof Object(1n) === "object"; // true
```

### 演算子

以下の演算子は BigInt 値またはオブジェクトでラップした BigInt 値で使用することができます。
```

+ * - % **
```


ビット操作演算子も同様に利用できますが、`>>>`（論理的右シフト）は BigInt が常に符号付きなので除外されます。

同様に、asm.js を壊さないようにするため単項演算子（`+`）にも対応していません。


```js
const previousMaxSafe = BigInt(Number.MAX\_SAFE\_INTEGER);
// 9007199254740991n

const maxPlusOne = previousMaxSafe + 1n;
// 9007199254740992n

const theFuture = previousMaxSafe + 2n;
// 9007199254740993n, this works now!

const multi = previousMaxSafe \* 2n;
// 18014398509481982n

const subtr = multi - 10n;
// 18014398509481972n

const mod = multi % 10n;
// 2n

const bigN = 2n \*\* 54n;
// 18014398509481984n

bigN \* -1n;
// -18014398509481984n
```


`/` 演算子もすべての数値に対して、期待される通りに動作します。ただし、小数の結果をもつ演算では BigInt 値と演算する際に小数が切り捨てられます。小数点以下の桁数は返されません。


```js
const expected = 4n / 2n;
// 2n

const truncated = 5n / 2n;
// 2n, not 2.5n
```

### 比較演算

BigInt 値は Number 値と厳密等価ではありませんが、*等価*にはなります。


```js
0n === 0; // false
0n == 0; // true
```


Number 値と BigInt 値は通常通り比較できます。


```js
1n < 2; // true
2n > 1; // true
2 > 2; // false
2n > 2; // false
2n >= 2; // true
```


BigInt 値と Number 値は配列内に混在させて並べ替えることができます。


```js
const mixed = [4n, 6, -12n, 10, 4, 0, 0n];
// [4n, 6, -12n, 10, 4, 0, 0n]

mixed.sort(); // 既定の並べ替えの動作
// [ -12n, 0, 0n, 10, 4n, 4, 6 ]

mixed.sort((a, b) => a - b);
// 型が混在した減算はできないので動作しない
// TypeError: can't convert BigInt value to Number value

// 適切な数値比較関数を使用した並べ替え
mixed.sort((a, b) => (a < b ? -1 : a > b ? 1 : 0));
// [ -12n, 0, 0n, 4n, 4, 6, 10 ]
```


なお、`Object` にラップされた BigInt は他のオブジェクトと同様の振る舞いをします。同じインスタンス同士が比較された場合にのみ等価となります。


```js
0n === Object(0n); // false
Object(0n) === Object(0n); // false

const o = Object(0n);
o === o; // true
```


Number 値と BigInt 値の型変換は精度が落ちる可能性があるため、次のことを推奨します。

* BigInt 値は、値が 253 を超えることが合理的に予想される場合にのみ使用する。
* BigInt 値と Number 値の間で型変換を行わない。
### 条件式

BigInt 値は次のような場合は Number 値のように動作します。

* `Boolean` へ変換される場合（`Boolean` 関数を使用して）
* 論理演算子の `||`、`&&`、`!` と一緒に使用された場合
* または `if` 文のような条件式の中で使用された場合

つまり、`0n` のみが偽値で、他のすべては真値となります。


```js
if (0n) {
  console.log("Hello from the if!");
} else {
  console.log("Hello from the else!");
}
// "Hello from the else!"

0n || 12n; // 12n
0n && 12n; // 0n
Boolean(0n); // false
Boolean(12n); // true
!12n; // false
!0n; // true
```

### 暗号処理

BigInt で対応している演算は、実行時間が一定ではないので、タイミング攻撃を受ける可能性があります。したがって、緩和要因がなければ JavaScript の BigInt を暗号処理で使うのは危険な可能性があります。非常に一般的な例として、攻撃者は `101n ** 65537n` と `17n ** 9999n` の時間差を計測し、経過時間にもとづいて秘密鍵のような秘匿情報の大きさを推定することができます。もしそれでも BigInt を使用しなければならない場合は、この問題に関する一般的なアドバイスが掲載されているタイミング攻撃のFAQをご覧ください。

### JSON での使用

`JSON.stringify()` を BigInt 値に対して使用すると `TypeError` が発生します。 BigInt 値は既定で JSON のシリアライズに対応していないためです。ただし、`JSON.stringify()` は特別に BigInt 値に対する裏口を残しており、 BigInt の `toJSON()` メソッドを呼び出そうとします（他のプリミティブ値に対してはそうしません）。したがって、自身で `toJSON()` メソッドを実装することができます（組み込みにオブジェクトにパッチを当てることが明確に抑止されていない数少ない例の一つ）。


```js
BigInt.prototype.toJSON = function () {
  return this.toString();
};
```


エラーを発生させるかわりに、`JSON.stringify()` は次のような文字列を生成します。


```js
console.log(JSON.stringify({ a: 1n }));
// {"a":"1"}
```


もし `BigInt.prototype` にパッチを当てたくない場合は、 BigInt 値のシリアライズに `JSON.stringify()` の `replacer` 引数を使うことができます。


```js
const replacer = (key, value) =>
  typeof value === "bigint" ? value.toString() : value;

const data = {
  number: 1,
  big: 18014398509481982n,
};
const stringified = JSON.stringify(data, replacer);

console.log(stringified);
// {"number":1,"big":"18014398509481982"}
```


長整数になることがわかっている値を含む JSON データがある場合は、`JSON.parse` の `reviver` 引数を使って対処することができます。


```js
const reviver = (key, value) => (key === "big" ? BigInt(value) : value);

const payload = '{"number":1,"big":"18014398509481982"}';
const parsed = JSON.parse(payload, reviver);

console.log(parsed);
// { number: 1, big: 18014398509481982n }
```


**メモ:** `JSON.stringify()` の replacer を汎用的にし、すべてのオブジェクトに対して BigInt 値を適切にシリアライズをすることが可能であるのに対し、`JSON.parse()` の reviver は期待するペイロードの形に特化していなければなりません。というのも、シリアライズは*非可逆的*だからです。つまり BigInt を表現する文字列と通常の文字列を区別することはできません。

### BigInt の変換

BigInt を期待する多くの組み込み演算は、まず引数を BigInt に変換します。演算は以下のように要約できます。

* BigInt はそのまま返される。
* `undefined` と `null` は `TypeError` を発生させる。
* `true` は `1n` になり、 `false` は `0n` になる。
* 文字列は整数リテラルを含むかのように解析され、変換される。解析に失敗すると `SyntaxError` が発生する。
* 数値は `TypeError` を発生させ、精度の低下を引き起こす意図しない暗黙の変換を防ぐ。
* シンボルは `TypeError` を発生させる。
* オブジェクトはまず、`[@@toPrimitive]()` （`"number"` をヒントに指定）、`valueOf()`、`toString()` の順にメソッドを呼び出してプリミティブ変換される。その結果のプリミティブは BigInt に変換される。

JavaScript でほぼ同じ効果を得る最良の方法は、`BigInt()` 関数を使うことです。`BigInt(x)` は同じアルゴリズムを使って `x` を変換しますが、数値が `TypeError` を発生させず、整数であれば BigInt に変換される点が異なります。

BigInt を期待する組み込み演算は、変換後に BigInt を固定幅に切り詰めることが多いことに注意してください。これは `BigInt.asIntN()` と `BigInt.asUintN()` 、および `BigInt64Array` と `BigUint64Array` のメソッドも含みます。

コンストラクター
--------

`BigInt()`

新しい BigInt 値を生成します。

静的メソッド
------

`BigInt.asIntN()`

BigInt 値を符号付き整数値に丸め、その値を返します。

`BigInt.asUintN()`

BigInt 値を符号なし整数値に丸め、その値を返します。

インスタンスプロパティ
-----------

以下のプロパティは `BigInt.prototype` で定義されており、すべての `BigInt` インスタンスで共有されます。

`BigInt.prototype.constructor`

インスタンスオブジェクトを作成したコンストラクター関数。`BigInt` インスタンスの場合、初期値は `BigInt` コンストラクターです。

`BigInt.prototype[@@toStringTag]`

`@@toStringTag` プロパティの初期値は文字列 `"BigInt"` です。このプロパティは `Object.prototype.toString()` で使われます。ただし、 `BigInt` も独自の `toString()` メソッドをもつので、`thisArg` として BigInt を指定して `Object.prototype.toString.call()` を呼び出さないかぎりこのプロパティは使われません。

インスタンスメソッド
----------

`BigInt.prototype.toLocaleString()`

この BigInt 値の言語に合わせた表現の文字列を返します。`Object.prototype.toLocaleString()` メソッドを上書きします。

`BigInt.prototype.toString()`

この BigInt 値を指定された基数で表現した文字列を返します。`Object.prototype.toString()` メソッドを上書きします。

`BigInt.prototype.valueOf()`

この BigInt 値を返します。`Object.prototype.valueOf()` メソッドを上書きします。

例
-

### 素数の計算


```js
// 渡された BigInt が素数であった場合は true を返します
function isPrime(p) {
  for (let i = 2n; i \* i <= p; i++) {
    if (p % i === 0n) return false;
  }
  return true;
}

// 引数として BigInt 値を取り、 nth 番目の素数を BigInt 値として返します。
function nthPrime(nth) {
  let maybePrime = 2n;
  let prime = 0n;

  while (nth >= 0n) {
    if (isPrime(maybePrime)) {
      nth--;
      prime = maybePrime;
    }
    maybePrime++;
  }

  return prime;
}

nthPrime(20n);
// 73n
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-bigint-objects |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* `Number`
* `Number.MAX_SAFE_INTEGER`