はじめに
業務でJavaScriptを触り始めて約1年が経ちました。
業務開始 = JavaScript歴なので最近やっと実装に必要なことは多少複雑なものでも、調べつつ進められるというレベルになってきたと感じています。
とにかくタスクをこなすのに必死で、言語仕様の理解をおざなりにしていたので、改めて根本的なことから学び直しています。
TypeScriptも触り始めるようになり、内包されているJavaScriptについての理解がより必要だと思ったのもきっかけの一つです。
データ型について整理をする中で、プリミティブ値についておや??と思うことがありました。
(とても基本的なことですが)
プリミティブ値
MDN web Docs から引用。
オブジェクトを除くすべての型は不変の値 (つまり、変更できない値) として定義されています。例えば文字列は(C 言語とは異なり)不変です。これらの型の値を、プリミティブ値と呼びます。
つまりオブジェクトではない
全ての型の値がプリミティブ値です。
逆説的に言えば、
プリミティブ値ではない
ものは全てオブジェクトです。
JavaScriptでは下記がプリミティブ値です。
-
Number (ex: 123, -10, 0x, 0o, 0b, 1.23, 1.2e3)
-
String (ex: 'abc', "efg",
hij ${hoge}
) -
Boolean (ex:true, false)
-
Null (null)
-
Undefined (undefined)
-
BigInt (ex: 1n)
-
Symbol (一意で不変のプリミティブ値)
※ シンボルの詳細はこちら
プリミティブ値の値を定義する時には、リテラルを使うます。
簡単にいうと、数値や文字列...etc のベタ書きです。
プリミティブ値はオブジェクトではない
プリミティブ値はオブジェクトではない ということはインスタンスメソッドも持たないということです。
へぇ〜。と思っていましたが、違和感を持ちました。
const pri = 'Qiita'.indexOf('Q',0 ,1);
console.log(pri); // 0
'Qiita'
は文字列リテラルでプリミティブ値です。
なのにindexOf()
メソッドが使えます。
??
プリミティブ値はオブジェクトではない
インスタンスメソッドも持たない
なんでメソッドか使えるのでしょうか....。
プリミティブ値からラッパーオブジェクトへの自動変換
文字列リテラルとString型を比較をしてみます。
const a = 'Qiita';
const b = new String('Qiita');
console.log(a === b); // false
console.log(a === b.valueOf); true
単純にa === b
でプリミティブ値のa
とString型のb
を比較するともちろん一致しません。
a === b.valueOf
という比較では、オブジェクトが持つvalueOf()が指定したオブジェクトのプリミティブ値を返すので一致します。
JavaScripteではプリミティブ値に対してアクセスするときに、
それぞれに対応するラッパーオブジェクト
に自動変換されます。
先ほどの'Qiita'.indexOf('Q',0 ,1)
は
'Qiita'.indexOf('Q',0 ,1);
↓
(new String('Qiita')).indexOf('Q',0 ,1);
文字列リテラルというプリミティブ値から、Stringオブジェクトに自動で変換されます。
'Qiita'
がindexOf()
メソッドを使えるのは、変換後のStringオブジェクトとしてインスタンスメソッドを実行しているためです。
このようにプリミティブ値に対応するオブジェクトに変換されるため、
リテラルでもメソッドが使えるようになります。
最後に
ものすごく初歩的なことですが、とりあえず書ければいいという段階から抜け出すためにこれからも言語仕様の理解に勤しみたいと思います。
理解が浅い部分があるかと思いますが、最後まで読んで頂きありがとうございました。