前回導入したCodeSandboxのConsoleを使って、JavaScriptの文法を確認してみる。
基本的な部分は、結構C言語に似ていて、ありがたい。
自分は丸飲み学習ができない。特に言語系は1つマスターしたものに対して、差分を取る形で学習していくのが一番効率よく学ぶことができる。
なので、今回のJavaScriptもC言語との差分を取ることで、少しずつでも前に進んでいければと思っている。
変数
変数の種類は、const, let, varの3つ。
C言語は型がガチガチの言語である。だからこそ、型を見ただけである程度用途が想像できるし、勘違いによる変数の使い方の間違いもかなり防ぐことができる。
型がない言語は世の中にたくさんあるが、JavaScriptも型が3つ(実質的には2つ)しかない中で、よしなに計らってくれるのが、逆に怖い。
変数の名前の付け方
言語によって、また同じ言語でも会社(やプロジェクト)によって書き方のルールは様々だと思うが、色々なサイトを見ていると、JavaScriptではキャメルケースで変数の名前を付けることが多いように見える。
先生に聞いてみると、現場ではJavaScriptの変数はキャメルケース(catNameみたいに先頭小文字、そのあとは単語単位の先頭が大文字)を使うとのこと。
世の中にはたくさんのコーディング規約(コーディングスタイルガイド)がたくさんあるようなので、それっぽいものを選んで読んでおけばいいのかな・・・。
varは再宣言も再代入も可能(ほとんど使わない)
再宣言
再代入
letは再宣言は不可、再代入可能
再宣言
再代入
constは定数なのでプリミティブ型の場合は変更はできない
プリミティブ型
配列やオブジェクトの場合はconstで宣言しても変更可能
配列
ここでちょっと余談。
こんな風に書いても、上と同じ結果になる。
console.log()には落とし穴があるようで、記述したとおりに上から順番に処理されていくわけではないということが判明。
配列の場合はjoin()とsplit()を使って、いったん文字列にしてから配列に戻して渡す方法があるらしいので、join()とsplit()を調べたときに試してみようと思う。
今回の件、まさにドンピシャの記事を教えてもらったので、詳細は下記の@POPOPON(commew)さんの記事参照。(スゴイ)
参考記事:
console.log の落とし穴:console.log にはオブジェクトの参照が渡るので気を付けよう
変数のデータ型
いや、変数の型が3個しかない時点で驚きだけど、データ型の分類としても2種類って・・・。ねえ。
プリミティブ型とオブジェクト型の2種類。
変数のサイズ無視感、ハンパない・・・。(驚愕)
それだけ処理する側が高性能っていうことなんだろうなぁ。
オブジェクト型の変数は、変数の中に値を保持しているわけではなくて、値を格納している場所を示す情報が入っているらしい。
C言語で言うところの、ポインタ的なやつか。
概念の理解は問題ないが、配列=データの場所を示す参照値が入っているというのに慣れないといけない。(うっかりしそう)
数値の精度はどこまで?
数値を扱う場合にいつも気になるのは、精度と最大・最小値。
まずは適当に大きそうな数字と小さそうな数字で計算。
ちっちゃい子が消えたww(どこ行った??)
それなら、忖度した数字ではいかが?
まあ、このくらいは余裕で計算できまっせって感じか。
JavaScriptの数値がどうなっているのか調べる。
MDN Web Docsの「Number.MAX_SAFE_INTEGER」の項目に、こう記載されている。
Number.MAX_SAFE_INTEGER 定数は、JavaScript における安全な整数の最大値 (2^53 - 1) を表します。
もっと大きな整数には、 BigInt を使用することを検討してください。
ということは、JavaScriptの数値はdouble(倍精度浮動小数点数=64ビット)が基準になっているということだ。
そして、その精度は52ビット分。
精度に漏れた分は、下の桁からテキトーになっていく。
使いたい数値が保証精度の範囲内かどうかを調べるには、「Number.isSafeInteger()」というメソッドがあるのでそれを利用する。
だから、さっきちっちゃい子が消えていたのは、ちっちゃい子が精度を保つ52ビット分では表現しきれなかったから。
こういう風に、大きい数字をインクリメントして~、とやってしまうと精度が損なわれるので注意。
オブジェクト型の変数の中身(プロパティ)1つ1つの型は?
前述した、condole.log()の落とし穴で、下記のような結果になってしまうのは理解した。
だが、こう書くと1つ目のconsole.log()に変更前の値が出力されるのはなぜか?
オブジェクトのプロパティを直に指定すると、プリミティブ型として認識されるということなのかな?
2021/11/2追記
RaiseTechのReactコース4週目が終わったところ。現在、引き続きJavaScriptの文法をやっている。
課題をやっているときに、ようやく腹落ちしたので、ここでOutput。
「オブジェクト型の変数を代入すると、参照値を渡すことになる」というのは理解できていたが、上の例で、オブジェクト(getCats)のプロパティ(getCats.type)を代入すると、なぜ値渡しになるのかが理解できていなかった。
これは、C言語のポインタの概念が、理解を邪魔していた。
C言語のポインタは、どこまで行ってもポインタなのだ。ポインタ変数は、一度宣言したらずっとポインタとして使う。そのアドレスにあるデータを読み出す場合は、*つけることによって意識的に値として扱う。
つまり、ポインタかデータかは必ず意識して使うので、参照値と値が無意識に混在することがないのである。
だから、自分が勝手にC言語の概念に当てはめて、JavaScriptのオブジェクトのプロパティは、それがオブジェクト型であれ、プリミティブ型であれ、オブジェクト型(参照値)として認識されるのではないかと思い込んでいたので、腹落ちしていなかった。
JavaScriptの場合は、参照値と値そのもの、というのは、本当に言葉通り、「オブジェクト型は参照値、プリミティブ型は値」だったのだ。
オブジェクトや配列の中にあろうとなかろうと、そのプロパティや要素がオブジェクト型なら参照値、プリミティブ型なら値なのだ。
親子関係は全く関係なかった、ということにようやく気付いた。
例えば、
getCatsはオブジェクト(オブジェクト型)なので参照値
getCatsのプロパティのtype, name, ageはプリミティブ型なので値
getCatsのプロパティのfriendsは配列(オブジェクト型)なので参照値
当然それらを代入する、necoType, necoName, necoAgeはプリミティブ型で、necoFriendsはオブジェクト型だ。
なので、getCats.friendsの配列を書き換えると、necoFriendsも同じ位置を参照しているので、書き換わる。
「オブジェクト型は参照値、プリミティブ型は値」は、素直にそう理解すればよかっただけだった。
ようやく理解できたw
JavaScriptはオブジェクト指向
C言語にはオブジェクト指向がない・・・。(考え方としてないわけじゃないんだけど、基本ないw)
しいて言うなら、構造体がちょっと近いかなと思ったりもするけど、あればもはや型の分類に入るんじゃないかとも思う。
以前にJavaを少しかじったことがあって、概念はそれなりに理解できているけど、実務でオブジェクト指向の言語を使ったことがないので、正直腹落ちしていない。
今後の私に期待(こればっかりだな・・・)。
4ヵ月後に、この記事に「腹落ちした」追記が書けることを祈るばかり。