前回の記事では、JavaScriptの実行環境の構築と基本的な文法について紹介しました。今回は、文字列の取り扱い方やデータ型、演算子について、より詳しく扱います。
文字列の基本
文字列の作成方法
JavaScriptでは、文字列を作成するために以下の3つの方法があります:
// 1. シングルクォート
const str1 = 'Hello World';
// 2. ダブルクォート
const str2 = "Hello World";
// 3. テンプレートリテラル(バッククォート)
const str3 = `Hello World`;
シングルクォートとダブルクォートは機能的に同じですが、テンプレートリテラル(バッククォート)には特別な機能があります。
テンプレートリテラルの機能と利点
テンプレートリテラルには、以下のような機能と利点があります:
const name = "Alice";
const age = 25;
// 従来の文字列結合
const message1 = name + "さんは" + age + "歳です。";
// テンプレートリテラルを使用
const message2 = `${name}さんは${age}歳です。`;
console.log(message1); // "Aliceさんは25歳です。"
console.log(message2); // "Aliceさんは25歳です。"
テンプレートリテラルのメリット
- 変数の埋め込みが直感的
- 複数行の文字列が書きやすい
- 特殊文字のエスケープが少なくて済む
// 複数行の文字列
const multiline = `
こんにちは、
これは複数行の
文字列です。
`;
console.log(multiline);
// 出力:
// こんにちは、
// これは複数行の
// 文字列です。
// タグ付きテンプレート
function sanitizeHTML(strings, ...values) {
return strings.reduce((result, str, i) => {
const value = values[i - 1] || '';
// 簡易的なHTMLエスケープ
const escaped = String(value)
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
return result + escaped + str;
});
}
const userInput = '<script>alert("危険!")</script>';
const safeName = sanitizeHTML`<div>ようこそ、${userInput}さん</div>`; // タグつきテンプレートの使用例
console.log(safeName);
// 出力:<div>ようこそ、<script>alert("危険!")</script>さん</div>
エスケープシーケンス
文字列内で特殊な文字を表現する場合は、エスケープシーケンスを使用します:
// よく使うエスケープシーケンス
const str1 = "改行を\n入れます";
const str2 = "タブを\t入れます";
const str3 = "\"クォートを\"入れます";
// テンプレートリテラルなら、クォートのエスケープが不要
const str4 = `"クォート"を入れます`;
型と変数の基本
JavaScriptの型システムを理解することは、バグの少ない安全なコードを書くために重要です。第1回でも扱いましたが、ここで改めて取り上げます。
プリミティブ型の種類
JavaScriptには以下の6つのプリミティブ型があります:
// 1. 文字列型(String)
const str = "Hello";
// 2. 数値型(Number)
const num = 42;
// 3. 真偽値型(Boolean)
const bool = true;
// 4. undefined型
let undef; // 値を代入していない変数。初期化されていない変数は暗黙的に undefined になる
console.log(undef); // undefined が出力される
console.log(typeof undef); // "undefined" が出力される
// 5. null型
const nullValue = null; // 意図的に「値がない」ことを表現
// 6. Symbol型(ES2015で追加):ユニークな値を生成
const sym = Symbol('description');
変数宣言の種類と使い分け
モダンなJavaScriptでは、var
の代わりに let
と const
を使用します:
// constの使用例(再代入不可)
const PI = 3.14159;
// PI = 3.14; // エラー:constは再代入できない
// letの使用例(再代入可能)
let count = 0;
count = 1; // OK
// varは使用を避ける(スコープの問題があるため)
var x = 10; // 非推奨
typeof演算子による型の確認
変数の型を調べるには typeof
演算子を使用します:
const str = "Hello";
const num = 42;
const bool = true;
const arr = [1, 2, 3];
const obj = { name: "Alice" };
console.log(typeof str); // "string"
console.log(typeof num); // "number"
console.log(typeof bool); // "boolean"
console.log(typeof arr); // "object"
console.log(typeof obj); // "object"
// nullの特殊なケース
console.log(typeof null); // "object" (これはJavaScriptの有名な仕様バグ)
NaNとNumber型のユーティリティ関数
JavaScriptでの数値の扱いには、いくつか注意の必要な点があります:
// NaN(Not a Number)の特徴
console.log(typeof NaN); // "number"
console.log(NaN === NaN); // false(NaNは自分自身とも等しくない)
console.log(Number.isNaN(NaN)); // true(正しいNaNの判定方法)
console.log(isNaN("文字列")); // true(グローバルのisNaN()は型変換を行う)
console.log(Number.isNaN("文字列")); // false(Number.isNaN()は型変換を行わない):グローバルの isNaN() は文字列を数値に変換しようとするため true を返してしまう
// 数値判定のユーティリティ関数
console.log(Number.isFinite(42)); // true(有限数かどうか)
console.log(Number.isFinite(1/0)); // false(Infinityは有限数ではない)
console.log(Number.isInteger(42)); // true(整数かどうか)
console.log(Number.isInteger(42.5)); // false(小数は整数ではない)
// 安全な整数の範囲
console.log(Number.MAX_SAFE_INTEGER); // 9007199254740991
console.log(Number.MIN_SAFE_INTEGER); // -9007199254740991
console.log(Number.isSafeInteger(9007199254740991)); // true
console.log(Number.isSafeInteger(9007199254740992)); // false
演算子と型変換
比較演算子
JavaScriptには2種類の等価演算子があります:
// 1. 厳密等価演算子(===):型と値の両方を比較
console.log(5 === "5"); // false
console.log(5 === 5); // true
// 2. 等価演算子(==):暗黙的な型変換を行ってから比較
console.log(5 == "5"); // true(非推奨)
// 型変換の例
console.log(1 == true); // true (数値型 1 に変換される)
console.log(0 == false); // true (数値型 0 に変換される)
console.log("" == false); // true (空文字は数値の0、つまり false に変換される)
console.log("1" == true); // true (文字列型 "1" は数値型 1 に変換され、true は数値型 1 に変換される)
console.log(null == undefined); // true (特殊なケース)
モダンなJavaScriptでは、バグの予防のために ===
(厳密等価演算子)の使用を推奨します:
// 厳密等価演算子を使った安全な比較
function checkValue(value) {
// 良い例:型を含めた厳密な比較
if (value === null || value === undefined) {
// == を使うと null も undefined も true となるので注意
// if (value == null) と書くこともできるが、型を明確にするために === を使う方が良い
// if(value == null)
// console.log('値は null or undefined');
//
// if(value == undefined)
// console.log('値は null or undefined');
return "値が設定されていません";
}
// 良い例:数値の型を保証
if (typeof value === "number") {
return "数値です";
}
return "その他の型です";
}
console.log(checkValue(null)); // "値が設定されていません"
console.log(checkValue(42)); // "数値です"
console.log(checkValue("42")); // "その他の型です"
型変換
JavaScriptでは、明示的な型変換と暗黙的な型変換があります。安全なコードを書くために、基本的には明示的な型変換を使用することを推奨します。
// 明示的な型変換(推奨)
const numStr = "42";
const num = Number(numStr); // 42(数値型)
const str = String(num); // "42"(文字列型)
const bool = Boolean(num); // true(真偽値型)
// 暗黙的な型変換(非推奨)
const result1 = "42" - 0; // 42(数値型)
const result2 = 42 + ""; // "42"(文字列型)
// 数値への変換
console.log(Number("42")); // 42
console.log(parseInt("42.5")); // 42(整数部分のみ)
console.log(parseFloat("42.5")); // 42.5(小数点も含める)
console.log(Number("abc")); // NaN(変換できない場合)
// 真偽値への変換
console.log(Boolean("")); // false(空文字列)
console.log(Boolean("abc")); // true(空でない文字列)
console.log(Boolean(0)); // false
console.log(Boolean(1)); // true
console.log(Boolean([])); // true(空配列)
console.log(Boolean(null)); // false
console.log(Boolean(undefined)); // false
実践的なコード例
function validateAndParseNumber(input) {
try {
// 文字列型でない場合は文字列に変換
const strValue = String(input).trim();
// 空文字列チェック
if (strValue === "") {
return {
isValid: false,
value: null,
error: "入力が空です"
};
}
// 数値への変換
const numValue = Number(strValue);
// NaN、Infinity、-Infinityのチェック
if (!Number.isFinite(numValue)) {
return {
isValid: false,
value: null,
error: "有効な数値ではありません"
};
}
// 安全な整数範囲のチェック(必要な場合)
if (!Number.isSafeInteger(numValue)) {
return {
isValid: false,
value: null,
error: "数値が大きすぎるか、整数ではありません"
};
}
return {
isValid: true,
value: numValue,
error: null
};
} catch (error) {
// 予期せぬエラーの処理
console.error("数値変換処理でエラーが発生:", error);
return {
isValid: false,
value: null,
error: "入力の処理中にエラーが発生しました"
};
}
}
// 使用例
console.log(validateAndParseNumber("42")); // { isValid: true, value: 42, error: null }
console.log(validateAndParseNumber("abc")); // { isValid: false, value: null, error: "有効な数値ではありません" }
console.log(validateAndParseNumber("")); // { isValid: false, value: null, error: "入力が空です" }
console.log(validateAndParseNumber("1e+999")); // { isValid: false, value: null, error: "有効な数値ではありません" }
console.log(validateAndParseNumber(42.5)); // { isValid: false, value: null, error: "数値が大きすぎるか、整数ではありません" }
// より実践的な数値処理の例
function calculateDiscount(price, discountRate) {
try {
// 引数の型チェックと変換
const validPrice = validateAndParseNumber(price);
if (!validPrice.isValid) {
throw new Error(`価格が不正です: ${validPrice.error}`);
}
// 割引率の検証(0-100の範囲)
const rate = Number(discountRate);
if (!Number.isFinite(rate) || rate < 0 || rate > 100) {
throw new Error("割引率は0から100の間で指定してください");
}
// 割引計算
const discount = Math.floor(validPrice.value * (rate / 100));
const finalPrice = validPrice.value - discount;
return {
originalPrice: validPrice.value,
discountRate: rate,
discount: discount,
finalPrice: finalPrice
};
} catch (error) {
return {
error: error.message,
originalPrice: null,
discountRate: null,
discount: null,
finalPrice: null
};
}
}
// 使用例
console.log(calculateDiscount("1000", 20));
// {
// originalPrice: 1000,
// discountRate: 20,
// discount: 200,
// finalPrice: 800
// }
console.log(calculateDiscount("invalid", 20));
// {
// error: "価格が不正です: 有効な数値ではありません",
// originalPrice: null,
// discountRate: null,
// discount: null,
// finalPrice: null
// }
まとめ
この回では、JavaScriptの文字列操作、データ型、演算子、型変換について学びました。重要なポイントを整理しましょう:
- 文字列操作
- テンプレートリテラル(
`
)を使用すると、可読性の高いコードが書ける - タグ付きテンプレートを使用することで、文字列の安全な加工が可能
- 複数行の文字列も簡単に記述可能
- テンプレートリテラル(
- 変数宣言
-
const
とlet
を使用し、var
は避ける - できるだけ
const
を使用し、再代入が必要な場合のみlet
を使用
-
- 比較演算子
-
===
(厳密等価演算子)を使用し、==
は避ける - 型の安全性を確保することでバグを防ぐ
-
- 型変換
- 明示的な型変換(
Number()
、String()
、Boolean()
)を使用 - 暗黙的な型変換は予期せぬバグの原因になるため、特別な理由がない限り避ける
-
Number.isNaN()
やNumber.isFinite()
などの適切な判定関数を使用
- 明示的な型変換(
- エラー処理
- 型変換やバリデーションでは適切なエラーハンドリングを実装
- エラーメッセージは具体的で理解しやすいものを使用
- try-catchを使用して予期せぬエラーに対応
これらの基礎を押さえることで、より安全で保守性の高いJavaScriptコードが書けるようになります。とくに、型の安全性を意識したコーディングは、バグの予防と早期発見に大きく貢献します。
次回予告
次回は「制御構文とループ」について紹介します。条件分岐(if文、switch文)や繰り返し処理(for文、while文)の基本と、モダンな書き方について扱います。