javascript 基本文法2

公開日: 2025/2/25

javascript 基本文法についてです。

1. データ型


JavaScriptは動的型付け言語に分類される言語であるため、静的型付け言語のような変数の型はありません。

しかし、文字列、数値、真偽値といった値の型は存在します。 これらの値の型のことをデータ型と呼びます。


データ型を大きく分けると、プリミティブ型とオブジェクトの2つに分類されます。

1.プリミティブ型(基本型)

プリミティブ型(基本型)は、真偽値や数値などの基本的な値の型のことです。

プリミティブ型の値は、一度作成したらその値自体を変更できないというイミュータブル(immutable)の特性を持ちます。

JavaScriptでは、文字列も一度作成したら変更できないイミュータブルの特性を持ち、プリミティブ型の一種として扱われます。

2.オブジェクト(複合型)

一方、プリミティブ型ではないものをオブジェクト(複合型)と呼び、 オブジェクトは複数のプリミティブ型の値またはオブジェクトからなる集合です。

オブジェクトは、一度作成した後もその値自体を変更できるためミュータブル(mutable)の特性を持ちます。

オブジェクトは、値そのものではなく値への参照を経由して操作されるため、参照型のデータとも言います。


データ型を細かく見ていくと、7つのプリミティブ型とオブジェクトからなります。


◆プリミティブ型(基本型)

 真偽値(Boolean): trueまたはfalseのデータ型

 数値(Number): 42 や 3.14159 などの数値のデータ型

 巨大な整数(BigInt): ES2020から追加された9007199254740992nなどの任意精度の整数のデータ型

 文字列(String): "JavaScript" などの文字列のデータ型

 undefined: 値が未定義であることを意味するデータ型

 null: 値が存在しないことを意味するデータ型

 シンボル(Symbol): ES2015から追加された一意で不変な値のデータ型

◆オブジェクト(複合型)

 プリミティブ型以外のデータ

 オブジェクト、配列、関数、クラス、正規表現、Dateなど

 プリミティブ型でないものは、オブジェクトであると覚えていれば問題ありません。


typeof演算子を使うことで、次のようにデータ型を調べることができます。

console.log(typeof true);// => "boolean"
console.log(typeof 42); // => "number"
console.log(typeof 9007199254740992n); // => "bigint"
console.log(typeof "JavaScript"); // => "string"
console.log(typeof Symbol("シンボル"));// => "symbol"
console.log(typeof undefined); // => "undefined"
console.log(typeof null); // => "object"
console.log(typeof ["配列"]); // => "object"
console.log(typeof { "key": "value" }); // => "object"
console.log(typeof function() {}); // => "function"

プリミティブ型の値は、それぞれtypeof演算子の評価結果として、その値のデータ型を返します。

一方で、オブジェクトに分類される値は"object"となります。


配列([])とオブジェクト({})は、どちらも"object"という判定結果になります。

 そのため、typeof演算子ではオブジェクトの詳細な種類を正しく判定することはできません。

ただし、関数はオブジェクトの中でも特別扱いされているため、typeof演算子の

2. リテラル


プリミティブ型の値や一部のオブジェクトは、リテラルを使うことで簡単に定義できるようになっています。


リテラルとはプログラム上で数値や文字列など、データ型の値を直接記述できるように構文として定義されたものです。

たとえば、"と"で囲んだ範囲が文字列リテラルで、これは文字列型のデータを表現しています。


次のコードでは、"こんにちは"という文字列型のデータを初期値に持つ変数strを定義しています。

// "と"で囲んだ範囲が文字列リテラル
const str = "こんにちは";

リテラル表現がない場合は、その値を作る関数に引数を渡して作成する形になります。

そのような冗長な表現を避ける方法として、よく利用される主要なデータ型にはリテラルが用意されています。


次の5つのプリミティブ型は、それぞれリテラル表現を持っています。

 ・真偽値

 ・数値

 ・BigInt

 ・文字列

 ・null

また、オブジェクトの中でもよく利用されるものに関してはリテラル表現が用意されています。

 ・オブジェクト

 ・配列

 ・正規表現

2-1. 真偽値(Boolean)

真偽値にはtrueとfalseのリテラルがあります。

それぞれはtrueとfalseの値を返すリテラルで、見た目どおりの意味となります。

true; // => true
false; // => false

2-10. [コラム] undefinedはリテラルではない

プリミティブ型として紹介したundefinedはリテラルではありません。

undefinedはただのグローバル変数で、undefinedという値を持っているだけです。


次のように、undefinedはただのグローバル変数であるため、同じundefinedという名前のローカル変数を宣言できます。

function fn(){
    const undefined = "独自の未定義値"; // undefinedという名前の変数をエラーなく定義できる
    console.log(undefined); // => "独自の未定義値"
}
fn();

これに対してtrue、false、nullなどはグローバル変数ではなくリテラルであるため、同じ名前の変数を定義することはできません。

リテラルは変数名として利用できない予約語のようなものであるため、再定義しようとすると構文エラー(SyntaxError)となります。

let null; // => SyntaxError

2-11. オブジェクトリテラル

JavaScriptにおいて、オブジェクトはあらゆるものの基礎となります。

そのオブジェクトを作成する方法として、オブジェクトリテラルがあります。

オブジェクトリテラルは{}(中カッコ)を書くことで、新しいオブジェクトを作成できます。

const obj = {}; // 中身が空のオブジェクトを作成

オブジェクトリテラルはオブジェクトの作成と同時に中身を定義できます。

オブジェクトのキーと値を:で区切ったものを {} の中に書くことで作成と初期化が同時に行えます。


次のコードで作成したオブジェクトは key というキー名と "value" という文字列の値を持つオブジェクトを作成しています。

キー名には、文字列またはSymbolを指定し、値にはプリミティブ型の値からオブジェクトまで何でも入れることができます。

const obj = {
    "key": "value"
};

このとき、オブジェクトが持つキーのことをプロパティ名と呼びます。

この場合、 objというオブジェクトはkeyというプロパティを持っていると言います。


objのkeyプロパティを参照するには、.(ドット)でつないで参照する方法と、 [](ブラケット)で参照する方法があります。

const obj = {
    "key": "value"
};
// ドット記法
console.log(obj.key); // => "value"
// ブラケット記法
console.log(obj["key"]); // => "value"

ドット記法では、プロパティ名が変数名と同じく識別子である必要があります。

そのため、次のように識別子として利用できないプロパティ名はドット記法として書くことができません。

// プロパティ名は文字列の"123"
const object = {
    "123": "value"
};
// OK: ブラケット記法では、文字列として書くことができる
console.log(object["123"]); // => "value"
// NG: ドット記法では、数値からはじまる識別子は利用できない
object.123

2-12. 配列リテラル

オブジェクトリテラルと並んで、よく使われるリテラルとして配列リテラルがあります。

配列リテラルは[と]で値をカンマ区切りで囲み、その値を持つArrayオブジェクトを作成します。

配列(Arrayオブジェクト)とは、複数の値に順序をつけて格納できるオブジェクトの一種です。

const emptyArray = []; // 空の配列を作成
const array = [1, 2, 3]; // 値を持った配列を作成


配列は0からはじまるインデックス(添字)に、対応した値を保持しています。

作成した配列の要素を取得するには、配列に対してarray[index]という構文で指定したインデックスの値を参照できます。

const array = ["index:0", "index:1", "index:2"];
// 0番目の要素を参照
console.log(array[0]); // => "index:0"
// 1番目の要素を参照
console.log(array[1]); // => "index:1"

2-13. 正規表現リテラル

JavaScriptは正規表現をリテラルで書くことができます。

正規表現リテラルは/(スラッシュ)と/(スラッシュ)で正規表現のパターン文字列を囲みます。

正規表現のパターン内では、+などの特定の記号や\(バックスラッシュ)からはじまる特殊文字が特別な意味を持ちます。


次のコードでは、数字にマッチする特殊文字である\dを使い、1文字以上の数字にマッチする正規表現をリテラルで表現しています。

const numberRegExp = /\d+/; // 1文字以上の数字にマッチする正規表現
// `numberRegExp`の正規表現が文字列"123"にマッチするかをテストする
console.log(numberRegExp.test("123")); // => true

2-2. 数値(Number)

数値には42のような整数リテラルと3.14159のような浮動小数点数リテラルがあります。


これらのリテラルで表現できる数値はIEEE 754の倍精度浮動小数として扱われます。

倍精度浮動小数では64ビットで数値を表現します。

64ビットのうち52ビットを数字の格納のために使い、11ビットを小数点の位置に使い、残りの1ビットはプラスとマイナスの符号です。

そのため、正確に扱える数値の最大値は2^53-1(2の53乗から1引いた値)となります。

2-3. 整数リテラル

整数リテラルには次の4種類があります。


10進数: 数字の組み合わせ

ただし、複数の数字を組み合わせた際に、先頭を0から開始すると8進数として扱われる場合があります


例)0、2、10
2進数: 0b(または0B)の後ろに、0または1の数字の組み合わせ

例)0b0、0b10、0b1010
8進数: 0o(または0O)の後ろに、0から7までの数字の組み合わせ
0o は数字のゼロと小文字アルファベットのo

例)0o644、0o777
16進数: 0x(または0X)の後ろに、0から9までの数字とaからfまたはAからFのアルファベットの組み合わせ
アルファベットの大文字・小文字の違いは値には影響しません

例)0x30A2、0xEEFF
0から9の数字のみで書かれた数値は、10進数として扱われます。

console.log(1); // => 1
console.log(10); // => 10
console.log(255); // => 255

0bからはじまる2進数リテラルは、ビットを表現するのによく利用されています。

bは2進数を表すbinaryを意味しています。

console.log(0b1111); // => 15
console.log(0b10000000000); // => 1024

0oからはじまる8進数リテラルは、ファイルのパーミッションを表現するのによく利用されています。

oは8進数を表すoctalを意味しています。

console.log(0o644);  // => 420
console.log(0o777);  // => 511


次のように、0からはじまり、0から7の数字を組み合わせた場合も8進数として扱われます。

しかし、この表記は10進数と紛らわしいものであったため、ES2015で0oの8進数リテラルが新たに導入されました。

また、strict modeではこの書き方は例外が発生するため、次のような8進数の書き方は避けた方がよいです。

// 非推奨な8進数の書き方
// strict modeは例外が発生
console.log(0644);  // => 420
console.log(0777);  // => 511

0xからはじまる16進数リテラルは、文字のコードポイントやRGB値の表現などに利用されています。

xは16進数を表すhexを意味しています。

console.log(0xFF); // => 255
// 小文字で書いても意味は同じ
console.log(0xff); // => 255
console.log(0x30A2); // => 12450

2-4. 浮動小数点数リテラル

浮動小数点数をリテラルとして書く場合には、次の2種類の表記が利用できます。


3.14159 のような .(ドット)を含んだ数値

2e8 のような e または E を含んだ数値

0からはじまる浮動小数点数は、0を省略して書くことができます。

.123; // => 0.123

2-5. [ES2020] BigInt

JavaScriptでは、1や3.14159などの数値リテラルはIEEE 754で定義された倍精度浮動小数となります。

倍精度浮動小数で正確に扱える数値の最大値は2^53-1(2の53乗から1引いた値である 007199254740991)です。

この数値リテラルで安全に表せる最大の数値はNumber.MAX_SAFE_INTEGERとして定義されています。

console.log(Number.MAX_SAFE_INTEGER); // => 9007199254740991

数値リテラルで2^53-1(9007199254740991)よりも大きな値を表現したり計算すると間違った結果となる場合があります。


この問題を解決するために、ES2020ではBigIntという新しい整数型のデータ型とリテラルが追加されました。

数値リテラルは倍精度浮動小数(64ビット)で数値を扱うのに対して、BigIntでは任意の精度の整数を扱えます。

そのため、BigIntでは2^53-1(9007199254740991)よりも大きな整数を正しく表現できます。


BigIntリテラルは、数値の後ろにnをつけます。

console.log(1n); // => 1n
// 2^53-1より大きな値も扱える
console.log(9007199254740992n); // => 9007199254740992n

BigIntは整数を扱うデータ型であるため、次のように小数点を含めた場合は構文エラーとなります。

1.2n; // => SyntaxError

2-6. [ES2021] Numeric Separators

数値が大きくなるほど、桁数の見間違いなどが発生しやすくなります。

次のコードは、1兆を数値リテラルで書いていますが、桁数を読み取りにくいです。

1000000000000;

ES2021から、数値リテラル内の区切り文字として_を追加できるNumeric Separatorsがサポートされています。

Numeric Separatorsは、数値リテラル内では区切り文字として_が追加できます。

次のコードも、1兆を数値リテラルで書いています。

数値リテラルを評価する際に_は単純に無視されるため同じ意味となります。

1_000_000_000_000;

Numeric Separatorsは数値リテラルである整数、浮動小数点、BigIntのリテラル内でのみ利用できます。

また、_はリテラルの先頭や数値の最後に追加することはできません。

_123; // 変数として評価される
3._14; // => SyntaxError
0x52_; // => SyntaxError
1234n_; // => SyntaxError

2-7. 文字列(String)

文字列リテラル共通のルールとして、同じ記号で囲んだ内容を文字列として扱います。

文字列リテラルとして次の3種類のリテラルがありますが、その評価結果はすべて同じ"文字列"になります。

console.log("文字列"); // => "文字列"
console.log('文字列'); // => "文字列"
console.log(`文字列`); // => "文字列"

2-8. ダブルクォートとシングルクォート

"(ダブルクォート)と'(シングルクォート)はまったく同じ意味となります。

PHPやRubyなどとは違い、どちらのリテラルでも評価結果は同じとなります。


文字列リテラルは同じ記号で囲む必要があるため、次のように文字列の中に同じ記号が出現した場合は、 \'のように\(バックスラッシュ)を使ってエスケープしなければなりません。

'8 o\'clock'; // => "8 o'clock"

また、文字列内部に出現しない別のクォート記号を使うことで、エスケープをせずに書くこともできます。

"8 o'clock"; // => "8 o'clock"

ダブルクォートとシングルクォートどちらも、改行をそのままでは入力できません。

次のように改行を含んだ文字列は定義できないため、構文エラー(SyntaxError)となります。

"複数行の
文字列を
入れたい"; // => SyntaxError: "" string literal contains an unescaped line break

改行の代わりに改行記号のエスケープシーケンス(\n)を使うことで複数行の文字列を書くことができます。

"複数行の\n文字列を\n入れたい";

また、名前のとおりテンプレートのような機能も持っています。

テンプレートリテラル内で${変数名}と書いた場合に、その変数の値を埋め込むことができます。

const str = "文字列";
console.log(`これは${str}です`); // => "これは文字列です"

テンプレートリテラルも他の文字列リテラルと同様に同じリテラル記号を内包したい場合は、\を使ってエスケープする必要があります。

`This is \`code\``;// => "This is `code`"

2-9. nullリテラル

nullリテラルはnull値を返すリテラルです。

nullは「値がない」ということを表現する値です。


次のように、未定義の変数を参照した場合は、 参照できないためReferenceErrorの例外が投げられます。

foo;// "ReferenceError: foo is not defined"

fooには値がないということを表現したい場合は、 null値を代入することで、null値を持つfooという変数を定義できます。

これにより、fooを値がない変数として定義し、参照できるようになります。

const foo = null;
console.log(foo); // => null

3. プリミティブ型とオブジェクト


プリミティブ型は基本的にリテラルで表現しますが、真偽値(Boolean)、数値(Number)、文字列(String)はそれぞれオブジェクトとして表現する方法もあります。

これらはプリミティブ型の値をラップしたようなオブジェクトであるためラッパーオブジェクトと呼ばれます。


ラッパーオブジェクトは、new演算子と対応するコンストラクタ関数を利用して作成できます。

たとえば、文字列のプリミティブ型に対応するコンストラクタ関数はStringとなります。


次のコードでは、Stringのラッパーオブジェクトを作成しています。

ラッパーオブジェクトは、名前のとおりオブジェクトの一種であるためtypeof演算子の結果も"object"です。

また、オブジェクトであるためlengthプロパティなどのオブジェクトが持つプロパティを参照できます。

// 文字列をラップしたStringラッパーオブジェクト
const str = new String("文字列");
// ラッパーオブジェクトは"object"型のデータ
console.log(typeof str); // => "object"
// Stringオブジェクトの`length`プロパティは文字列の長さを返す
console.log(str.length); // => 3


しかし、明示的にラッパーオブジェクトを使うべき理由はありません。

なぜなら、JavaScriptではプリミティブ型のデータに対してもオブジェクトのように参照できる仕組みがあるためです。

次のコードでは、プリミティブ型の文字列データに対してもlengthプロパティへアクセスできています。

// プリミティブ型の文字列データ
const str = "文字列";
// プリミティブ型の文字列は"string"型のデータ
console.log(typeof str); // => "string"
// プリミティブ型の文字列も`length`プロパティを参照できる
console.log(str.length); // => 3