プログラミング経験者であるあなたにとって、変数の概念やデータ型の存在自体は目新しいものではありません。しかし、JavaScriptには「動的型付け」や「歴史的経緯による特殊なスコープ仕様」、「独特な型変換」といった、他言語経験者が特に躓きやすいポイントがあります。
本章では、モダンなJavaScript(ES6以降)における標準的な記述方法を中心に、レガシーな仕様との違いや、バグを生みやすい落とし穴について解説します。
現代のJavaScript開発において、変数宣言のルールは非常にシンプルです。
「基本は const、再代入が必要な場合のみ let を使い、var は決して使わない」 これが鉄則です。
ES6(2015年)で導入された const と let は、C++やJava、C#などと同様にブロックスコープを持ちます。
なぜ var を使うべきではないのでしょうか。それは var が関数スコープであり、意図しない変数の共有や「巻き上げ(Hoisting)」によるバグを引き起こしやすいからです。
以下のコードで、スコープの違いを確認してみましょう。
function checkScope() {
if (true) {
var functionScoped = "I am visible outside this block";
let blockScoped = "I am NOT visible outside this block";
const constantValue = "I am also block scoped";
}
console.log("var output:", functionScoped); // 参照可能(関数スコープのため)
try {
console.log("let output:", blockScoped); // ReferenceError
} catch (e) {
console.error("let error:", e.message);
}
}
checkScope();node scope_demo.jsvar output: I am visible outside this block let error: blockScoped is not defined
JavaScriptは動的型付け言語であり、変数は特定の型に紐付きませんが、値自体は型を持っています。JavaScriptの値は大きく分けて「プリミティブ型」と「オブジェクト(参照)型」に分類されます。
プリミティブ型はイミュータブル(変更不可)であり、以下の7種類が存在します。
true または falseNumber型では表現できない巨大な整数を扱う型(末尾に n)この章では、まず最もよく使う String / Number / Boolean / undefined / null を順に見ていきます。Symbol と BigInt は用途が限定的なため、ここでは「プリミティブ型の一種」であることだけ押さえれば十分です。
JavaScriptの文字列は、シングルクォート (') またはダブルクォート (") で作成します。
また、バッククォート (`) で囲むテンプレートリテラルを使うと、変数や式を文字列に埋め込めます。文字列の連結(+)より読みやすくなることが多いため、こちらを使うのが一般的です。
>) の後にコマンドを入力し、Enterキーで実行します。> const name = "Ada";
undefined
> const language = 'JavaScript';
undefined
> // + で連結
> "Hello, " + name + "!"
'Hello, Ada!'
> // テンプレートリテラルで埋め込み
> `Hello, ${name}!`
'Hello, Ada!'
> // 式も埋め込める
> `${language}は${10 + 5}日で入門できます`
'JavaScriptは15日で入門できます'
JavaScriptの数値は Number 型で表され、整数と小数を区別しません。どちらも同じ number として扱われます。
四則演算は直感的に行えます。べき乗は **、剰余は % を使います。
>) の後にコマンドを入力し、Enterキーで実行します。> const a = 10; // 整数 undefined > const b = 3.14; // 小数 undefined > typeof a 'number' > typeof b 'number' > 10 + 3 13 > 10 / 3 3.3333333333333335 > 10 % 3 1 > 2 ** 4 16 > 0.1 + 0.2 0.30000000000000004
0.1 + 0.2 のような小数計算で誤差が出るのは、JavaScriptが数値を内部的に2進数の浮動小数点として扱うためです。
真偽値は true と false の2つの値を持ちます。条件分岐や判定処理で使う基本的な型です。
論理演算子には、AND(&&)、OR(||)、NOT(!)があります。
>) の後にコマンドを入力し、Enterキーで実行します。> const isActive = true; undefined > const hasPermission = false; undefined > typeof isActive 'boolean' > // AND: 両方 true なら true > isActive && hasPermission false > // OR: どちらかが true なら true > isActive || hasPermission true > // NOT: true/false を反転 > !isActive false
他言語経験者が最初に混乱しやすいのが、この undefined と null の違いです。
>) の後にコマンドを入力し、Enterキーで実行します。> let unassigned; undefined > unassigned undefined > let empty = null; undefined > typeof unassigned 'undefined' > typeof empty 'object'
typeof null が 'object' になるのは、JavaScript初期から残っている歴史的な仕様です。null 自体はオブジェクトではなく、プリミティブ型の値です。
プリミティブ以外のすべての値はオブジェクト(参照型)です。これらはメモリ上のアドレス(参照)として扱われます。
主なオブジェクト型には以下があります。
>) の後にコマンドを入力し、Enterキーで実行します。> // Object: キーと値のペアの集合
> const user = { name: "Alice", age: 25 };
undefined
> user.name
'Alice'
> user["age"]
25
> // Array: 順序付きリスト(インデックスは 0 から始まる)
> const colors = ["Red", "Green", "Blue"];
undefined
> colors[0]
'Red'
> colors.length
3
重要な点として、const で宣言した変数は「再代入」ができませんが、中身がオブジェクトの場合、プロパティの変更は可能です。これは const が「参照先のメモリアドレス」を固定するものであり、ヒープ領域にあるデータそのものを不変にするわけではないためです。
const user = {
name: "Alice",
id: 1
};
// 再代入はエラーになる
// user = { name: "Bob" }; // TypeError: Assignment to constant variable.
// プロパティの変更は可能
user.name = "Bob";
console.log(user);
// 配列もオブジェクトの一種
const colors = ["Red", "Green"];
colors.push("Blue");
console.log(colors);node object_mutation.js{ name: 'Bob', id: 1 }
[ 'Red', 'Green', 'Blue' ]JavaScriptにおける最大の落とし穴の一つが「等価演算子」です。
**厳密等価演算子 (===) **は「値」と「型」の両方が等しいかを比較します。
等価演算子 (==) は、比較する前に暗黙的な型変換を行います。これにより、直感的ではない結果が生じることがあります。
基本的には常に === (および !==)を使用するようにしてください。
>) の後にコマンドを入力し、Enterキーで実行します。> 1 === "1" // 型が違うので false(推奨) false > 1 == "1" // 文字列が数値に変換されて比較されるため true(非推奨) true > 0 == false // true true > null == undefined // true(ここだけは例外的に許容するスタイルもあるが、基本は避ける) true > [] == ![] // 非常に難解な挙動(trueになる) true
JavaScriptは文脈に応じて勝手に型を変換しようとします。
+ 演算子は、数値の加算だけでなく文字列の連結にも使われます。片方が文字列であれば、もう片方も文字列に変換されて連結されます。
>) の後にコマンドを入力し、Enterキーで実行します。> 10 + 20 30 > 10 + "20" // 数値が文字列 "10" に変換され連結される '1020' > "10" + 20 '1020' > 10 - "2" // 減算は数値計算しかないので、文字列 "2" が数値に変換される 8
const をデフォルトとし、再代入が必要な場合のみ let を使う。var は使用しない。const で宣言したオブジェクトの中身は変更可能である。===(厳密等価演算子)を使用し、== による暗黙の型変換を避ける。itemName という変数に商品名(文字列)、price という変数に価格(数値)、stock という変数に在庫数(数値)をそれぞれ代入してください。その後、テンプレートリテラルを使って「商品: [商品名], 価格: [価格]円, 在庫: [在庫数]個」という形式の文字列を作り、console.log() で出力するコードを書いてみましょう。
node practice2_1.js(出力例) 商品: 高性能マウス, 価格: 4500円, 在庫: 2個
const を使って、name(商品名・文字列)と price(価格・数値)を持つ商品オブジェクト product を作成してください。
次に、price を別の値に変更し、さらに stock(在庫数・数値)プロパティを新たに追加してから、console.log() でオブジェクトの内容を出力してみましょう。
node practice2_2.js(出力例) { name: 'コーヒー', price: 550, stock: 30 }