💡

【JS】本当に理解するJavaScript 〜プリミティブ編〜

2022/11/07に公開

ということで、早速ですが問題です。
海外でのJavaScriptエンジニアの面接などでこのような問題が出されることがあるようです。

問題:console.logの結果はどのようになるでしょうか?

let person = "alice"
person[0] = "A"
console.log(person)

 
 

いかがでしょうか?
何の迷いもなく、100%の自信を持って回答と根拠が浮かんでいるでしょうか?
では早速答えを見ていきましょう。

正解はこちら
let person = "alice"
person[0] = "A"
console.log(person)
>> "alice"

 
 
 
 
 
 
 
 
 
 
 
 

正解できたでしょうか?
答えに少しでも迷ってしまった方は今一度プリミティブ値について理解を深めていきましょう。

プリミティブ値はイミュータブルである

いきなりですが、これがこの問題を正しく答えるための必要な知識であり、JSの世界を理解するために必要不可欠な知識です。
順に理解していきましょう。

プリミティブ値とは

まずはざっとmozillaのページでざっと確認します。

https://developer.mozilla.org/ja/docs/Glossary/Primitive

JavaScript において、プリミティブ (primitive、プリミティブ値、プリミティブデータ型) はオブジェクトでなく、メソッドを持たないデータのことです。 6 種類のプリミティブデータ型があります。文字列、数値、BigInt、真偽値、undefined、そしてシンボル (ECMAScript 2016 で追加) です。
すべてのプリミティブ値は、イミュータブル (immutable) 、つまり変更できません。変数には新しい値を再割り当てすることができますが、既存の値については、オブジェクト、配列、関数が変更できるのに対して、プリミティブ値は変更することができません。

以下の6種類がJavaScriptにおけるプリミティブ値です。

  • undefined
  • boolean
  • number
  • bigint
  • string
  • symbol

symbolやbigintはほとんど出てこないので扱いません。
こんなのがあるのか程度に覚えておくと良いと思います。

値がどの種類なのかはtypeofメソッドを使うと確認することができます。

// undefined
let hoge
console.log(typeof(hoge)); // "undefined"
console.log(typeof(undefined)); // "undefined"

// boolean
console.log(typeof(true)); // "boolean"
console.log(typeof(false)); // "boolean"

//number
console.log(typeof(28)); // "number"
console.log(typeof(3.14)); // "number"
console.log(typeof(NaN)); // "number"

//string
console.log(typeof("こんにちは")); // "string"
console.log(typeof('')); // "string"

補足

booleanはtruefalseの2種類しかありません。
numberに出てきているNaNですが、Not a Numberの略で0/0など数値にできない結果となる場合にこの値になります。
間違いやすいですがこれもnumberです。

続いてイミュータブルとは何かを理解しましょう。

値自体の変更はできない(=イミュータブル)

イミュータブルは日本語で「突然変異」と訳されますが、チェンジの大げさな言い方と捉えれば良いかと思います。
コードを書く上で値を変えるということは突然変異と言ってしまうくらい大きな問題となることがある、という意味が込められているような気もします。(所感)

まずは変数を定義するときに何が起きているかをイメージを確認しながら理解していきます。
私たちのコードの世界(変数)とJSの世界を分けて考えます。

let person = "alice"

上記のコードは以下のように表現できます。

変数定義

私たちのコードの世界ではpersonという変数が定義されました。
そしてJSの世界ではaliceという値が誕生しました。
JSの世界では値が誕生するとその値は死ぬまでaliceであり、alice以外の何者にもなれません。
 
そして私たちの世界に定義された変数とJSの世界に生まれた値を繋ぐのが矢印(=)です。
この矢印が私たちの世界とJSの世界を繋ぐ唯一の手段です。
 
私たちは新たにJSの世界に値を生み出すことができ、その値と既に定義されている変数を矢印で繋ぎなおすことができます。

let person = "alice"
person = "bob"

変数再定義

JSの世界にaliceという値はあるのですが、私たちの世界とは繋がり(参照)が消え、見えなってしまいました。(JSの世界には値はあるイメージです。)

ではもう一度最初に出した問題を見てみましょう。

let person = "alice"
person[0] = "A"
console.log(person)

personがAliceを参照するには、結果がAliceとなるような値を返す関数を実行すれば良いことになります。
先頭の文字を大文字にする方法はいろいろありますが一例を以下に記載します。

 person = person.charAt(0).toUpperCase() + person.slice(1)
 console.log(person)
 >> Alice

まとめ

プリミティブ値はイミュータブルであり、値自体は変えられない。変えられるのは変数の参照先である

ということになります。読んでいただきありがとうございました!

Discussion