概要
- JavaScript の値は大きく プリミティブ(原始)型 と オブジェクト型 に分かれます。主なプリミティブ:
Number,BigInt,String,Boolean,undefined,null,Symbol。 Number,String,Booleanには ラッパーオブジェクト(new Number(...)等)が存在する。プリミティブには通常プロパティやメソッドが無いが、メソッド呼び出し時に JS エンジンが一時的なオブジェクト(ラッパー)を作って処理する(=オートボクシング / autoboxing)。undefinedとnullにはラッパーオブジェクトは無く、メソッドやプロパティアクセスはTypeErrorになる。
仕組み(オートボクシング) — どう動くか
例:
let s = "hello";
console.log(typeof s); // "string" (プリミティブ)
console.log(s.toUpperCase()); // "HELLO"
JavaScripttoUpperCase() を呼ぶとき、エンジンは内部で一時的に new String(s) のようなオブジェクトを作り、そのオブジェクトのメソッドを呼び終えると破棄します。つまり見かけ上はプリミティブでもメソッドが使えるが、恒久的にオブジェクト化されるわけではありません。
代表的な具体例と結果(重要)
1) 数値リテラルでメソッドを呼ぶときの小テク
(1).toString(2) // "1"
1..toString(2) // "1" ← 1. は小数点と解釈され、次の . がプロパティアクセス
// 1.toString() は構文エラーになる(1. がないので)
JavaScript2) 一時オブジェクトにプロパティを付けても残らない
let str = "hi";
str.foo = 123;
console.log(str.foo); // undefined
JavaScript理由:str.foo = 123 時に一時的な String オブジェクトが作られるが、代入後すぐ破棄されるため永続化しない。
3) new を使うとオブジェクトになる(落とし穴)
let p = 0;
let o = new Number(0);
console.log(typeof p); // "number"
console.log(typeof o); // "object"
console.log(p === o); // false (型が違う)
console.log(p == o); // true (== は型変換して値が等しい)
JavaScript4) Boolean の罠(典型)
let bPrim = false;
let bObj = new Boolean(false);
if (bPrim) console.log("prim true"); else console.log("prim false");
// -> "prim false"
if (bObj) console.log("obj true"); else console.log("obj false");
// -> "obj true" ← オブジェクトは truthy
JavaScriptnew Boolean(false) は中身は false だがオブジェクトなので if などの条件判定では 常に truthy に見えます。バグになりやすいです。
5) undefined/null はメソッドを持たない
let u = undefined;
u.toString(); // TypeError: Cannot read properties of undefined
JavaScript6) BigInt, Symbol と new
BigIntとSymbolは コンストラクタではないためnew BigInt(...)/new Symbol(...)は使えません(TypeError)。BigInt(123)やSymbol("x")はプリミティブを返します。
比較・等価性の注意点
===は型と値の厳密比較。ラッパーオブジェクトはtypeofが"object"なので、プリミティブと===で等しくなりません。==は型変換(抽象的等価性)を行うため、new Number(1) == 1はtrueになることがある(オブジェクトがプリミティブに変換されるため)。- つまり
new Number(0) === 0 // falseだがnew Number(0) == 0 // trueになるケースがあり、混乱しやすい。普段は===を推奨。
実務での推奨(ベストプラクティス)
new Number,new String,new Booleanを使わない。
ほとんどのケースで不要・有害です。プリミティブ(42,"abc",true)を使うか、型変換が必要ならNumber(x),String(x),Boolean(x)を使ってください(newを付けない)。- 真偽判定は
Boolean(x)または!!xを使う。new Boolean(x)はオブジェクトで truthy なので誤りの元。 - 型チェックは
typeof/Array.isArray/instanceofを使い分ける(オブジェクト化されるとtypeofが変わる点に注意)。 - メソッドアクセスは気にせずプリミティブのままでOK。 JS が内部で一時オブジェクトを作ってくれるので
"abc".toUpperCase()のように普通に書いて構いません。 - 数値リテラルのメソッド呼び出しは
(1).toString()や1..toString()のように書く(構文エラー回避)。 null/undefinedに対してプロパティやメソッド呼び出しをしない(事前チェックをする)。
よくある落とし穴(まとめ)
new Boolean(false)を if に入れると常に真になる → バグ- プリミティブにプロパティを設定しても残らない → 期待しないこと
typeofが"object"になって型判定が混乱する(ラッパーを作らないことで回避)==の自動型変換で思わぬ真偽になる →===を使う
追加の小ネタ・補足
- 値を文字列化したいときは
String(x)、数に変換したいときはNumber(x)/parseInt/parseFloatを使う。Boolean(x)で真偽に変換、または!!x。 Object(value)を使うと明示的にラッパーオブジェクトを作れますが(Object(3)->new Number(3)相当)、普通は不要です。NaNの比較は注意:NaN !== NaN。等価判定にはNumber.isNaN()やObject.is()を使う。
まとめ
- 「プリミティブ値にメソッドを呼べる」のは JS が必要なときだけ一時オブジェクトを作るから(オートボクシング)。
new Number/String/Booleanは 作らない。混乱とバグの元。undefinedとnullはラッパーを持たない → それらに対するアクセスはエラーになる。- 実務ではプリミティブを使い、明示的変換は
Number(),String(),Boolean()を使う。

