クラスの使用 - JavaScript

クラスの使用
======

* « 前のページ
* 次のページ »

JavaScript はプロトタイプベースの言語です。オブジェクトの動作は、自分自身のプロパティとプロトタイプのプロパティで指定します。しかし、クラスの追加により、オブジェクトの階層の作成、プロパティとその値の継承は、Java などの他のオブジェクト指向言語とかなり方向性が近くなっています。この章では、クラスからオブジェクトを作成する方法を説明します。

他にも多くの言語では、クラスやコンストラクターは、オブジェクトやインスタンスと明確に判別されます。JavaScript では、クラスは主に既存のプロトタイプ継承の仕組みを抽象化したもので、すべてのパターンがプロトタイプベースの継承に変換可能です。クラス自体も通常の JavaScript の値であり、独自のプロトタイプチェーンを持っています。実際、JavaScript のほとんどの関数はコンストラクターとして使用することができます - 新しいオブジェクトを作成するには、コンストラクター関数と一緒に `new` 演算子を使用します。

このチュートリアルでは、よく抽象化されたクラスモデルを使って遊び、クラスがどのような意味づけをするのかについて説明します。もし、基盤となるプロトタイプシステムを深く掘り下げたいのであれば、継承とプロトタイプチェーンのガイドを読むと良いでしょう。

この章では、あなたがすでに JavaScript にある程度慣れていて、普通のオブジェクトを使用したことがあることを想定しています。

クラスの概要
------

JavaScript をある程度使いこなしている方、あるいはガイドに沿って進んできた方は、たとえ作成していなくても、すでにクラスを使用したことがあるのではないでしょうか？例えば、これは馴染みがあるかもしれません。

```js
const bigDay = new Date(2019, 6, 19);
console.log(bigDay.toLocaleDateString());
if (bigDay.getTime() < Date.now()) {
  console.log("Once upon a time...");
}
```

最初の行では、クラス `Date` のインスタンスを作成し、`bigDay` と名付けています。2 行目では、`bigDay` インスタンスに対して メソッド `toLocaleDateString()` を呼び出して、文字列を返しています。次に、2 つの数値を比較しています。1 つは `getTime()` メソッドから返されたもの、もう 1 つは `Date` クラス自体から `Date.now()` として直接呼び出されたものです。

`Date` は JavaScript の組み込みクラスです。この例から、クラスが何をするのかの基本的な考えを得ることができます。

* クラスは `new` 演算子を用いてオブジェクトを作成します。
* それぞれのオブジェクトは、クラスによって追加されたいくつかのプロパティ（データまたはメソッド）を持ちます。
* クラスは、いくつかのプロパティ（データまたはメソッド）を自分自身に格納し、通常、インスタンスと対話するために使用しあｍす。

これらは、クラスの 3 大機能に対応しています。

* コンストラクター
* インスタンスメソッドとインスタンスフィールド
* 静的メソッドと静的フィールド
クラスの宣言
------

クラスはふつう、クラス宣言で作成されます。

```js
class MyClass {
  // クラス本体...
}
```

クラス本体の中で、利用できる機能は多岐にわたります。

```js
class MyClass {
  // コンストラクター
  constructor() {
    // コンストラクターの本体
  }
  // インスタンスフィールド
  myField = "foo";
  // インスタンスメソッド
  myMethod() {
    // myMethod 本体
  }
  // 静的フィールド
  static myStaticField = "bar";
  // 静的メソッド
  static myStaticMethod() {
    // myStaticMethod 本体
  }
  // 静的ブロック
  static {
    // 静的初期化コード
  }
  // フィールド、メソッド、静的フィールド、静的メソッドには、すべて
  // 「プライベート」形式があります
  #myPrivateField = "bar";
}
```

ES6 以前の世界から来た人は、関数をコンストラクターとして使用することに慣れているかもしれません。上記のパターンは、関数コンストラクターを使うと、おおよそ以下のように対応させることができます。

```js
function MyClass() {
  this.myField = "foo";
  // コンストラクター本体
}
MyClass.myStaticField = "bar";
MyClass.myStaticMethod = function () {
  // myStaticMethod 本体
};
MyClass.prototype.myMethod = function () {
  // myMethod 本体
};

(function () {
  // 静的初期化コード
})();
```

**メモ:** プライベートフィールドとメソッドは、クラスにおける新しい機能であり、関数コンストラクターにおける同等の機能はありません。

### クラスの構築

クラスを宣言した後は、`new`演算子を使用してそのインスタンスを作成することができます。

```js
const myInstance = new MyClass();
console.log(myInstance.myField); // 'foo'
myInstance.myMethod();
```

一般的な関数コンストラクターは、`new` で構築することも、`new` なしで呼び出すことも可能です。しかし、`new` なしでクラスを「呼び出し」しようとすると、エラーになります。

```js
const myInstance = MyClass(); // TypeError: Class constructor MyClass cannot be invoked without 'new'
```

### クラス宣言の巻き上げ

関数宣言とは異なり、クラス宣言は巻き上げが行われません（見方を変えると、巻き上げが行われるが、一時的なデッドゾーンの制約を受けます）。つまり、宣言前にクラスを使用することはできません。

```js
new MyClass(); // ReferenceError: Cannot access 'MyClass' before initialization

class MyClass {}
```

この動作は、`let` や `const` で宣言した変数と似ています。

### クラス式

関数と同様に、クラス宣言にも対応する式があります。

```js
const MyClass = class {
  // Class body...
};
```

クラス式も名前を持つことができます。式の名前は、クラス本体でのみ見ることができます。

```js
const MyClass = class MyClassLongerName {
  // クラス本体。ここでは、MyClass と MyClassLongerName は同じクラスを指しています。
};
new MyClassLongerName(); // ReferenceError: MyClassLongerName is not defined
```

コンストラクター
--------

おそらくクラスの最も重要な仕事は、オブジェクトの「工場」として機能することでしょう。例えば、`Date` コンストラクターを使用する際、渡された日付データを表す新しいオブジェクトが生成されることを期待します。これでそのインスタンスが公開する、他のメソッドを操作することができます。クラスでは、インスタンスの生成はコンストラクターによって行われます。

例として、特定の色を表す `Color` というクラスを作成しましょう。ユーザーは RGB の 3 つの値を渡して色を作成します。

```js
class Color {
  constructor(r, g, b) {
    // RGB 値を `this` のプロパティとして割り当てる。
    this.values = [r, g, b];
  }
}
```

ブラウザーで開発ツールを開き、上記のコードをコンソールに貼り付け、インスタンスを作成します。

```js
const red = new Color(255, 0, 0);
console.log(red);
```

このような出力が確認できるはずです。
```

Object { values: (3) […] }
  values: Array(3) [ 255, 0, 0 ]
```

これで `Color` インスタンスを作成することに成功し、そのインスタンスには `values` プロパティがあり、それは渡した RGB 値の配列です。これは次のものとほぼ同じです。

```js
function createColor(r, g, b) {
  return {
    values: [r, g, b],
  };
}
```

コンストラクターの構文は通常の関数と全く同じです。つまり、残余引数のような他の構文も使用できます。

```js
class Color {
  constructor(...values) {
    this.values = values;
  }
}

const red = new Color(255, 0, 0);
// 上記と同じ形状のインスタンスを作成します。
```

`new` を呼び出すたびに、異なるインスタンスが作成されます。

```js
const red = new Color(255, 0, 0);
const anotherRed = new Color(255, 0, 0);
console.log(red === anotherRed); // false
```

クラスのコンストラクター内では、`this` の値は新しく作成されるインスタンスを指します。このインスタンスにプロパティを割り当てることもできますし、既存のプロパティ（特にメソッド — 次回取り上げます）を読み取ることもできます。

`this` の値は、自動的に `new` の結果として返されます。コンストラクターからは値を返さないことをお勧めします。プリミティブでない値を返すと、それが `new` 式の値となり、 `this` の値は削除されるからです。（`new`が何をするのかについては、その解説で詳しく説明されています。）

```js
class MyClass {
  constructor() {
    this.myField = "foo";
    return {};
  }
}

console.log(new MyClass().myField); // undefined
```

インスタンスメソッド
----------

クラスがコンストラクターだけを持つ場合、それは単にプレーンなオブジェクトを作成する `createX` ファクトリー関数と大差ありません。しかし、クラスの威力は、インスタンスにメソッドを自動的に割り当てる「テンプレート」として使用できることです。

例えば `Date` インスタンスでは、年、月、曜日などのように、1 つの日付値からさまざまな情報を取得するために、さまざまなメソッドが使用できます。また、`setFullYear`のように、対応する `setX` でこれらの値を設定することもできます。

自分自身で作った `Color` クラスには、色の赤成分の値を返す `getRed` というメソッドを追加することができます。

```js
class Color {
  constructor(r, g, b) {
    this.values = [r, g, b];
  }
  getRed() {
    return this.values[0];
  }
}

const red = new Color(255, 0, 0);
console.log(red.getRed()); // 255
```

メソッドがない場合は、コンストラクターの中で関数を定義したくなるかもしれません。

```js
class Color {
  constructor(r, g, b) {
    this.values = [r, g, b];
    this.getRed = function () {
      return this.values[0];
    };
  }
}
```

これはうまく動作します。しかし、問題は、`Color`インスタンスが作成されるたびに、すべて同じことをするにもかかわらず、新しい関数が作成されることです。

```js
console.log(new Color().getRed === new Color().getRed); // false
```

これに対して、メソッドを使用すると、すべてのインスタンスで共有されることになります。関数はすべてのインスタンスで共有することができますが、それでも異なるインスタンスが呼び出すと、`this` の値が異なるため、動作が異なることがあります。このメソッドがどこに格納されているかというと、すべてのインスタンスのプロトタイプ、つまり `Color.prototype` に定義されています。詳しくは 継承とプロトタイプチェーン に説明があります。

同様に、色の赤成分の値を設定する `setRed` という新しいメソッドを作成することができます。

```js
class Color {
  constructor(r, g, b) {
    this.values = [r, g, b];
  }
  getRed() {
    return this.values[0];
  }
  setRed(value) {
    this.values[0] = value;
  }
}

const red = new Color(255, 0, 0);
red.setRed(0);
console.log(red.getRed()); // 0。もちろん、この段階では「黒」と呼ばれるものなので。
```

プライベートフィールド
-----------

インスタンスの `values` 配列に直接アクセスできるのに、わざわざ `getRed` や `setRed` メソッドを使用する必要があるのか、と思われるかもしれません。

```js
class Color {
  constructor(r, g, b) {
    this.values = [r, g, b];
  }
}

const red = new Color(255, 0, 0);
red.values[0] = 0;
console.log(red.values[0]); // 0
```

オブジェクト指向プログラミングには、「カプセル化」と呼ばれる哲学があります。これは、オブジェクトの基盤となる実装にはアクセスせず、オブジェクトと対話するために抽象化されたメソッドを使用することを意味しています。例えば、突然、色を HSL として表すことにしたとします。

```js
class Color {
  constructor(r, g, b) {
    // values is now an HSL array!
    this.values = rgbToHSL([r, g, b]);
  }
  getRed() {
    return this.values[0];
  }
  setRed(value) {
    this.values[0] = value;
  }
}

const red = new Color(255, 0, 0);
console.log(red.values[0]); // 0。255 ではなくなります。純粋な赤の H の値は 0 だからです。
```

ユーザーは `values` が RGB 値を突然崩壊させることを意味していると思い込み、自分のロジックが壊れる原因になりかねません。そのため、もしあなたがクラスの実装者であれば、インスタンスの内部データ構造をユーザーから隠したいでしょう。これは、API をきれいに保つためと、あなたが「害のないリファクタリング」をしたときにユーザーのコードが壊れるのを防ぐためです。クラスでは、これは *private fields* を通して行われます。

プライベートフィールドは、接頭辞に `#` (ハッシュ記号) を持つ識別子です。このハッシュはフィールドの名前に不可欠な要素であり、プライベートプロパティがパブリックプロパティと名前が衝突することはないことを意味しています。プライベートフィールドをクラスのどこかで参照するには、クラス本体でそれを宣言する必要があります（プライベートプロパティをその場で作成することはできません）。これを除けば、プライベートフィールドは通常のプロパティとほとんど同じです。

```js
class Color {
  // 宣言: それぞれの Color インスタンスには、 #values というプライベートフィールドがある
  #values;
  constructor(r, g, b) {
    this.#values = [r, g, b];
  }
  getRed() {
    return this.#values[0];
  }
  setRed(value) {
    this.#values[0] = value;
  }
}

const red = new Color(255, 0, 0);
console.log(red.getRed()); // 255
```

クラス外からプライベートフィールドにアクセスすると、初期の構文エラーになります。`#privateField` は特殊な構文なので、静的解析を行い、コードを評価する前にプライベートフィールドの使い方をすべて見つけることができるため、言語はこれを防ぐことができます。

```js
console.log(red.#values); // SyntaxError: Private field '#values' must be declared in an enclosing class
```

JavaScript でのプライベートフィールドはハードプライベートです。クラスがこのプライベートフィールドを公開するメソッドを実装していない場合、クラスの外からそれを取得する仕組みは全くありません。つまり、公開されるメソッドの動作が変わらない限り、クラスのプライベートフィールドにどんなリファクタリングを行っても安全だということです。

`values` フィールドをプライベートにした後は、`getRed` と `setRed` のメソッドを単純なパススルーメソッドにするのではなく、いくつかのロジックを追加することができます。例として、`setRed` に有効な R 値かどうかを調べる機能を追加することができます。

```js
class Color {
  #values;
  constructor(r, g, b) {
    this.#values = [r, g, b];
  }
  getRed() {
    return this.#values[0];
  }
  setRed(value) {
    if (value < 0 || value > 255) {
      throw new RangeError("Invalid R value");
    }
    this.#values[0] = value;
  }
}

const red = new Color(255, 0, 0);
red.setRed(1000); // RangeError: Invalid R value
```

もし `values` プロパティを公開したままにしておくと、ユーザーは `values[0]` に直接割り当てることで簡単にこのチェックを回避し、不正な色を作成することができます。しかし、うまくカプセル化された API を使えば、コードをより堅牢にし、下流でのロジックエラーを防ぐことができるのです。

クラスメソッドは、同じクラスに属している限り、他のインスタンスのプライベートフィールドを読み取ることができます。

```js
class Color {
  #values;
  constructor(r, g, b) {
    this.#values = [r, g, b];
  }
  redDifference(anotherColor) {
    // #values には、必ずしもここからアクセスする必要はありません。
    // 同じクラスに属する他のインスタンスのプライベートフィールドに
    // アクセスすることができます。
    return this.#values[0] - anotherColor.#values[0];
  }
}

const red = new Color(255, 0, 0);
const crimson = new Color(220, 20, 60);
red.redDifference(crimson); // 35
```

しかし、`anotherColor` が Color のインスタンスでない場合、`#values` は存在しないことになります。（他のクラスが同じ名前の `#values` プライベートフィールドを持っていたとしても、同じことを参照しているわけではないので、ここではアクセスすることができません。）存在しないプライベートプロパティにアクセスすると、通常のプロパティのように `undefined` を返すのではなく、エラーが発生します。オブジェクトにプライベートフィールドが存在するかどうかわからず、エラーを処理するために `try`/`catch` を使用せずにアクセスしたい場合は、 `in` 演算子を使用することができます。

```js
class Color {
  #values;
  constructor(r, g, b) {
    this.#values = [r, g, b];
  }
  redDifference(anotherColor) {
    if (!(#values in anotherColor)) {
      throw new TypeError("Color instance expected");
    }
    return this.#values[0] - anotherColor.#values[0];
  }
}
```

**メモ:** このとき、`#` は特殊な識別子構文であり、フィールド名を文字列のように使用することはできないことに留意してください。`"#values" in anotherColor` は、プライベートフィールドではなく、文字通り `"#values"` というプロパティ名を探していくことになります。

プライベートプロパティを使用するには、いくつかの制限があります。同じ名前を単一のクラスで 2 回宣言することはできませんし、削除することもできません。どちらも初期の構文エラーにつながります。

```js
class BadIdeas {
  #firstName;
  #firstName; // syntax error occurs here
  #lastName;
  constructor() {
    delete this.#lastName; // also a syntax error
  }
}
```

メソッド、ゲッター、セッターも同様にプライベートにすることができます。クラスが内部で行う必要があるが、コードの他の部分からは呼び出すことができないような複雑なものがある場合に有用です。

例えば、HTML のカスタム要素を作成し、クリックしたりタップしたりしたときに何かやや複雑な動作をさせることを想像してみてください。さらに、要素がクリックされたときに起こるやや複雑なことは、このクラスに限定されるべきで、JavaScript の他の部分がそれにアクセスすることはない（あるいは、する必要がある）ためです。

```js
class Counter extends HTMLElement {
  #xValue = 0;
  constructor() {
    super();
    this.onclick = this.#clicked.bind(this);
  }
  get #x() {
    return this.#xValue;
  }
  set #x(value) {
    this.#xValue = value;
    window.requestAnimationFrame(this.#render.bind(this));
  }
  #clicked() {
    this.#x++;
  }
  #render() {
    this.textContent = this.#x.toString();
  }
  connectedCallback() {
    this.#render();
  }
}

customElements.define("num-counter", Counter);
```

この場合、ほとんどすべてのフィールドとメソッドが、このクラスのプライベートとなります。したがって、このクラスは他のコードに対して、基本的に組み込みの HTML 要素のようなインターフェイスを表示しています。プログラムの他の部分は `Counter` の内部構造に影響を与える力はありません。

アクセサーフィールド
----------

`color.getRed()` と `color.setRed()` は、色の赤成分の値を読み書きできるようにするものです。Java のような言語の出身者であれば、このパターンにとても馴染みがあると思います。しかし、プロパティに単純にアクセスするためにメソッドを使用することは、JavaScript ではまだいくらか人間工学的でないようです。アクセサーフィールドを使えば、あたかも「実際のプロパティ」であるかのように、何かを操作することができるようになります。

```js
class Color {
  constructor(r, g, b) {
    this.values = [r, g, b];
  }
  get red() {
    return this.values[0];
  }
  set red(value) {
    this.values[0] = value;
  }
}

const red = new Color(255, 0, 0);
red.red = 0;
console.log(red.red); // 0
```

オブジェクトに `red` というプロパティがあるように見えますが、実際にはインスタンスにそのようなプロパティは存在しません。メソッドは 2 つしかありませんが、接頭辞に `get` と `set` がついているので、あたかもプロパティのように操作することが可能になっています。

もしフィールドにゲッターだけあってセッターがない場合、それは事実上読み取り専用になります。

```js
class Color {
  constructor(r, g, b) {
    this.values = [r, g, b];
  }
  get red() {
    return this.values[0];
  }
}

const red = new Color(255, 0, 0);
red.red = 0;
console.log(red.red); // 255
```

厳格モードの場合、`red.red = 0` の行は、"Cannot set property red of #<Color> which has only a getter" という型エラーが発生します。厳密モード以外では、代入は暗黙に無視されます。

パブリックフィールド
----------

プライベートフィールドに対してパブリックフィールドがあり、すべてのインスタンスがプロパティを持つことができます。フィールドは通常、コンストラクターの引数に依存しないように設計されています。

```js
class MyClass {
  luckyNumber = Math.random();
}
console.log(new MyClass().luckyNumber); // 0.5
console.log(new MyClass().luckyNumber); // 0.3
```

パブリックフィールドは、`this`にプロパティを割り当てるのとほぼ同じです。例えば、上の例も変換できます。

```js
class MyClass {
  constructor() {
    this.luckyNumber = Math.random();
  }
}
```

静的プロパティ
-------

`Date` の例では、現在の日付を返す `Date.now()` メソッドにも遭遇しています。このメソッドは Date のインスタンスに属するものではなく、クラスそのものに属するものです。しかし、Dateインスタンスを扱うときに有益なメソッドであるため、グローバルな `DateNow()` 関数として公開するのではなく、`Date` クラスに搭載しています。

**メモ:** ユーティリティメソッドの接頭辞に、そのメソッドが扱うものを付けることは「名前空間化」と呼ばれ、良い習慣とされています。例えば、JavaScript では、古い接頭辞のない `parseInt()` メソッドに加え、後から、数字を扱うためのメソッドであることを示すために `Number.parseInt()` メソッドが追加されました。

静的プロパティは、クラスの個々のインスタンスではなく、クラス自体に定義されるクラス機能のグループです。これらの機能には、次のようなものがあります。

* 静的メソッド
* 静的フィールド
* 静的ゲッターおよびセッター

また、すべてのものには、対応するプライベートなものがあります。例えば、`Color` クラスでは、指定された 3 つの値が有効な RGB 値であるかどうかを調べる静的メソッドを作成することができます。

```js
class Color {
  static isValid(r, g, b) {
    return r >= 0 && r <= 255 && g >= 0 && g <= 255 && b >= 0 && b <= 255;
  }
}

Color.isValid(255, 0, 0); // true
Color.isValid(1000, 0, 0); // false
```

静的プロパティは、その点を除いて、インスタンスに対応するものととてもよく似ています。

* すべてに `static` の接頭辞が付いており、
* インスタンスからはアクセスできません。

```js
console.log(new Color(0, 0, 0).isValid); // undefined
```

また、静的初期化ブロックという特別な構造があり、これはクラスが最初に読み込まれたときに実行されるコードのブロックです。

```js
class MyClass {
  static {
    MyClass.myStaticProperty = "foo";
  }
}

console.log(MyClass.myStaticProperty); // 'foo'
```

静的初期化ブロックは、クラスが宣言された後、すぐにコードを実行するのとほぼ同じです。唯一の違いは、静的なプライベートプロパティにアクセスできることです。

拡張と継承
-----

クラスがもたらす重要な機能は（プライベートフィールドによる人間工学的なカプセル化に加えて）「継承」です。これは、あるオブジェクトが他のオブジェクトの動作の大部分を「借り」ながら、ある部分は自分自身でロジックを上書きしたり拡張したりできることを意味しています。

例えば、`Color` クラスがこれで透明度に対応する必要が出てきたとします。透明度を示す新しいフィールドを追加したくなるかもしれません。

```js
class Color {
  #values;
  constructor(r, g, b, a = 1) {
    this.#values = [r, g, b, a];
  }
  get alpha() {
    return this.#values[3];
  }
  set alpha(value) {
    if (value < 0 || value > 1) {
      throw new RangeError("Alpha value must be between 0 and 1");
    }
    this.#values[3] = value;
  }
}
```

しかし、これではすべてのインスタンス — 透明でない大部分（アルファ値が 1 のもの） — が余分なアルファ値を持たなければならないことを意味しており、とても洗練されたものではありません。さらに、機能が増え続けると、`Color` クラスはとても肥大化し、メンテナンスが難しくなります。

その代わりに、オブジェクト指向プログラミングでは、「派生クラス」を作成することになります。派生クラスは、親クラスのすべてのパブリックプロパティへアクセスすることができます。JavaScript では、派生クラスは `extends` 節で宣言され、そのクラスがどのクラスから拡張されているかを示します。

```js
class ColorWithAlpha extends Color {
  #alpha;
  constructor(r, g, b, a) {
    super(r, g, b);
    this.#alpha = a;
  }
  get alpha() {
    return this.#alpha;
  }
  set alpha(value) {
    if (value < 0 || value > 1) {
      throw new RangeError("Alpha value must be between 0 and 1");
    }
    this.#alpha = value;
  }
}
```

すぐに気付くことがいくつかあります。最初の点は、コンストラクタの中で、`super(r, g, b)` を呼び出していることです。`this` にアクセスする前に `super()` を呼び出すことは言語要件です。`super()` は親クラスのコンストラクターを呼び出して `this` を初期化します — ここでは `this = new Color(r, g, b)` とほぼ同じ意味です。`super()` の前にコードを置くことはできますが、`super()` の前に `this` にアクセスすることはできません。言語上、未初期化の `this` にアクセスすることはできないからです。

親クラスが `this` を変更した後、派生クラスは自分自身でロジックを作成することができます。ここでは、`#alpha` というプライベートフィールドを追加し、それと対話するためのゲッター/セッターのペアを提供しました。

派生クラスは、親クラスからすべてのメソッドを継承します。例えば、`ColorWithAlpha` は自分自身で`get red()` アクセサーを宣言していませんが、この動作は親クラスで指定されているので、`red` にアクセスすることはできます。

```js
const color = new ColorWithAlpha(255, 0, 0, 0.5);
console.log(color.red); // 255
```

派生クラスは親クラスのメソッドを上書きすることもできます。例えば、すべてのクラスは `Object` クラスを暗黙的に継承しており、`toString()` など、いくつかの基本的なメソッドが定義されています。しかし、基本の `toString()` メソッドは、ほとんどの場合 `[object Object]` を表示するため、使い勝手が悪いです。

```js
console.log(red.toString()); // [object Object]
```

代わりに、このクラスは色の RGB 値を表示するようにオーバーライドすることができます。

```js
class Color {
  #values;
  // …
  toString() {
    return this.#values.join(", ");
  }
}

console.log(new Color(255, 0, 0).toString()); // '255, 0, 0'
```

派生クラス内では、`super` を使用することで、親クラスのメソッドにアクセスすることができます。これにより、強化メソッドを構築し、コードの重複を避けることができます。

```js
class ColorWithAlpha extends Color {
  #alpha;
  // …
  toString() {
    // 親クラスの toString() を呼び出し、返値を構築する
    return `${super.toString()}, ${this.#alpha}`;
  }
}

console.log(new ColorWithAlpha(255, 0, 0, 0.5).toString()); // '255, 0, 0, 0.5'
```

`extends` を使用すると、静的メソッドも同様に継承されるので、オーバーライドや拡張も可能です。

```js
class ColorWithAlpha extends Color {
  // ...
  static isValid(r, g, b, a) {
    // 親クラスの isValid() を呼び出し、返値において構築する
    return super.isValid(r, g, b) && a >= 0 && a <= 1;
  }
}

console.log(ColorWithAlpha.isValid(255, 0, 0, -1)); // false
```

派生クラスは親クラスのプライベートフィールドにアクセスできません。これは、JavaScript のプライベートフィールドが「ハードプライベート」であることのもう一つの重要な側面です。プライベートフィールドは、クラス本体にスコープされ、外部のコードにアクセスすることはできません。

```js
class ColorWithAlpha extends Color {
  log() {
    console.log(this.#values); // SyntaxError: Private field '#values' must be declared in an enclosing class
  }
}
```

クラスは 1 つのクラスからしか拡張できません。これにより、ダイヤモンド問題のような多重継承における問題を防ぐことができます。しかし、JavaScriptの動的な性質上、クラス構成やmixinsによって多重継承の効果を実現することは可能です。

派生クラスのインスタンスは、基底クラスの instance of でもある。

```js
const color = new ColorWithAlpha(255, 0, 0, 0.5);
console.log(color instanceof Color); // true
console.log(color instanceof ColorWithAlpha); // true
```

なぜクラスか
------

このガイドはこれまで実用的なものでした。私たちはクラスをどのように使用できるかに焦点を当てていますが、1つだけ未解決の疑問があります。なぜクラスを使用するのでしょうか？答えは、「場合による」です。

クラスはパラダイム、つまりコードを整理する方法を導入します。クラスはオブジェクト指向プログラミングの基礎であり、継承や多態性（特にサブタイピング）といった概念に基づいて構築されています。しかし、多くの人は哲学的にある種の OOP の実践に反対しており、その結果クラスを使用していません。

例えば、`Date` オブジェクトが悪名高いのは、変更可能であることです。

```js
function incrementDay(date) {
  return date.setDate(date.getDate() + 1);
}
const date = new Date(); // 2019-06-19
const newDay = incrementDay(date);
console.log(newDay); // 2019-06-20
// 古い日付も変わってしまう！？
console.log(date); // 2019-06-20
```

内部状態が変更可能であることは、オブジェクト指向プログラミングの重要な要素ですが、一見何の変哲もない処理が予期せぬ副作用を持ち、プログラムの他の部分の動作を変えてしまうことがあるため、コードの推論が困難になることが多いのです。

コードを再利用するために、私たちは通常、クラスを拡張しがちが、これは大きな継承パターンの階層を生み出す可能性があります。

![典型的な OOP 継承ツリーで、 5つのクラスと 3 つの階層があります。](/ja/docs/Web/JavaScript/Guide/Using_classes/figure8.1.png)

しかし、あるクラスが他のクラスを 1 つだけしか拡張できない場合、継承をきれいに記述するのが難しいことがよくあります。複数のクラスの振る舞いが欲しい場合もよくあります。これは、Java ではインターフェイスで、JavaScript ではミックスインで実現することができます。しかし、結局のところ、まだとても便利とは言えません。

一方、クラスは、コードをより高いレベルで整理するためのとても強力な手段です。例えば、`Color` クラスがなければ、ユーティリティ関数を何十個も作成しなければならないかもしれません。

```js
function isRed(color) {
  return color.red === 255;
}
function isValidColor(color) {
  return (
    color.red >= 0 &&
    color.red <= 255 &&
    color.green >= 0 &&
    color.green <= 255 &&
    color.blue >= 0 &&
    color.blue <= 255
  );
}
// ...
```

しかし、クラスを使えば、すべて `Color` という名前空間の下に集めることができるので、読みやすさが向上します。また、プライベートフィールドを導入することで、特定のデータを下流のユーザーから隠すことができ、クリーンな API を作成することができます。

一般的に、独自の内部データを格納し、多くの動作を公開するオブジェクトを作成したい場合には、クラスの使用を検討すべきでしょう。JavaScript の組み込みクラスを例にとると、以下のようになります。

* `Map` および `Set` クラスは、要素の集合を保持し、 `get()`, `set()`, `has()`, などを使用してキーによって要素にアクセスすることができます。
* `Date` クラスは日時を UNIX タイムスタンプ（数値）で保持し、日時の個々の部分を整形、更新、読み取りすることができます。
* `Error` クラスは、例外に関する具体的な情報、例えばエラーメッセージ、スタックトレース、原因などを保持します。これは、豊富な継承構造を持ついくつかのクラスの 1 つです。`TypeError` や `ReferenceError` など、`Error` を継承する複数の組み込みクラスがあります。エラーの場合、この継承によってエラーの意味を絞り込むことができます。それぞれのクラスが固有のエラーの種類を表すので、`instanceof` で容易に調べることができます。

JavaScript には、コードを正規のオブジェクト指向で整理する仕組みがありますが、それを使用するかどうか、どのように使用するかは、すべてプログラマーの裁量に委ねられています。

* « 前のページ
* 次のページ »


オブジェクトでの作業 - JavaScript

オブジェクトでの作業
==========

* « 前のページ
* 次のページ »

JavaScript は、シンプルなオブジェクトベースの枠組みを持つ言語として設計されています。JavaScript におけるオブジェクトはプロパティの集まりであり、プロパティは名前 (あるいは*キー*) と値との関連付けから成り立っています。プロパティの値を関数にすることもでき、これはいわゆるオブジェクトのメソッドとなります。ブラウザーにあらかじめ定義されているオブジェクトに加え、独自のオブジェクトを定義することもできます。この節ではオブジェクト、プロパティ、関数、メソッドの使い方と、独自のオブジェクトを作成する方法を説明します。

オブジェクトの概要
---------

他の多くのプログラミング言語と同様、JavaScript におけるオブジェクトも、現実世界の「もの」 (すなわちオブジェクト) になぞらえることができます。JavaScript におけるオブジェクトの概念は、現実世界に実在する「もの」との対比で解釈できます。

JavaScript において、オブジェクトはプロパティと型を持つ独立した存在です。カップを例に考えてみましょう。カップは様々なプロパティ (特性) をもったもの (オブジェクト) です。カップは、色や形状、重さや材質といったプロパティを持っています。同様に、JavaScript のオブジェクトもプロパティを持つことができ、プロパティによってそのオブジェクトの特徴を定義することができます。

オブジェクトとプロパティ
------------

JavaScript のオブジェクトは、自身に関連付けられたプロパティを持ちます。オブジェクトのプロパティは、オブジェクトに関連付けられている変数と捉えることができます。オブジェクトのプロパティは、オブジェクトに属するものという点を除けば、基本的に通常の JavaScript 変数と同じようなものです。オブジェクトのプロパティは、オブジェクトの特性を定義します。オブジェクトのプロパティには、単純なドット表記でアクセスします。

```js
objectName.propertyName;
```

すべての JavaScript の変数と同じく、オブジェクト名 (通常の変数にもなります) とプロパティ名では、大文字と小文字は厳密に区別されます。プロパティに値を代入することでプロパティを定義する事ができます。以下のようにして、`myCar` という名前のオブジェクトを作成し、`make`、`model`、`year` という名前のプロパティを付与することができます

```js
var myCar = new Object();
myCar.make = "Ford";
myCar.model = "Mustang";
myCar.year = 1969;
```

上記の例は、\*\*オブジェクト初期化子\*\*を使用して作成することもできます。オブジェクト初期化子は、中括弧 (`{}`) で囲まれたオブジェクトのプロパティ名と関連する値の 0 個以上のペアをカンマで区切ったリストです。

```js
var myCar = {
  make: "Ford",
  model: "Mustang",
  year: 1969,
};
```

オブジェクトに割り当てられていないプロパティは `undefined` です (`null` ではありません)。

```js
myCar.color; // undefined
```

JavaScript オブジェクトのプロパティは、ブラケット (角括弧) 記述法でもアクセスすることができます (詳しくはプロパティのアクセサーを参照してください)。個々のプロパティが文字列値と関連付けられてアクセスできるため、オブジェクトは*連想配列*と呼ばれることがあります。ですから例えば、`myCar` オブジェクトのプロパティに次のようにアクセスできます。

```js
myCar["make"] = "Ford";
myCar["model"] = "Mustang";
myCar["year"] = 1969;
```

オブジェクトプロパティの名前には、あらゆる有効な JavaScript 文字列 (空文字列を含む) か、文字列に変換できるものが使用できます。しかしながら、JavaScript 識別子として有効ではないプロパティ名 (例えば空白やダッシュを含んでいたり、数字で始まったりするプロパティ名) には、ブラケット (角括弧) 表記法でのみアクセスできます。この表記法はプロパティ名を動的に決める場合 (プロパティ名が実行時に決まる場合) に便利です。例を示します。

```js
// カンマで区切られた 4 つの変数が作成され、
// 1 つに割り当てられます。
var myObj = new Object(),
  str = "myString",
  rand = Math.random(),
  obj = new Object();

myObj.type = "ドット表記";
myObj["date created"] = "空白入りの文字列";
myObj[str] = "文字列の値";
myObj[rand] = "乱数";
myObj[obj] = "オブジェクト";
myObj[""] = "空文字列も可能";

console.log(myObj);
```

なお、JavaScript のオブジェクトのプロパティ名 (キー) は文字列かシンボルしか扱えないので、各括弧表記の中のキーはすべて、シンボルを除いて文字列に変換されます (将来、クラスフィールドの提案が進行すると、プライベート名も追加される予定ですが、`[]` の形は使用できません)。例えば、上記のコードで `obj` キーが `myObj` に追加されるとき、JavaScript は `obj.toString()` メソッドを呼び出し、結果の文字列を新しいキーとして使用します。

変数内の文字列値を使ってプロパティにアクセスすることもできます。

```js
var propertyName = "make";
myCar[propertyName] = "Ford";

propertyName = "model";
myCar[propertyName] = "Mustang";
```

ブラケット表記法を用いて `for...in` でオブジェクトの列挙可能なプロパティすべてを巡回することができます。どのように動作するかを説明するため、以下にオブジェクトとオブジェクト名を引数として渡すと、オブジェクトのプロパティを表示する関数を示します。

```js
function showProps(obj, objName) {
  var result = "";
  for (var i in obj) {
    // obj.hasOwnProperty() はオブジェクトのプロトタイプチェーンからプロパティを絞り込むために使用しています
    if (obj.hasOwnProperty(i)) {
      result += objName + "." + i + " = " + obj[i] + "\n";
    }
  }
  return result;
}
```

そして、`showProps(myCar, "myCar")` のように関数を呼び出すと次の結果が返ります。

```js
myCar.make = Ford;
myCar.model = Mustang;
myCar.year = 1969;
```

オブジェクトの全プロパティの列挙
----------------

ECMAScript 5 以降では、オブジェクトのプロパティをリストアップ/トラバース (横断走査) する言語特有の方法が 3 つあります。

* `for...in` ループ
 この方法は、オブジェクトとそのプロトタイプチェーンにある列挙可能なプロパティをすべて横断します
* `Object.keys(o)`
 このメソッドは、そのオブジェクト独自の (プロトタイプチェーンを除く) 列挙可能なすべてのプロパティ名 ("keys") を配列で返します
* `Object.getOwnPropertyNames(o)`
 このメソッドは、そのオブジェクト独自のすべてのプロパティ名を (列挙可能かどうかに関わらず) 配列で返します

ECMAScript 5 よりも前では、オブジェクトの全プロパティを列挙する言語特有の方法はありません。しかし、次の関数で実現できます。

```js
function listAllProperties(o) {
  var objectToInspect;
  var result = [];

  for (
    objectToInspect = o;
    objectToInspect !== null;
    objectToInspect = Object.getPrototypeOf(objectToInspect)
  ) {
    result = result.concat(Object.getOwnPropertyNames(objectToInspect));
  }

  return result;
}
```

これは「隠された」プロパティ (プロトタイプチェーンのより近いところに他の同名のプロパティがあるために、オブジェクトを通してアクセスすることができないプロトタイプチェーン上のプロパティ) を見つけるのに便利です。アクセス可能なプロパティを列挙するには、配列内の重複を削除するだけで簡単に実現できます。

新しいオブジェクトの作成
------------

JavaScript には数多くの定義済みオブジェクトがあります。さらに、独自のオブジェクトを定義できます。オブジェクトはオブジェクト初期化子を使って作成することができます。他にも、まずコンストラクター関数を作り、その関数を `new` 演算子との組み合わせで呼び出すことでオブジェクトをインスタンス化することもできます。

### オブジェクト初期化子の使用

コンストラクター関数を使ったオブジェクトの作成のほかに、オブジェクト初期化子を使用してオブジェクトを作成することができます。オブジェクト初期化子を使うことを、オブジェクトをリテラル表記法で作ると表現することがあります。「オブジェクト初期化子」は、C++ で使われる用語と同じ意味です。

オブジェクト初期化子を使ったオブジェクトの構文は次のようになります。

```js
var obj = {
  property\_1: value_1, // property\_# は識別子だったり、
  2: value_2, // 数値だったり、
  // ...,
  "property n": value_n, // 文字列だったりします
};
```

`obj` は新しいオブジェクトの名前、`property_i` は識別子 (名前、数値、または文字列リテラルのいずれか)、`value_i` は式で、その値が `property_i` に代入されます。`obj` と代入は任意です。もし他の場所でこのオブジェクトを参照する必要がないのなら、変数への代入は不要です。(なお、もしオブジェクトが文の書かれる場所に現れる場合は、リテラルがブロック文と混同されないように、オブジェクトリテラルを括弧で囲む必要がある場合があります。)

オブジェクト初期化子は式であり、それぞれのオブジェクト初期化子は、それが現れる文が実行されるたびにオブジェクトを作成する結果になります。オブジェクト初期化子が同一であっても、作成されるオブジェクトは互いに等しいとはみなされません。オブジェクトは `new Object()` の呼び出しが行われたかのように作成されます。つまり、オブジェクトリテラル式から作成されるオブジェクトは `Object` のインスタンスです。

次の文では、式 `cond` が true の場合にのみオブジェクトを作り、変数 `x` に代入します。

```js
if (cond) var x = { greeting: "hi there" };
```

次の例では 3 つのプロパティを持った `myHonda` を作ります。なお、`engine` プロパティもまた、プロパティを持つオブジェクトです。

```js
var myHonda = { color: "red", wheels: 4, engine: { cylinders: 4, size: 2.2 } };
```

配列を作るためにオブジェクト初期化子を使うこともできます。配列リテラルを参照してください。

### コンストラクター関数の使用

別の方法として、次の 2 つの手順でオブジェクトを作ることができます。

1. コンストラクター関数を記述してオブジェクトの型を定義します。この時、便宜上の理由から慣習的に、1 文字目は大文字とします。
2. `new` でオブジェクトのインスタンスを作成します。

オブジェクトの型を定義するには、名前、プロパティ、メソッドを指定するオブジェクト型用の関数を作ります。例えば、車についてのオブジェクト型を作りたいとしましょう。このオブジェクト型は `car` と呼ばれ、make、model、year のプロパティを持たせたいとします。これを行うには、以下のような関数を書きます。

```js
function Car(make, model, year) {
  this.make = make;
  this.model = model;
  this.year = year;
}
```

`this` を使うことで、関数に渡されたオブジェクトのプロパティに対し値を代入していることに注意してください。

以下のようにして `mycar` と呼ばれるオブジェクトを作成できるようになりました。

```js
var mycar = new Car("Eagle", "Talon TSi", 1993);
```

この文では `mycar` を作り、プロパティに指定した値を代入します。`mycar.make` の値は文字列 "Eagle" になり、`mycar.year` は整数 1993 になり、といった具合です。

`new` を使って `car` オブジェクトをいくつでも作れます。例えば、

```js
var kenscar = new Car("Nissan", "300ZX", 1992);
var vpgscar = new Car("Mazda", "Miata", 1990);
```

オブジェクトは、別のオブジェクトをプロパティとして持つことができます。例えば、`person` という名前のオブジェクトを次のように定義しましょう。

```js
function Person(name, age, sex) {
  this.name = name;
  this.age = age;
  this.sex = sex;
}
```

それから、2 個の新しい `person` オブジェクトを次のようにインスタンス化します。

```js
var rand = new Person("Rand McKinnon", 33, "M");
var ken = new Person("Ken Jones", 39, "M");
```

そして、`Car` の定義を `person` オブジェクトを取る `owner` プロパティを含むよう、以下のように書き換えることができます。

```js
function Car(make, model, year, owner) {
  this.make = make;
  this.model = model;
  this.year = year;
  this.owner = owner;
}
```

新しいオブジェクトをインスタンス化するには、以下のようにします。

```js
var car1 = new Car("Eagle", "Talon TSi", 1993, rand);
var car2 = new Car("Nissan", "300ZX", 1992, ken);
```

新しいオブジェクトを作成する際、上の文ではリテラル文字列や整数値を渡す代わりに、オブジェクト `rand` と `ken` を引数 owner として渡していることに注意してください。そして、car2 の owner の名前を知りたければ、以下のプロパティでアクセスできます。

```js
car2.owner.name;
```

なお、既に定義されたオブジェクトにはいつでもプロパティを追加することができます。例えば、以下の文は、

```js
car1.color = "black";
```

car1 にプロパティ `color` を追加し、そこに "black" という値を代入します。しかしながら、これは他のどのオブジェクトにも影響しません。同じ型のすべてのオブジェクトに新しいプロパティを追加するには、`car` オブジェクト型の定義にそのプロパティを追加する必要があります。

### Object.create メソッドの使用

オブジェクトは `Object.create()` メソッドを使用して作成することもできます。このメソッドは、コンストラクター関数の定義なしに作りたいオブジェクトのプロトタイプを選べるため、とても便利です。

```js
// Animal のプロパティとメソッドをカプセル化
var Animal = {
  type: "Invertebrates", // プロパティの既定値、「無脊椎動物」
  displayType: function () {
    // Animal の種類を表示するメソッド
    console.log(this.type);
  },
};

// animal1 という新しい animal 型を作成
var animal1 = Object.create(Animal);
animal1.displayType(); // 出力 : Invertebrates

// Fishes という新しい animal 型を作成
var fish = Object.create(Animal);
fish.type = "Fishes";
fish.displayType(); // 出力 : Fishes
```

継承
--

JavaScript のすべてのオブジェクトは、1 つ以上の他のオブジェクトを継承しています。継承元になるオブジェクトはプロトタイプと呼ばれ、継承されたプロパティはコンストラクターの `prototype` オブジェクトにあります。詳細は継承とプロトタイプチェーンを参照してください。

オブジェクトプロパティのインデックス付け
--------------------

オブジェクトのプロパティは、プロパティ名または番号インデックスで参照することができます。名前によってプロパティを初期定義した場合、常に名前を使って参照する必要があり、インデックスによってプロパティを初期定義した場合、常にインデックスを使って参照する必要があります。

この制限は、(以前に `Car` オブジェクト型に対して行ったように) コンストラクター関数でオブジェクトとプロパティを作るときや、個々のプロパティを明示的に定義した場合 (例えば `myCar.color = "red"`) に適用されます。初めにオブジェクトプロパティをインデックスで、たとえば `myCar[5] = "25 mpg"` のように定義した場合、以降そのプロパティは `myCar[5]` としてしか参照できません。

このルールの例外は、`forms` 配列型オブジェクトのような HTML から反映された配列型オブジェクトです。この配列型オブジェクトにあるオブジェクトは、いつでもインデックス (文書中に現れる位置を基準としたもの) と名前 (定義されていれば) のどちらからも参照できます。例えば、文書内の 2 つ目の `<FORM>` タグが `NAME` 属性として "myForm" という値を持つとき、フォームは `document.forms[1]`、`document.forms["myForm"]` 、`document.forms.myForm` のいずれかで参照できます。

オブジェクト型に対するプロパティの定義
-------------------

`prototype` プロパティを使用すると、定義済みのオブジェクト型に対してプロパティを追加することができます。このプロパティはオブジェクトの 1 つのインスタンスだけではなく、指定された型のすべてのオブジェクトで共有されます。次のコードはすべての `car` 型のオブジェクトに `color` プロパティを追加し、オブジェクト `car1` の `color` プロパティに値を代入します。

```js
Car.prototype.color = null;
car1.color = "black";
```

詳しくは、JavaScript リファレンス内にある、`Function` オブジェクトの `prototype` プロパティを参照してください。

メソッドの定義
-------

メソッドはオブジェクトに関連付けられた関数です。簡単に言えば、オブジェクトのプロパティである関数です。メソッドは通常の関数と同じ方法で定義されますが、オブジェクトのプロパティに代入される点が異なります。詳細はメソッドの定義を参照してください。例えば、

```js
objectName.methodname = functionName;

var myObj = {
  myMethod: function(params) {
    // ...処理を行う
  }

  // これでも動作します

  myOtherMethod(params) {
    // ...他の処理を行う
  }
};
```

ここで `objectName` は既存のオブジェクトを、`methodname` はメソッドを割り当てたい名前を、`functionName` は関数の名前を指しています。

そして次のようにオブジェクトに続けてメソッドを呼び出します。

```js
object.methodname(params);
```

オブジェクトのコンストラクター関数にメソッドの定義を含めることで、オブジェクト型に対してメソッドを定義することができます。以前に定義した `car` オブジェクトのプロパティを整形して表示する関数を定義するとします。例えば以下の通りです。

```js
function displayCar() {
  var result = "美しい " + this.year + "年式 " + this.make + " " + this.model;
  pretty\_print(result);
}
```

`pretty_print` は水平線と文字列を表示する関数です。`this` を使ってメソッドが属するオブジェクトを参照していることに注意してください。

次の文をオブジェクトの定義に追加すると、この関数を `car` のメソッドにできます。

```js
this.displayCar = displayCar;
```

そして、`car` の完全な定義は次のようになります。

```js
function Car(make, model, year, owner) {
  this.make = make;
  this.model = model;
  this.year = year;
  this.owner = owner;
  this.displayCar = displayCar;
}
```

次のようにして、個々のオブジェクトに対して `displayCar` メソッドを呼び出せます。

```js
car1.displayCar();
car2.displayCar();
```

オブジェクト参照のための `this` の使用
-----------------------

 JavaScript には、メソッド内で現在のオブジェクトを参照するための `this`
 という特別なキーワードがあります。以下の例には、`Manager` と `Intern` という 2 つのオブジェクトがあり、それぞれが独自の `name`, `age`, `job` を持っています。関数 `sayHi()` の中に `this.name` があることに注目してください。2 つのオブジェクトに追加してそれらを呼び出すことで、`'Hello, My name is'` を返し、その特定のオブジェクトから `name` の値を追加しています。

```js
const Manager = {
  name: "John",
  age: 27,
  job: "Software Engineer",
};
const Intern = {
  name: "Ben",
  age: 21,
  job: "Software Engineer Intern",
};

function sayHi() {
  console.log("Hello, my name is", this.name);
}

// 両方のオブジェクトに sayHi 関数を追加
Manager.sayHi = sayHi;
Intern.sayHi = sayHi;

Manager.sayHi(); // Hello, my name is John'
Intern.sayHi(); // Hello, my name is Ben'
```

`this` は自身が入っているオブジェクトを参照します。上記の例に `howOldAmI()` という新しい関数を作って、その人の年齢を示す文をログに出力できます。

```js
function howOldAmI() {
  console.log("I am " + this.age + " years old.");
}
Manager.howOldAmI = howOldAmI;
Manager.howOldAmI(); // I am 27 years old.
```

ゲッターとセッターの定義
------------

ゲッターは、特定のプロパティの値を取得するメソッドです。セッター は、特定のプロパティの値を設定するメソッドです。ゲッターとセッターは、新しいプロパティの追加をサポートする定義済みのコアオブジェクト、またはユーザー定義オブジェクト上で定義できます。

ゲッターとセッターは次のどちらの方法でも作れます。

* オブジェクト初期化子を使用して定義する。
* ゲッターやセッターを追加するメソッドを使用して、任意のオブジェクトへ後から追加する。

オブジェクト初期化子を使用してゲッターとセッターを定義するには、ゲッターメソッドの前に `get` を、セッターメソッドの前に `set` を記述するだけです。当然ですがゲッターメソッドは引数を想定してはいけませんし、セッターメソッドは正確に 1 つの引数（新しい設定値）を期待します。
 例えば、以下のようになります。

```js
var o = {
  a: 7,
  get b() {
    return this.a + 1;
  },
  set c(x) {
    this.a = x / 2;
  },
};

console.log(o.a); // 7
console.log(o.b); // 8 <-- この時点で get b() メソッドが開始されます。initiated.
o.c = 50; // <-- この時点で set c(x) メソッドが開始されます。
console.log(o.a); // 25
```

`o` オブジェクトのプロパティは以下の通りです。

* `o.a` — 数値
* `o.b` — `o.a` + 1 を返すゲッター
* `o.c` — `o.c` に設定される値を 1/2 にしたものを `o.a` に設定するセッター

`[gs]et propertyName(){ }` という構文により誤解を招くかもしれませんが、オブジェクトリテラル内で "[gs]et *property*()" によって定義されたゲッターやセッターの関数名は、（`__define[GS]etter__` とは対照的に）ゲッターやセッター自体の名前ではないことに注意してください。

ゲッターとセッターはまた、`Object.defineProperties` メソッドを使用して、生成後のオブジェクトにいつでも追加できます。このメソッドの第 1 引数はゲッターまたはセッターを定義するオブジェクトです。第 2 引数はプロパティ名がゲッターまたはセッターの名前で、プロパティ値がゲッターまたはセッター関数を定義するオブジェクトです。前回の例と同じゲッターとセッターを定義する例を見てみましょう。

```js
var o = { a: 0 };

Object.defineProperties(o, {
  b: {
    get: function () {
      return this.a + 1;
    },
  },
  c: {
    set: function (x) {
      this.a = x / 2;
    },
  },
});

o.c = 10; // 'a' プロパティに 10 / 2 (5) を代入するセッターを実行します
console.log(o.b); // a + 1 つまり 6 を与えるゲッターを実行します
```

2 つの方法のどちらを選ぶのかは、自身のプログラミングスタイルや行っている作業によります。すでにオブジェクト初期化子を気に入っているのなら、プロトタイプの定義時にほとんどの場合、最初の書式を選ぶでしょう。この書式はより簡潔で自然です。しかしながら、ゲッターやセッターを後から追加しなければならないとき — 自分がプロトタイプやオブジェクトの詳細を書いていない場合 — には、2 番目の書式だけが使えます。2 番目の書式には JavaScript の動的な性質が表現されています — ただし、コードを読みにくく理解しづらいものにする可能性があります。

プロパティの削除
--------

継承されたものでないプロパティは `delete` 演算子を使って削除できます。以下のコードはプロパティを削除する方法です。

```js
// 2 つのプロパティ a と b を持つ新しいオブジェクト myobj を作成。
var myobj = new Object();
myobj.a = 5;
myobj.b = 12;

// プロパティ a を削除すると、myobj には b プロパティだけが残る。
delete myobj.a;
console.log("a" in myobj); // yields "false"
```

`delete` 演算子はまた、`var` キーワードを使わずに定義されたグローバル変数の削除にも使えます。

```js
g = 17;
delete g;
```

オブジェクトの比較
---------

JavaScript では、オブジェクトは参照型です。2 つの異なるオブジェクトは、同じプロパティを持っていても等値とは見なされません。同じオブジェクトへの参照を比較した時のみ真となります。

```js
// 2 つの変数は、同じプロパティを持つ 2 つの異なるオブジェクト
var fruit = { name: "apple" };
var fruitbear = { name: "apple" };

fruit == fruitbear; // false が返される
fruit === fruitbear; // false が返される
```

```js
// 2 つの変数、オブジェクトは 1 つ
var fruit = { name: "apple" };
var fruitbear = fruit; // fruitbear に fruit オブジェクトへの参照を代入

// fruit と fruitbear は同じオブジェクトを指している
fruit == fruitbear; // true が返される
fruit === fruitbear; // true が返される

fruit.name = "grape";
console.log(fruitbear); // { name: "apple" } ではなく { name: "grape" } と出力される
```

比較演算子についての詳細は、リファレンスの比較演算子の節をご覧ください。

関連情報
----

* より詳しく知りたければ、当ガイドのオブジェクトモデルの詳細をお読みください。
* ECMAScript 2015 のクラス (オブジェクトを作る新しい方法) について知りたければ、リファレンスの JavaScript クラスの節をお読みください。
* « 前のページ
* 次のページ »


キー付きコレクション - JavaScript

キー付きコレクション
==========

* « 前のページ
* 次のページ »

本章では、キーによって順序付けされたデータのコレクションを紹介します。Map および Set オブジェクトは挿入順に反復処理を行える要素を保持します。

Map
---

### `Map` オブジェクト

ECMAScript 2015 で値と値とをマッピングする新しいデータ構造が導入されました。`Map` オブジェクトはシンプルなキー / バリューマップで、挿入順に要素を反復処理することができます。

次のコードでは `Map` を用いたいくつかの基本的な操作を表しています。また、追加の例や全ての API については、`Map` リファレンスページをご覧ください。`for...of` ループを使って、各反復処理において `[key, value]` からなる配列を返しています。

```js
let sayings = new Map();
sayings.set("dog", "woof");
sayings.set("cat", "meow");
sayings.set("elephant", "toot");
sayings.size; // 3
sayings.get("dog"); // woof
sayings.get("fox"); // undefined
sayings.has("bird"); // false
sayings.delete("dog");
sayings.has("dog"); // false

for (let [key, value] of sayings) {
  console.log(key + " goes " + value);
}
// "cat goes meow"
// "elephant goes toot"

sayings.clear();
sayings.size; // 0
```

### `Object` と `Map` との比較

伝統的に、objects は文字列を値にマップするのに使われてきました。オブジェクトを使うことで、キーを値に設定し、その値を取得し、キーを削除し、キーに対応する何かが格納されているかどうかを検出することができます、しかしながら、`Map` の方が少し便利です。

* `Object` のキーは `Strings` オブジェクトです、`Map` ならどんな値も使えるというのに。
* `Map` は簡単にサイズを取得できます。`Object` はサイズを手作業で追跡する必要があります。
* `Map` の反復処理は要素の挿入順に行われます。
* `Object` はプロトタイプを持っているので、オブジェクトによるマップにはデフォルトキーが存在します（これは `map = Object.create(null)` を使って回避できます）。

`Map` と `Object` のどちらを使用すべきかを決めるには下記の 3 つのヒントが役立つでしょう :

* 実行時までキーが不明なとき、またはすべてのキーが同じ型、すべての値が同じ型のときは Object よりも Map を使用しましょう。
* プリミティブ値をキーとして保存する必要がある場合に Map を使用しましょう。Object はキーが数値、真偽値、もしくはいずれのプリミティブ値であるかどうかに関わらず、それぞれのキーを文字列として扱います。
* 個々の要素を操作するロジックがある場合は、Object を使用しましょう。
### `WeakMap` オブジェクト

`WeakMap` オブジェクトは、**キーはオブジェクトのみ**で、値は任意の値にできるキー / バリューのペアからなるコレクションです。キーによるオブジェクト参照は**弱く**保持され、そのオブジェクトへの参照が他に存在しないときはガベージコレクション (GC) の対象になります。`WeakMap` API は `Map` API と同じです。

`Map` オブジェクトとの違いの１つは、`WeakMap` のキーは列挙可能ではないことです（すなわち、キーのリストを取得するメソッドがありません）。もしも列挙可能であれば、リストは非決定性をもたらす、ガベージコレクションの状態に依存することになってしまいます。

詳細やサンプルコードについては、`WeakMap` リファレンスページの「なぜ WeakMap なのか？」もご覧ください。

`WeakMap` オブジェクトのよくある使用方法のひとつとして、オブジェクトに対するプライベートデータの格納、あるいは実装の細部の隠蔽があります。次の例は Nick Fitzgerald 氏のブログ投稿、"Hiding Implementation Details with ECMAScript 6 WeakMaps"（ECMAScript 6 WeakMaps を使って実装の詳細を隠蔽する）です。プライベートなデータとメソッドはオブジェクトの内部に属していて、プライベートな WeakMap オブジェクトに格納されています。インスタンスから露出する全てとプロトタイプは公開されています、他の全てのものは外部よりアクセスできません。`privates` はモジュールから export されていません。

```js
const privates = new WeakMap();

function Public() {
  const me = {
    // ここにプライベートデータが置かれる
  };
  privates.set(this, me);
}

Public.prototype.method = function () {
  const me = privates.get(this);
  // `me` にプライベートデータを詰め込む…
};

module.exports = Public;
```

Set
---

### `Set` オブジェクト

`Set` オブジェクトは値によって構成されるコレクションです。挿入順に要素を反復処理することができます。`Set` の 1 つの値は 1 回だけ出現します; `Set` のコレクションでは値は一意です。

次のコードでは `Set` を用いたいくつかの基本的な操作を表しています。また、追加の例や全ての API については、`Set` リファレンスページをご覧ください。

```js
let mySet = new Set();
mySet.add(1);
mySet.add("some text");
mySet.add("foo");

mySet.has(1); // true
mySet.delete("foo");
mySet.size; // 2

for (let item of mySet) console.log(item);
// 1
// "some text"
```

### `Array` と `Set` 間の変換

`Array.from` または スプレッド構文 を使用して `Set` から `Array` を生成できます。また、`Set` コンストラクタを使って `Array` から `Set` へと逆変換することができます。

**メモ:** `Set` オブジェクトは*一意の値*を格納することにくれぐれも注意してください、重複した要素は `Array` から変換するときに削除されます。

```js
Array.from(mySet);
[...mySet2];

mySet2 = new Set([1, 2, 3, 4]);
```

### `Array` と `Set` との比較

伝統的に、要素の集合は多くの状況において JavaScript の配列に格納されてきました。しかし、新しい `Set` オブジェクトにはいくつかの利点があります :

* 配列の `indexOf` を使用してコレクションに要素が存在しているかどうかを調べるのは低速です。
* `Set` オブジェクトは値を使って要素を削除できます。配列の場合には要素のインデックを使い、スプライス（該当要素を取り除いて残りをつなぎ合わせる）操作が必要です。
* `NaN` 値は配列の `indexOf` で検索することはできません。
* `Set` オブジェクトは一意の値を格納します、あなたが重複を気にする必要がありません。
### `WeakSet` オブジェクト

`WeakSet` オブジェクトは、オブジェクトのコレクションです。`WeakSet` 内の 1 つのオブジェクトは 1 回だけ出現します; `WeakSet` コレクション内では値は一意で、オブジェクトは列挙可能ではありません。

`Set` オブジェクトとの主な違いは下記の通りです :

* `Set` とは対照的に、`WeakSet` は**オブジェクトのみのコレクション**で、任意の型の任意の値でのコレクションではありません。
* `WeakSet` は弱い: コレクションでのオブジェクトでの参照は弱く保持されています。`WeakSet` 内に格納されているオブジェクトに対する参照がなくなった場合、ガベージコレクションされます。これはまた、現在コレクション内に格納されているオブジェクトのリストがないということを表しています。`WeakSet` は列挙可能ではありません。

`WeakSet` オブジェクトの使用例は限定的です。メモリーリークが発生しないため、例えば、DOM 要素をキーとして使用し、監視するためにそれらにマーキングすることが安全に行なえます。

`Map` と `Set` におけるキーと値の等値性
--------------------------

`Map` オブジェクトのキーの等値性と `Set` オブジェクトの値の等値性は両方とも、「same-value-zero アルゴリズム」に基づいています:

* 等値性は原則として同値演算子 `===` のように判定されます。
* `-0` と `+0` は等しいと見なします。
* `NaN` は（`===` とは逆に）自身と等しいと見なされます。
* « 前のページ
* 次のページ »


数値と日付 - JavaScript

数値と日付
=====

* « 前のページ
* 次のページ »

本章では、JavaScript で数値と日付の計算を実行するのに使われる概念、オブジェクト、関数について紹介します。これには 10 進数、2 進数、16 進数数値を含むそれぞれの基数で表された数値を使用することや、数値の幅広い種類の数学的演算を実行するグローバル `Math` オブジェクトの使い方も含みます。

数値
--

JavaScript では、数値はすべて 64 ビット倍精度浮動小数点数のフォーマットである IEEE 754 (すなわち、±2−1022 と ±2+1023 の間、もしくはおよそ ±10−308 と ±10+308 の間の数値、53 ビットの精度による) にしたがって実装されています。±253 − 1 までの整数は正確に表現できます。

浮動小数点数の表現に加えて、数値型は 3 つの記号的な値を持っています。 `+``Infinity`、`-``Infinity`、`NaN`（非数、not-a-number）です。

JavaScript に最近巨大な数値を表す `BigInt` が実装されました。 `BigInt` には注意事項があり、例えば、`BigInt` と `Number` の値は同じ演算で混ぜたり比較することができず、`BigInt` の値を `Math` オブジェクトで使用することもできません。

JavaScript における他のプリミティブ型との関わりについては、JavaScript のデータ型とデータ構造 もご覧ください。

4 種類の数値リテラル、10 進数、2 進数、8 進数、16 進数を使用することができます。

### 10 進数

```js
1234567890;
42;

// ゼロを先頭に使用するときは気をつけて:

0888; // 10 進数として 888 と解析される
0777; // Strict モードでない場合 8 進数として解析される (10 進数の 511 になる)
```

10 進数リテラルはゼロ (`0`) から始めて、それ以降に 10 進の桁を続けることが可能ですが、`0` に続くすべての数値が 8 より小さい場合、その数値は 8 進数として解析されることに注意してください。

### 2 進数

2 進数の構文では、先行ゼロの後に小文字または大文字の "B" を使います (`0b` または `0B`)。`0b` の後の数値が 0 または 1 ではない場合、 `SyntaxError`: "Missing binary digits after 0b"（0b の後に 2 進数の桁がありません） が発生します。

```js
var FLT\_SIGNBIT = 0b10000000000000000000000000000000; // 2147483648
var FLT\_EXPONENT = 0b01111111100000000000000000000000; // 2139095040
var FLT\_MANTISSA = 0b00000000011111111111111111111111; // 8388607
```

### 8 進数

8 進数の構文では、先頭にゼロを使用します。`0` の後の数値が 0 から 7 の範囲外の場合、数値は 10 進数として解釈されます。

```js
var n = 0755; // 493
var m = 0644; // 420
```

ECMAScript 5 における厳格モードでは上記の 8 進数記法を禁じています。8 進数記法は ECMAScript 5 仕様の一部ではありませんが、すべてのブラウザーで先行ゼロによる 8 進数記法をサポートしており、 `0644 === 420` や `"\045" === "%"` となります。ECMAScript 2015 ではまた、先行する `0o` を使う 8 進数構文をサポートしています。

```js
var a = 0o10; // ES2015: 8
```

### 16 進数

16 進数の構文では、先行ゼロの後に小文字または大文字の "X" を使います (`0x` または `0X`)。0x の後の数値が範囲 (0123456789ABCDEF) 外の場合、 `SyntaxError`: "Identifier starts immediately after numeric literal" (数値リテラルの直後に識別子があります) が発生します。

```js
0xfffffffffffffffff; // 295147905179352830000
0x123456789abcdef; // 81985529216486900
0xa; // 10
```

### 指数表現

```js
1e3; // 1000
2e6; // 2000000
0.1e2; // 10
```

Number オブジェクト
-------------

組み込み `Number` オブジェクトは最大値、NaN、無限大といった数値定数のプロパティを持っています。これらのプロパティの値は変更できません。下記のように使用します:

```js
var biggestNum = Number.MAX\_VALUE;
var smallestNum = Number.MIN\_VALUE;
var infiniteNum = Number.POSITIVE\_INFINITY;
var negInfiniteNum = Number.NEGATIVE\_INFINITY;
var notANum = Number.NaN;
```

自作した `Number` オブジェクトのプロパティではなく、上記の定義済み `Number` オブジェクトのプロパティを常に参照してください。

次の表は `Number` オブジェクトのプロパティの要約です。

| プロパティ | 説明 |
| --- | --- |
| `Number.MAX_VALUE` | 表現可能な最大値。(`±1.7976931348623157e+308`) |
| `Number.MIN_VALUE` | 表現可能な最小値。(`±5e-324`) |
| `Number.NaN` | 非数を表す特別な値。 |
| `Number.NEGATIVE_INFINITY` | 負の無限大を表す特別な値。オーバーフローした際に返されます。 |
| `Number.POSITIVE_INFINITY` | 正の無限大を表す特別な値。オーバーフローした際に返されます。 |
| `Number.EPSILON` | `Number` オブジェクトで表現可能な、ある数とそれよりも大きい最小数との差分値 (計算機イプシロン)。(`2.220446049250313e-16`) |
| `Number.MIN_SAFE_INTEGER` | JavaScript で正確に扱える最小の整数値。(−253 + 1, or `−9007199254740991`) |
| `Number.MAX_SAFE_INTEGER` | JavaScript で正確に扱える最大の整数値。(+253 − 1, or `+9007199254740991`) |

| メソッド | 説明 |
| --- | --- |
| `Number.parseFloat()` | 文字列引数を解析し、浮動小数点数を返します。 グローバル関数 `parseFloat()` と同等。 |
| `Number.parseInt()` | 文字列引数を解析し、指定された根（基数）の整数を返します。 グローバル関数 `parseInt()` と同等。 |
| `Number.isFinite()` | 渡された値が有限数であるか否かを判定します。 |
| `Number.isInteger()` | 渡された値が整数であるか否かを判定します。 |
| `Number.isNaN()` | 渡された値が `NaN`（非数）であるか否かを判定します。原型となったグローバル関数 `isNaN()` よりもロバストな（対応能力が強い）バージョン。 |
| `Number.isSafeInteger()` | 渡された値が正確に扱える整数であるか否かを判定します。 |

`Number` オブジェクトのプロトタイプは様々なフォーマットの `Number` オブジェクトから情報を取得するメソッドを提供します。次表は `Number.prototype` のメソッドの要約です。

| メソッド | 説明 |
| --- | --- |
| `toExponential()` | 数値の指数表記を表す文字列を返します。 |
| `toFixed()` | 数値の固定小数点表記を表す文字列を返します。 |
| `toPrecision()` | 特定の精度の固定小数点表記による数値を表す文字列を返します。 |

Math オブジェクト
-----------

組み込み `Math` オブジェクトは数学定数および数学関数のためのプロパティとメソッドを有しています。例えば、`Math` オブジェクトの `PI` プロパティは π (3.141...) の値を持ちます。以下のようにアプリケーション内で使用できます。

```js
Math.PI;
```

同様に、標準的な数学関数が `Math` のメソッドにあります。数学関数には、三角関数、対数、指数、およびその他の関数が含まれます。例えば、三角関数 sin を使用したい場合、下記のように記述します。

```js
Math.sin(1.56);
```

`Math` のすべての三角関数メソッドはラジアンで引数を取ることに注意してください。

次表は `Math` オブジェクトメソッドの要約です。

| メソッド | 説明 |
| --- | --- |
| `abs()` | 絶対値。 |
| `sin()`, `cos()`, `tan()` | 標準三角関数。引数はラジアン。 |
| `asin()`, `acos()`, `atan()`, `atan2()` | 逆三角関数。戻り値はラジアン。 |
| `sinh()`, `cosh()`, `tanh()` | 双曲線三角関数。引数は双曲線角度。 |
| `asinh()`, `acosh()`, `atanh()` | 逆双曲線三角関数。戻り値は双曲線角度。 |
| `pow()`, `exp()`, `expm1()`, `log10()`, `log1p()`, `log2()` | 指数と対数関数。 |
| `floor()`, `ceil()` | 引数以下の最大の整数値、引数以上の最小の整数値を返します。 |
| `min()`, `max()` | カンマで区切られた数値リストの引数から最小値、最大値をそれぞれ返します。 |
| `random()` | 0 から 1 の間のランダムな数値を返します。 |
| `round()`, `fround()`, `trunc()`, | 丸めと切り捨て関数。 |
| `sqrt()`, `cbrt()`, `hypot()` | 平方根、立方根、引数の二乗の和の平方根を返す。 |
| `sign()` | 数の符号、すなわち数が正、負またはゼロかどうかを返します。 |
| `clz32()`, `imul()` | 32 ビットのバイナリー表現にした場合の先行ゼロの個数を返す関数。 2 つの引数を C 言語のように 32 ビット乗算した結果を返す関数。 |

他の多くのオブジェクトとは異なり、決して独自の `Math` オブジェクトを生成しないでください。常にビルトイン `Math` オブジェクトを使用してください。

Date オブジェクト
-----------

JavaScript には日付のためのデータ型がありません。しかし、アプリケーション内で日付を取り扱うための `Date` オブジェクトとそのメソッドが利用できます。 `Date` オブジェクトは日付の設定、取得、操作を行う多数のメソッドを有しています。このオブジェクトはいかなるプロパティも持ちません。

JavaScript は Java と同じように日付を取り扱います。2 つの言語は同様の日付用メソッドを多く持ち、両方の言語とも、Unix タイムスタンプが 1970 年 1 月 1 日 00:00:00 からの秒の数値であるのと同様に、1970 年 1 月 1 日 00:00:00 からのミリ秒の数値で日付を格納しています。

`Date` オブジェクトの設定可能範囲は 1970 年 1 月 1 日 UTC 時間 に対し -100,000,000 日から 100,000,000 日までです。

`Date` オブジェクトは次のように生成します。

```js
var dateObjectName = new Date([parameters]);
```

ここで `dateObjectName` は生成される `Date` オブジェクトの名前です。新しいオブジェクトか、あるいは既存のオブジェクトのプロパティにすることができます。

`new` キーワードなしで `Date` を呼び出すと、単に現在の日付と時間を文字列表現にしたものを返します。

上記構文の `parameters` は以下のいずれかになります。

* パラメータなし: 今日の日時を生成します。例えば、`today = new Date();`
* 次のような形式による日付を表す文字列: "月 日, 年 時:分:秒." 例えば、`var Xmas95 = new Date("December 25, 1995 13:30:00")`。時、分、秒を省略した場合、その値はゼロに設定されます。
* 年、月、日に対応する整数の集合。例えば、`var Xmas95 = new Date(1995, 11, 25)`
* 年、月、日、時、分、秒に対応する整数の集合。例えば、`var Xmas95 = new Date(1995, 11, 25, 9, 30, 0);`
### Date オブジェクトのメソッド

日時を扱う `Date` オブジェクトのメソッドは下記のカテゴリに分類されます:

* "set" メソッド、`Date` オブジェクト内の日時の値の設定を行うメソッド
* "get" メソッド、`Date` オブジェクトから日時を取得を行うメソッド
* "to" メソッド、`Date` オブジェクトから文字列値を返すメソッド
* "parse" と "UTC メソッド、`Date` 文字列を解析するメソッド

"get" と "set" メソッドを使用して、秒、分、時、日、曜日、月、年をそれぞれ取得、設定できます。曜日を返す `getDay` メソッドはありますが、対応する `setDay` メソッドはありません。というのも、曜日は自動的に設定されるからです。これらのメソッドはそれぞれの値を表すのに下記の整数値を使用します:

* 秒と分: 0 〜 59
* 時: 0 〜 23
* 曜日: 0 （日曜日） 〜 6 （土曜日）
* 日: 1 〜 31 （日）
* 月: 0 （1 月） 〜 11 （12 月）
* 年: 1900 年以降の年

例えば、次の日付を定義してみます。

```js
var Xmas95 = new Date("December 25, 1995");
```

すると、`Xmas95.getMonth()` は 11 を返し、`Xmas95.getFullYear()` は 1995 を返します。

`getTime` と `setTime` メソッドは日付を比較するのに便利です。`getTime` メソッドは `Date` オブジェクトに対して January 1, 1970, 00:00:00 からのミリ秒の数値を返します。

例えば、次のコードでは今年に残された日数を表示します。:

```js
var today = new Date();
var endYear = new Date(1995, 11, 31, 23, 59, 59, 999); // 月日を設定
endYear.setFullYear(today.getFullYear()); // 今年の年を設定
var msPerDay = 24 \* 60 \* 60 \* 1000; // 一日をミリ秒に換算
var daysLeft = (endYear.getTime() - today.getTime()) / msPerDay;
var daysLeft = Math.round(daysLeft); // 今年の残り日数を返す
```

この例では、今日の日時を含む `today` と名付けられた `Date` オブジェクトを生成します。それから、`endYear` と名付けられた `Date` オブジェクトを生成し、年を今年に設定します。そして、1 日あたりのミリ秒値を使って、`today` と `endYear` 間の日数を計算する際に `getTime` を使用し、そして日数に丸めます。

`parse` メソッドは日付文字列から既存の `Date` オブジェクトに値を割り当てるのに便利です。例えば、次のコードは `parse` と `setTime` を使用し、日付の値を `IPOdate` オブジェクトに割り当てます:

```js
var IPOdate = new Date();
IPOdate.setTime(Date.parse("Aug 9, 1995"));
```

### 例

次の例では、`JSClock()` 関数がデジタル時計の形式で時刻を返します。

```js
function JSClock() {
  var time = new Date();
  var hour = time.getHours();
  var minute = time.getMinutes();
  var second = time.getSeconds();
  var temp = "" + (hour > 12 ? hour - 12 : hour);
  if (hour == 0) temp = "12";
  temp += (minute < 10 ? ":0" : ":") + minute;
  temp += (second < 10 ? ":0" : ":") + second;
  temp += hour >= 12 ? " P.M." : " A.M.";
  return temp;
}
```

`JSClock` 関数は、はじめに `time` という名前の新しい `Date` オブジェクトを生成します。引数が与えられていないため、time は現在の日付と時刻で生成されます。次に、`getHours` および `getMinutes`、`getSeconds` メソッドを呼び出して、現在の時、分、秒を `hour`、`minute`、`second` に代入します。

続く 4 つの式は、時刻を基にした文字列値を組み立てます。最初の式は `temp` 変数を生成し、それに条件式を用いて値を代入します。`hour` が 12 よりも大きい場合は (`hour - 12`)、そうでない場合は単に hour を代入します。hour が 0 の場合は 12 になります。

次の式は、`minute` 値を `temp` に追加します。`minute` の値が 10 よりも小さい場合、条件式により先行ゼロの文字が追加されます。そうでない場合は区切りのコロン文字を追加します。そして秒の値を同じ方法で `temp` に追加します。

最後の条件式は、`hour` が 12 以上の場合、"P.M." を `temp` に追加します。そうでない場合は "A.M." を `temp` に追加します。

* « 前のページ
* 次のページ »


制御フローとエラー処理 - JavaScript

制御フローとエラー処理
===========

* « 前のページ
* 次のページ »

JavaScript は、特に制御フロー文についてはコンパクトな文のセットに対応しており、アプリケーションに多様な対話的機能を組み込むために利用することができます。この節ではこれらの文の概要を説明します。

JavaScript リファレンスには、この章で紹介する文についての完全な詳細が載っています。また、JavaScript のコードではセミコロン (`;`) 文字で文を区切ります。

あらゆる JavaScript の式は、文でもあります。式に関する詳細については式と演算子を参照ください。

ブロック文
-----

最も基本的な文は*ブロック文*で、文のグループ化に使います。ブロックは、一組の波括弧で区切られます。
```

{
  statement_1;
  statement_2;
  ⋮
  statement_n;
}
```

### 例

ブロック文は一般に制御フロー文 (`if`, `for`, `while`) で用いられます。

```js
while (x < 10) {
  x++;
}
```

ここでは `{ x++; }` がブロック文となります。

**メモ:** ECMAScript 2015 (6th edition) より前の JavaScript にはブロックスコープが**ありません**。古い JavaScript では、ブロック内で導入された変数のスコープは、そのブロックがある関数やスクリプトになり、それらの変数を設定した影響は、そのブロックを越えて持続します。つまり、*ブロック文はスコープを定義しない*ということです。

「単独の」ブロックも正しい構文ですが、C や Java のブロックで提供されるものとは異なる結果をもたらします。例えば、

```js
var x = 1;
{
  var x = 2;
}
console.log(x); // 2 を出力
```

ここで `2` が出力されるのは、ブロック内の `var x` 文がブロックの前の `var x` 文と同じスコープ内にあるためです。(C や Java では、同様のコードで `1` が出力されます。)

**ECMAScript 2015 から**は、`let` 文や `const` による変数宣言はブロックスコープとなります。詳しくは `let` 文や `const` のリファレンスページをご覧ください。

条件文
---

条件文は、指定した条件が true の場合に実行する命令の集まりです。JavaScript は `if...else` と `switch` の 2 つの条件文に対応しています。

### `if...else` 文

`if` を使用すると、論理条件が `true` の場合に文を実行することができます。任意の `else` 節を使用すると、条件が `false` の場合にも文を実行することができます。

`if` 文は次のように使用します。
```

if (condition) {
  statement_1;
} else {
  statement_2;
}
```

条件は、`true` または `false` と評価される任意の式にすることができます。（`true` と `false` の評価の説明については、Boolean を参照してください。）

条件が `true` と評価された場合、`statement_1` が実行されます。そうでなければ、`statement_2` が実行されます。`statement_1` と `statement_2` は、入れ子になった `if` 文も含めて、任意の文にすることができます。

以下のように、`else if` を使用した文を組み合わせて、複数の条件を順番にテストすることもできます。
```

if (condition_1) {
  statement_1;
} else if (condition_2) {
  statement_2;
} else if (condition_n) {
  statement_n;
} else {
  statement_last;
}
```

複数の条件がある場合、`true` と評価された最初の論理条件のみが実行されます。複数の文を実行するには、ブロックステートメント (`{ … }`) 内にグループ化します。

#### ベストプラクティス

一般的に、常にブロック文を使用するのが優れた方法です。*特に* `if` 文を入れ子にしたコードで有効です。
```

if (condition) {
  statement_1_runs_if_condition_is_true;
  statement_2_runs_if_condition_is_true;
} else {
  statement_3_runs_if_condition_is_false;
  statement_4_runs_if_condition_is_false;
}
```

条件式内で単純な代入を行わないでください。コードを一見した際に、代入を等値条件と見間違えるおそれがあるためです。

例えば、このようにはコードを*書かない*でください。

```js
// "x == y" と読み間違えるおそれがある。
if (x = y) {
  /\* ここに文が来る \*/
}
```

条件式で代入を行う必要がある場合、一般的な方法は次のように、代入式をさらに丸括弧でくくることです。

```js
if ((x = y)) {
  /\* ここに文が来る \*/
}
```

#### false と評価される値

以下の値は `false` と評価されます (また、Falsy な値と呼ばれています)。

* `false`
* `undefined`
* `null`
* `0`
* `NaN`
* 空の文字列 (`""`)

上記以外の—オブジェクトを含む—すべての値は、条件文に渡されると `true` と評価されます。

**メモ:** プリミティブな真偽値の `true` と `false` を、`Boolean` オブジェクトの true や false という値と混同しないでください。

例:

```js
var b = new Boolean(false);
if (b)         // この条件は true に評価される
if (b == true) // この条件は false に評価される
```

#### 例

次の例で、関数 `checkData` は `Text` オブジェクトに含まれている文字数が 3 である場合に `true` を返し、そうでない場合はアラートを表示して `false` を返します。

```js
function checkData() {
  if (document.form1.threeChar.value.length == 3) {
    return true;
  } else {
    alert(
      "Enter exactly three characters. " +
        `${document.form1.threeChar.value} is not valid.`,
    );
    return false;
  }
}
```

### `switch` 文

`switch` 文を使うと、プログラムは式を評価し、その式の値を `case` ラベルと照合します。一致すると、プログラムはそのラベルに関連付けられた文を実行します。

`switch` 文は次のようになります。
```

switch (expression) {
  case label_1:
    statements_1
    [break;]
  case label_2:
    statements_2
    [break;]
    …
  default:
    statements_def
    [break;]
}
```

JavaScript は上記の switch 文を次のように評価します。

* プログラムは最初に、式の値に一致するラベルを持つ `case` 節を探し、関連付けられた文を実行します。
* 一致するラベルがない場合、プログラムはオプションの `default` 節を探します。
    + 存在する場合は `default` 節に制御を移し、関連付けられた文を実行します。
    + `default` 節が見つからない場合、プログラムは `switch` 文の末尾の後に続く文から実行を再開します。
    + (慣例により、`default` 節は最後の節に置きますが、そうしなければいけないわけではありません。)

#### break 文

オプションの `break` 文は、それぞれの `case` 節と関連付けられ、該当する文が実行されるとプログラムが `switch` から抜け出し、`switch` の次の文から実行が継続されることを保証します。`break` が省略されると、プログラムは `switch` 文の内部の実行を続けます (そして、次の `case` を順番に評価します)。

#### 例

次の例では、`fruittype` が '`Bananas`' と評価された場合、case '`Bananas`' に一致して、それに関連付けら cv れた文を実行します。`break` 文に出くわすとプログラムは `switch` から抜けて、`switch` の後に続く文を実行します。`break` を省略すると、`case 'Cherries'` の文も実行されます。

```js
switch (fruittype) {
  case "Oranges":
    console.log("Oranges are $0.59 a pound.");
    break;
  case "Apples":
    console.log("Apples are $0.32 a pound.");
    break;
  case "Bananas":
    console.log("Bananas are $0.48 a pound.");
    break;
  case "Cherries":
    console.log("Cherries are $3.00 a pound.");
    break;
  case "Mangoes":
    console.log("Mangoes are $0.56 a pound.");
    break;
  case "Papayas":
    console.log("Mangoes and papayas are $2.79 a pound.");
    break;
  default:
    console.log(`Sorry, we are out of ${fruittype}.`);
}
console.log("Is there anything else you'd like?");
```

例外処理文
-----

`throw` 文を使用して例外を発生させ、`try...catch` 文を使用して例外を処理することができます。

* `throw` 文
* `try...catch` 文
### 例外の型

JavaScript では、ほぼどのようなオブジェクトでも例外として投げることができます。とはいえ、必ずしも投げられるオブジェクトすべてが同等に作られているわけではありません。数値や文字列をエラーとして投げる方法がよく用いられますが、こうした用途のために特別に作られた例外データ型を使用した方がより効率的な場合もあります。

* ECMAScript 例外
* `DOMException` と `DOMError`
### `throw` 文

`throw` 文は、例外を投げるために使用します。例外を投げるには、投げたい値を含む式を指定してください。
```

throw expression;
```

特定の型の式だけではなく、あらゆる式を投げることができます。下記のコードでは、さまざまな型の例外を投げています。

```js
throw "Error2"; // 文字列型
throw 42; // 数値型
throw true; // 論理型
throw {
  toString: function () {
    return "これはオブジェクトです！";
  },
};
```

**メモ:** 例外を投げる際にオブジェクトを指定することができます。そして、`catch` ブロックでそのオブジェクトのプロパティを参照することができます。

```js
// UserException というオブジェクト型を作成
function UserException(message) {
  this.message = message;
  this.name = "UserException";
}

// 文字列として使用されるとき（例 : エラーコンソール上）に
// 例外を整形する
UserException.prototype.toString = function () {
  return `${this.name}: "${this.message}"`;
};

// UserException のインスタンスを作成し、それを投げる
throw new UserException("Value too high");
```

### `try...catch` 文

`try...catch` 文はテストしたい文のブロックを指定し、さらに投げられる例外に対する 1 つ以上の対処方法を指定します。例外が投げられると、`try...catch` 文がそれを受け取ります。

`try...catch` 文は 1 つの `try` ブロックと 0 個以上の `catch` ブロックで構成されます。`try` ブロックは 1 つ以上の文を含み、`catch` ブロックは `try` ブロックで例外が投げられた場合の処理を指定する文が含まれます。

要するに、成功した場合に実行したい `try` ブロックと、失敗した場合に制御を移行させたい `catch` ブロックで構成されています。`try` ブロック内（もしくは `try` ブロック内から呼び出された関数内）のいずれかの文が例外を投げると、制御は*すぐに* `catch` ブロックに移ります。`try` ブロックで例外が投げられなかった場合、`catch` ブロックはスキップされます。`finally` ブロックは `try` および `catch` ブロックを実行した後に実行しますが、`try...catch` 文の後に続く文より先に実行されます。

次の例では `try...catch` 文を使用しています。この例では渡された値に基づいて、配列から月の名前を取り出す関数を実行します。値に対応する月の数字 (`1`–`12`) が無い場合は `"InvalidMonthNo"` という値を持つ例外が投げられ、`catch` ブロックの中の文は `monthName` という変数に `'unknown'` という値をセットします。

```js
function getMonthName(mo) {
  mo = mo - 1; // 月の数字を配列のインデックスに合わせる (1 = Jan, 12 = Dec)
  let months = [
    "Jan",
    "Feb",
    "Mar",
    "Apr",
    "May",
    "Jun",
    "Jul",
    "Aug",
    "Sep",
    "Oct",
    "Nov",
    "Dec",
  ];
  if (months[mo]) {
    return months[mo];
  } else {
    throw "InvalidMonthNo"; // throw キーワードが使われている
  }
}

try {
  // 実行を試みる文
  monthName = getMonthName(myMonth); // この関数が例外を投げる場合がある
} catch (e) {
  monthName = "unknown";
  logMyErrors(e); // 例外オブジェクトをエラーハンドラーに渡す
}
```

#### `catch` ブロック

`catch` ブロックを用いることで、`try` ブロックで生じうるすべての例外を扱うことができます。
```

catch (catchID) {
  statements
}
```

`catch` ブロックには、`throw` 文で指定される値を保持しておく識別子 (上記の構文における `catchID`) を指定します。投げられた例外についての情報を得るのに、この識別子を使います。

JavaScript は `catch` ブロックに入るときにこの識別子を作成します。識別子は `catch` ブロックの区間だけ存続します。つまり、`catch` ブロックの実行が終わると、その識別子はもう使えなくなります。

例えば、次のコードは例外を投げます。例外が生じると、制御が `catch` ブロックに移ります。

```js
try {
  throw "myException"; // 例外を生成
} catch (err) {
  // ここには例外を扱う文が入る
  logMyErrors(err); // 例外オブジェクトをエラーハンドラに渡す
}
```

**メモ:** **ベストプラクティス:** `catch` ブロック内でコンソールにエラーをログ出力する場合は、`console.log()` よりも `console.error()` がデバッグ目的では推奨されています。これはメッセージをエラーとして書式化し、ページによって生成されたエラーメッセージの一覧に追加します。

#### `finally` ブロック

`finally` ブロックは、`try` および `catch` ブロックの実行*後*に実行される文が入ります。また、`finally` ブロックの中のコードは `try…catch…finally` に続く分が実行される*前*に実行されます。

また、`finally` ブロックは例外が発生する*かどうかにかかわらず*実行されるということに注意することも大切です。また、例外が発生したら、`finally` ブロック内の文は発生した例外が `catch` ブロックで処理されなくても実行されます。

`finally` ブロックを使用することで、例外発生時に適切にスクリプトを停止させることができます。例えば、スクリプトで使用していたリソースを解放しなければならない場合などです。

次の例ではファイルを開き、そのファイルを使用する文を実行します (サーバー側 JavaScript ではファイルにアクセスできます)。ファイルを開いている間に発生すると、スクリプトが停止する前に `finally` ブロックでそのファイルを閉じます。ここで `finally` を使用することで、エラーが発生した場合であってもファイルが開かれたままにならないことを*保証*します。

```js
openMyFile();
try {
  writeMyFile(theData); // ここでエラーが投げられる可能性がある
} catch (e) {
  handleError(e); // エラーを受け取り、それを処理する
} finally {
  closeMyFile(); // 常にリソースが閉じられる
}
```

`finally` ブロックが値を返す場合、その値は `try` および `catch` ブロックの `return` 文にかかわらず `try…catch…finally` 全体が生成する返値になります。

```js
function f() {
  try {
    console.log(0);
    throw "bogus";
  } catch (e) {
    console.log(1);
    return true; // この返値は、finally ブロックが
    // 完了するまで保留となる
    console.log(2); // ここまで到達しない
  } finally {
    console.log(3);
    return false; // 直前の "return" が上書きされる
    console.log(4); // ここまで到達しない
  }
  // ここで "return false" が実行される
  console.log(5); // ここまで到達しない
}
console.log(f()); // 0, 1, 3, false
```

`finally` ブロックによる返値の上書きは、`catch` ブロック内で発生した、または再発生した例外にも適用されます。

```js
function f() {
  try {
    throw "bogus";
  } catch (e) {
    console.log('caught inner "bogus"');
    throw e; // この throw 文は finally ブロックが
    // 完了するまで保留になる
  } finally {
    return false; // 直前の "throw" が上書きされる
  }
  // ここで "return false" が実行される
}

try {
  console.log(f());
} catch (e) {
  // ここには到達しない
  // f() を実行した際、`finally` ブロックが false を返し、
  // 上記の `catch` の中にある `throw` を上書する
  console.log('caught outer "bogus"');
}

// OUTPUT
// caught inner "bogus"
// false
```

#### try...catch 文の入れ子

1 つ以上の `try...catch` 文を入れ子にすることができます。

内側の `try...catch` 文に `catch` ブロックが*ない*場合は次のようになります。

1. `finally` ブロックを含む必要があります。そして、
2. 囲んでいる `try...catch` 文の `catch` ブロックがエラーの照合先としてチェックされます。

詳しくは、`try...catch` の中の nested try-blocks を参照してください。

### Error オブジェクトの活用

エラーの種類に応じて、`name` や `message` プロパティを使ってより詳細なメッセージが得られるようにすることができます。

`name` は `Error` のクラス全般 (例えば `DOMException` や `Error`) を表し、一方 `message` は通常、エラーオブジェクトを文字列に変換したものより簡潔なメッセージを表します。

独自の例外を発生させて、これらのプロパティを有効に活用したい場合 (`catch` ブロックで独自の例外とシステムの例外とを区別したくない場合など)、`Error` コンストラクターが使えます。

例えば、次のようにします。

```js
function doSomethingErrorProne() {
  if (ourCodeMakesAMistake()) {
    throw (new Error('The message'));
  } else {
    doSomethingToGetAJavascriptError();
  }
}
⋮
try {
  doSomethingErrorProne();
} catch (e) {               // `console.error()` を実際に使ってログを出力してみます
  console.error(e.name);    // 'Error' をログ出力
  console.error(e.message); // 'The message'、または JavaScript のエラーメッセージをログ出力
}
```

* « 前のページ
* 次のページ »


JavaScript の型付き配列 - JavaScript

JavaScript の型付き配列
=================

**JavaScript の型付き配列**は配列状のオブジェクトであり、生のバイナリーデータにアクセスする手段を提供します。

`Array` オブジェクトは動的に拡大または縮小され、任意の JavaScript 値を持つことができます。JavaScript エンジンは、これらの配列を高速化するために最適化を実施します。しかしながら、音声や動画の操作、WebSocket を使った生データへのアクセスなどの機能が加わり、ウェブアプリケーションがどんどん強力になるにつれて、 JavaScript コードで型付き配列を用いて生データを高速に簡単に操作できると便利な場面があることが分かってきました。そこで、型付き配列の登場です。 JavaScript の型付き配列の各要素は、 8 ビットの整数から 64 ビットの浮動小数点数まで、いくつかの対応している形式のうちの 1 つの生のバイナリー値です。

ただし、型付き配列を通常の配列と混同しては*いけません*。型付き配列に対して `Array.isArray()` を呼び出すと `false` を返します。また、通常の配列では使用できるが型付き配列では対応していないメソッドがあります（例えば push や pop）。

バッファーとビュー: 型付き配列の構造
-------------------

最大限の柔軟性と効率性を達成するために、JavaScript の型付き配列では **バッファー** と **ビュー** に実装を分けています。バッファー（`ArrayBuffer` オブジェクトで実装）は、データの塊を表すオブジェクトです。これは特に形式がなく、またその中身にアクセスする手段を提供しません。バッファーに格納されている情報にアクセスするには、ビューを使用する必要があります。ビューはコンテキスト（データの種類、開始位置のオフセット、要素の数）を提供し、データを実際の型付き配列に返します。

![Typed arrays in an ArrayBuffer](/ja/docs/Web/JavaScript/Guide/Typed_arrays/typed_arrays.png)

### ArrayBuffer

`ArrayBuffer` は、一般的な固定長のバイナリーデータのバッファーを示すために使用するデータ型です。 `ArrayBuffer` の内容物を直接操作することはできません。代わりにバッファーを特定の形式で表現し、またバッファーの内容物を読み書きするために使用する、型付き配列のビューまたは `DataView` を作成します。

### 型付き配列のビュー

型付き配列のビューは自身を表現する名称を持ち、`Int8`、`Uint32`、`Float64` などの一般的な数値型のビューを提供します。特別な型付き配列のビューとして `Uint8ClampedArray` があります。これは、値を 0 から 255 の間に制限します。例えば Canvas のデータ処理に役立ちます。

| 型 | 値の範囲 | バイト数 | 説明 | Web IDL 型 | 同等の C の型 |
| --- | --- | --- | --- | --- | --- |
| `Int8Array` | -128 ～ 127 | 1 | 8 ビット 2 の補数方式の符号付き整数値 | `byte` | `int8_t` |
| `Uint8Array` | 0 ～ 255 | 1 | 8 ビット符号なし整数値 | `octet` | `uint8_t` |
| `Uint8ClampedArray` | 0 ～ 255 | 1 | 8 ビット符号なし整数値（切り詰め） | `octet` | `uint8_t` |
| `Int16Array` | -32768 ～ 32767 | 2 | 16 ビット 2 の補数方式の符号付き整数値 | `short` | `int16_t` |
| `Uint16Array` | 0 ～ 65535 | 2 | 16 ビット符号なし整数値 | `unsigned short` | `uint16_t` |
| `Int32Array` | -2147483648 ～ 2147483647 | 4 | 32 ビット 2 の補数方式の符号付き整数値 | `long` | `int32_t` |
| `Uint32Array` | 0 ～ 4294967295 | 4 | 32 ビット符号なし整数値 | `unsigned long` | `uint32_t` |
| `Float32Array` | `-3.4E38` ～ `3.4E38` および `1.2E-38` が最小の正の値 | 4 | 32 ビットIEEE 浮動小数点数 (7 桁の有効数字、例えば `1.123456`) | `unrestricted float` | `float` |
| `Float64Array` | `-1.8E308` ～ `1.8E308` および `5E-324` が最小の正の値 | 8 | 64 ビットIEEE 浮動小数点数 (16 桁の有効数字、例えば `1.123...15`) | `unrestricted double` | `double` |
| `BigInt64Array` | -263 ～ 263 - 1 | 8 | 64 ビット 2 の補数方式の符号付き整数値 | `bigint` | `int64_t (signed long long)` |
| `BigUint64Array` | 0 ～ 264 - 1 | 8 | 64 ビット符号なし整数値 | `bigint` | `uint64_t (unsigned long long)` |

### DataView

`DataView` は、任意のデータをバッファーに読み書きするためのゲッター/セッター API を提供する、低レベルインターフェイスです。これは、例えばさまざまな型のデータを扱う場合に役立ちます。型付き配列のビューは、プラットフォームのネイティブのバイト順 (Endianness) になります。`DataView` では、バイト順を制御できます。既定でははビッグエンディアンですが、ゲッター/セッターメソッドでリトルエンディアンに設定できます。

型付き配列を使用する Web API
------------------

これらは、型付き配列を利用する API の例です。他にもありますが、常に追加されています。

`FileReader.prototype.readAsArrayBuffer()`

`FileReader.prototype.readAsArrayBuffer()` メソッドは、指定した `Blob` または `File` の内容物の読み取りを開始します。

`XMLHttpRequest.prototype.send()`

`XMLHttpRequest` のインスタンスの `send()` メソッドが、型付き配列と `ArrayBuffer` オブジェクトを引数としてサポートしました。

`ImageData.data`

これは `0` から `255` の間の整数値である、RGBA データを持つ一次元配列を表す `Uint8ClampedArray` です。

例
-

### バッファーと合わせてビューを使用する

始めにバッファーの作成が必要であり、ここでは 16 バイト固定長とします。

```js
const buffer = new ArrayBuffer(16);
```

これで、全体が 0 で初期化されたメモリー領域ができました。しかし、そのバッファーに対してできることはあまりありません。バッファーが実際に 16 バイトの大きさであることを確認する程度のことはできます。

```js
if (buffer.byteLength === 16) {
  console.log("Yes, it's 16 bytes.");
} else {
  console.log("Oh no, it's the wrong size!");
}
```

このバッファーで実際の作業を行う前に、ビューを作成しなければなりません。バッファー内のデータを 32 ビット符号付き整数値の配列として扱うビューを作成してみましょう。

```js
const int32View = new Int32Array(buffer);
```

この時点で配列のフィールドへ、通常の配列と同じようにアクセスすることが可能になります。

```js
for (let i = 0; i < int32View.length; i++) {
  int32View[i] = i \* 2;
}
```

これは配列を値 `0`, `2`, `4`, `6` の 4 つのエントリ (4 つのエントリが各 4 バイトで、合計 16 バイト) で埋めます。

### 同一のデータに対する複数のビュー

同一のデータに対して複数のビューを作成できることを考えると、それらは実に興味深いものになります。例えば、前出のコードの続きを以下のようにします。

```js
const int16View = new Int16Array(buffer);

for (let i = 0; i < int16View.length; i++) {
  console.log(`Entry ${i}: ${int16View[i]}`);
}
```

ここでは、同一のバッファーを既存の 32 ビット値のビューと共有する 16 ビット整数値のビューを作成して、バッファー内の値すべてを 16 ビット整数値として出力しています。すると、`0`, `0`, `2`, `0`, `4`, `0`, `6`, `0` という出力を得ます。

ここで一歩進みましょう。以下のコードについて考えてみてください。

```js
int16View[0] = 32;
console.log(`Entry 0 in the 32-bit array is now ${int32View[0]}`);
```

このコードの出力は `"Entry 0 in the 32 ビットarray is now 32"` になります。

言い換えると、2 つの配列は同じデータバッファーを異なる形式で取り扱う単純なビューであるということです。同様のことを、任意のビュー型で行うことができます。

### 複合データ構造を扱う

1 つのバッファーを、バッファー内において異なるオフセットで始まり、またタイプが異なる複数のビューと結びつけることで、複数の種類のデータを持つデータオブジェクトを取り扱うことが可能になります。これにより、例えば WebGL の複合データ構造やデータファイルを取り扱うことが可能になります。

以下の C 構造体について考えてみましょう。

```cpp
struct someStruct {
  unsigned long id;
  char username[16];
  float amountDue;
};
```

このような形式のデータを含むバッファーは、以下のようにアクセスできます。

```js
const buffer = new ArrayBuffer(24);

// ... read the data into the buffer ...

const idView = new Uint32Array(buffer, 0, 1);
const usernameView = new Uint8Array(buffer, 4, 16);
const amountDueView = new Float32Array(buffer, 20, 1);
```

例えば、合計金額には `amountDueView[0]` でアクセスできます。

**メモ:** C 構造体におけるデータ構造の配置は機種依存です。これらのデータ埋め込みの違いに注意および配慮してください。

### 通常の配列への変換

型付き配列を処理した後は、 `Array` プロトタイプの利点を享受するため通常の配列に変換することが、有用な場合があります。これは `Array.from()` を使用する、あるいは `Array.from` がサポートされていなければ以下のコードを使用して実現できます。

```js
const typedArray = new Uint8Array([1, 2, 3, 4]);
const normalArray = Array.from(typedArray);
```

同様にスプレッド演算子を使用するとこうなります。

```js
const typedArray = new Uint8Array([1, 2, 3, 4]);
const normalArray = [...typedArray];
```

または、 `Array.from()` に対応していない場合は次のコードを使用するとこうなります。

```js
const typedArray = new Uint8Array([1, 2, 3, 4]);
const normalArray = Array.prototype.slice.call(typedArray);
```

関連情報
----

* Base64 でエンコードされた文字列から `ArrayBuffer` または型付き配列を取得
* Faster Canvas Pixel Manipulation with Typed Arrays
* Typed Arrays: Binary Data in the Browser
* エンディアン


関数 - JavaScript

関数
==

* « 前のページ
* 次のページ »

関数は、 JavaScript の基本的な構成要素のひとつです。 JavaScript の関数は、プロシージャに似ています。 — タスクを実行したり値を計算したりする一連の文ですが、プロシージャが関数として認められるためには、何らかの入力を受け取り、入力と出力の間に何らかの明白な関係がある出力を返す必要があります。関数を使用するには、呼び出したいスコープのどこかで関数を定義する必要があります。

より詳しくは JavaScript の関数に関する完全なリファレンスについての章をご覧ください。

関数の定義
-----

### 関数宣言

**関数定義** (**関数宣言**や**関数定義文** とも呼ばれます) は `function` キーワードと、それに続く以下の内容で構成されます。

* 関数の名前。
* 関数への引数のリスト。丸括弧でくくり、カンマで区切ります。
* 関数を定義する JavaScript の文。波括弧 `{...}` でくくります。

例えば、次のコードは `square` という名前の簡単な関数を定義します。

```js
function square(number) {
  return number \* number;
}
```

関数 `square` は `number` という名前の引数を 1 つとります。この関数は、引数 (すなわち `number`) の 2 乗を返すように指示する 1 つの文で構成されています。`return` 文は、関数が返す値を指定します。

```js
return number \* number;
```

プリミティブな引数 (数値など) は**値渡し**で関数に渡されます。つまり、値は関数に渡されますが、関数が引数の値を変更しても、**この変更はグローバルな値や関数の呼び出し元の値には影響を与えません**。

オブジェクト (すなわち非プリミティブ値、例えば `Array` オブジェクトやユーザー定義オブジェクトなど) を引数として渡すと、関数がオブジェクトのプロパティを変更した場合、その変更が関数外でも有効になります。次の例をご覧ください。

```js
function myFunc(theObject) {
  theObject.make = "Toyota";
}

var mycar = { make: "Honda", model: "Accord", year: 1998 };
var x, y;

x = mycar.make; // x は "Honda" という値になる

myFunc(mycar);
y = mycar.make; // y は "Toyota" という値になる
// (プロパティが関数で変更されている)
```

### 関数式

ここまでの関数宣言はすべて構文的な文でしたが、関数は関数式によって作成することもできます。

このような関数は**無名** (anonymous) にすることができます。名前をつけなくてもよいのです。例えば、関数 `square` は次のように定義することができます。

```js
const square = function (number) {
  return number \* number;
};
var x = square(4); // x の値は 16 となる
```

ただし、関数式には名前を指定することもできます。名前を指定することで、関数が自分自身を参照することができ、また、デバッガーのスタックトレースで関数を特定しやすくなります。

```js
const factorial = function fac(n) {
  return n < 2 ? 1 : n \* fac(n - 1);
};

console.log(factorial(3));
```

関数式は、ある関数を別の関数の引数として渡すときに便利です。次の例では、第 1 引数に関数を、第 2 引数に配列を受け取るべき `map` 関数を示しています。

```js
function map(f, a) {
  let result = []; // 新しい配列を作成
  let i; // 変数の宣言
  for (i = 0; i != a.length; i++) result[i] = f(a[i]);
  return result;
}
```

下記のコードでは、この関数は関数式で定義された関数を受け取って、2 つ目の引数で受け取った配列の各要素に対して実行しています。

```js
function map(f, a) {
  let result = []; // 新しい配列を作成
  let i; // 変数の宣言
  for (i = 0; i != a.length; i++) result[i] = f(a[i]);
  return result;
}
const f = function (x) {
  return x \* x \* x;
};
let numbers = [0, 1, 2, 5, 10];
let cube = map(f, numbers);
console.log(cube);
```

これは `[0, 1, 8, 125, 1000]` を返します。

JavaScript では、条件に基づいて関数を定義することもできます。例えば次の関数の定義は、 `myFunc` という関数を、変数 `num` が `0` に等しい場合のみ定義します。

```js
var myFunc;
if (num === 0) {
  myFunc = function (theObject) {
    theObject.make = "Toyota";
  };
}
```

これまで説明してきた関数の定義に加えて、`Function` コンストラクターを、`eval()` のような文字列からの関数作成に用いることができます。

**メソッド**は、オブジェクトのプロパティである関数のことです。オブジェクトとメソッドについて詳しくは、「オブジェクトを利用する」の章をご覧ください。

関数の呼び出し
-------

関数を*定義*しても、その関数が*実行*されるわけではありません。関数の定義とは、ただ単に関数に名前をつけ、その関数が呼び出されたときに何をするかを指定することです。

関数の**呼び出し**は、指定した引数を用いて実際に指定された動作を実行します。例えば、 `square` という関数を定義した場合、次のようにして呼び出すことができます。

```js
square(5);
```

この文は `5` という引数とともに関数を呼び出します。関数は自身の文を実行し、 `25` という値を返します。

関数を呼び出すときは*スコープ内*になければいけませんが、次の例のように、関数の宣言を巻き上げる (呼び出しより後に置く) ことができます。

```js
console.log(square(5));
/\* ... \*/
function square(n) {
  return n \* n;
}
```

関数のスコープは自身が宣言された関数内、あるいは最上位で宣言されたのであればプログラム全体になります。

**メモ:** この動作は、上記の構文 (すなわち `function funcName(){}`) を用いて関数を定義したときに限ることに注意してください。次のコードは動作しません。

これは、関数の巻き上げが*関数式*ではなく*関数宣言*でしか機能しないことを意味しています。

```js
console.log(square); // square は初期値が undefined の状態で巻き上げられています。
console.log(square(5)); // Uncaught TypeError: square is not a function
const square = function (n) {
  return n \* n;
};
```

関数の引数は、文字列や数値に限られてはいません。オブジェクト全体を関数に渡すこともできます。`show_props` 関数 (オブジェクトを利用するの章で定義) は、オブジェクトを引数にとる関数の例です。

関数はその関数自身を呼び出すこともできます。例えば、ここに階乗を計算する関数を示します。

```js
function factorial(n) {
  if (n === 0 || n === 1) return 1;
  else return n \* factorial(n - 1);
}
```

1 から 5 までの階乗の計算は、次のようになります。

```js
var a, b, c, d, e;
a = factorial(1); // a の値は 1 となる
b = factorial(2); // b の値は 2 となる
c = factorial(3); // c の値は 6 となる
d = factorial(4); // d の値は 24 となる
e = factorial(5); // e の値は 120 となる
```

関数を呼び出す方法は他にもあります。関数を動的に呼び出す必要があったり、関数の引数の数が変化したり、関数呼び出しのコンテキストを実行時に決定された特定のオブジェクトに設定する必要があったりする場合がよくあります。

*関数はそれ自体がオブジェクト*です。 — そして、それらのオブジェクトはメソッドを持っています。 (`Function` オブジェクトを参照してください。) そのうちのひとつ、 `apply()` メソッドを使って、この目的を達成することができます。

関数のスコープ
-------

関数の内部で宣言された変数は、関数の外部からアクセスすることができません。これは、変数が関数のスコープ内でのみ定義されているためです。その一方、関数は自身が定義されたスコープ内で定義されているすべての変数や関数にアクセスできます。

言い換えると、グローバルスコープで定義された関数は、グローバルスコープで定義されたすべての変数にアクセスできます。ある関数の内部で宣言された関数は、自身の親となる関数内で定義されたすべての変数や、その関数がアクセス権を持つ他の変数にもアクセスできます。

```js
// 以下の変数はグローバルスコープで定義
var num1 = 20,
  num2 = 3,
  name = "Chamakh";

// この関数はグローバルスコープで定義
function multiply() {
  return num1 \* num2;
}

multiply(); // 60 を返す

// 入れ子になっている関数の例
function getScore() {
  var num1 = 2,
    num2 = 3;

  function add() {
    return name + " scored " + (num1 + num2);
  }

  return add();
}

getScore(); // "Chamakh scored 5" を返す
```

スコープと関数スタック
-----------

### 再帰

関数は自身を参照し、呼び出すことができます。関数が自身を参照する方法は 3 種類あります。

1. 関数名
2. `arguments.callee`
3. 関数を参照しているスコープ内の変数

例えば、以下のような関数定義を考えてみましょう。

```js
var foo = function bar() {
  // ここには文が来る
};
```

関数本体の中で、以下のものはすべて同様の意味となります。

1. `bar()`
2. `arguments.callee()`
3. `foo()`

自身を呼び出す関数のことを**再帰関数**と言います。いくつかの点で、再帰はループに似ています。どちらも同じコードを何度も実行しますし、 (無限ループを防ぐため、というより無限再帰を防ぐために) 条件が必要です。

例えば、以下のループは・・・

```js
var x = 0;
while (x < 10) {
  // "x < 10" がループ条件
  // 何らかの処理を行う
  x++;
}
```

再帰関数の宣言とその呼び出しとに置き換えることができます。

```js
function loop(x) {
  if (x >= 10) {
    // "x >= 10" が終了条件 ("!(x < 10)" と同等)
    return;
  }
  // 何らかの処理を行う
  loop(x + 1); // 再帰呼び出し
}
loop(0);
```

一方で、単純な反復ループでは行えないアルゴリズムもあります。例えば、ツリー構造 (例えば DOM) のすべてのノードを取得する処理は、再帰を使うとより簡単です。

```js
function walkTree(node) {
  if (node == null) {
    return;
  }
  // ノードに対し処理を行う
  for (var i = 0; i < node.childNodes.length; i++) {
    walkTree(node.childNodes[i]);
  }
}
```

関数 `loop` と比較すると、再帰呼び出しごとにさらに多数の再帰呼び出しを行います。

どんな再帰アルゴリズムも再帰でないものに書き換えることが可能ですが、ロジックがはるかに複雑になることが多く、そのためにはスタックを使用する必要があります。

実際、再帰自体もスタックを使用しています。関数スタックです。このスタックのような動作は、次の例で見ることができます。

```js
function foo(i) {
  if (i < 0) return;
  console.log("begin: " + i);
  foo(i - 1);
  console.log("end: " + i);
}
foo(3);

// 出力:

// begin: 3
// begin: 2
// begin: 1
// begin: 0
// end: 0
// end: 1
// end: 2
// end: 3
```

### 入れ子の関数とクロージャ

関数の中に関数を入れ子に (ネスト) することができます。入れ子になった (内側の) 関数は、それを含んでいる (外側の) 関数の外には非公開となります。

これにより**クロージャ**が作られます。クロージャとは、環境に束縛された (式によって「閉じ込められた」) 変数を自由に持たせることができる式 (通常は一つの関数) のことです。

入れ子になった関数はクロージャなので、これはつまり、入れ子になった関数は内包する関数の引数と変数を「継承」することができるということです。別の言い方をすれば、内側の関数は外側の関数のスコープを持っているということです。

まとめると、次のようになります。

* 内側の関数へは、外側の関数の中にある文からのみアクセスできます。
* 内側の関数はクロージャを形成します。内側の関数は外側の関数の引数と変数を利用できますが、外側の関数は内側の関数の引数と変数を利用できません。

以下の例では入れ子になった関数が示されています。

```js
function addSquares(a, b) {
  function square(x) {
    return x \* x;
  }
  return square(a) + square(b);
}
a = addSquares(2, 3); // 13 を返す
b = addSquares(3, 4); // 25 を返す
c = addSquares(4, 5); // 41 を返す
```

内側の関数はクロージャとなるので、外側の関数からクロージャを呼び出し、外部と内部両方の関数に対し引数を指定することができます。

```js
function outside(x) {
  function inside(y) {
    return x + y;
  }
  return inside;
}
fn_inside = outside(3); // 渡されたものに 3 を加算する関数を取得する、と
// 考えてください。
result = fn\_inside(5); // 8 を返す

result1 = outside(3)(5); // 8 を返す
```

### 変数の保護

`inside` が返されるとき、変数 `x` がどのように保護されるのかに注目してください。クロージャはそれ自身が参照しているすべてのスコープ内の引数と変数を保護することになります。それぞれの呼び出しには異なる引数が渡される可能性があるので、 `outside` を呼び出すたびに新しいクロージャが作られます。返された `inside` がもはやアクセスできなくなった時にのみメモリーが解放されます。

これはその他のオブジェクトの内部で参照を保持する場合と違いはないのですが、クロージャの場合は直接参照を設定せず、また情報を取得できないので、明白さは劣ります。

### 多重入れ子関数

関数は下記のように、多重に入れ子にすることができます。

* 関数 (`A`) の中に関数 (`B`) があり、関数 (`B`) の中に関数 (`C`) があるとします。
* 関数 `B` と `C` はクロージャとなるので、 `B` は `A` にアクセスでき、 `C` は `B` にアクセスできます。
* さらに、 `C` は `A` にアクセス可能な `B` にアクセスできるので、 `C` は `A` にもアクセスできます。

このようにして、クロージャは多重スコープを導入できます。つまり関数のスコープが再帰的に包含されているのです。これを*スコープチェーン*と呼びます。 (なぜ「チェーン」と呼ぶのかは後で説明します。)

次の例を見てみましょう。

```js
function A(x) {
  function B(y) {
    function C(z) {
      console.log(x + y + z);
    }
    C(3);
  }
  B(2);
}
A(1); // 6 がログに出力される (1 + 2 + 3)
```

この例では、関数 `C` は関数 `B` の引数 `y` と関数 `A` の引数 `x` にアクセスしています。

なぜこれが可能かというと、

1. 関数 `B` は関数 `A` に含まれたクロージャとなっています (すなわち、 `B` は `A` の引数と変数にアクセスできます)。
2. 関数 `C` は関数 `B` に含まれたクロージャとなっています。
3. クロージャ `B` は `A` の中にあり、 `C` のクロージャも `A` の中にあるので、 `C` は `B` *と* `A` の*両方*の引数と変数にアクセスできます。言い換えれば、`C` は `B`、`A` の順でスコープがつながっている (*chain*) のです。

その一方で、逆は成り立ちません。 `A` は `C` にアクセスできません。なぜなら `A` は、 `C` を変数の一つとして持っている `B` の引数や変数にはアクセスできないからです。このように `C` は `B` の外に対してのみ非公開となっています。

### 名前の衝突

クロージャ中のスコープに同じ名前の 2 つの引数や変数がある場合、*名前の衝突*が生じます。より内側のスコープが優先されるので、最も内側にあるスコープが最優先に、最も外側のスコープが最も低い優先度となります。これがスコープチェーンです。チェーンの最初は最も内側のスコープ、そして最後は最も外側のスコープとなります。次の例を見てみましょう。

```js
function outside() {
  var x = 5;
  function inside(x) {
    return x \* 2;
  }
  return inside;
}

outside()(10); // 10 ではなく 20 を返す
```

文 `return x` の箇所で、`inside` の引数 `x` と `outside` の変数 `x` との間に名前の衝突が発生しています。ここでのスコープチェーンは、{ `inside`, `outside`, グローバルオブジェクト } です。したがって `inside` の `x` が `outside` の `x` より優先され、結果 10 (`outside` の `x`) ではなく、20 (`inside` の `x`) が返されます。

クロージャ
-----

クロージャは、 JavaScript でもっとも強力な機能のひとつです。 JavaScript では関数の入れ子が可能であることに加えて、内側の関数が外側の関数内で定義されたすべての変数や関数に対し (外側の関数がアクセスできる、他の変数や関数すべてにも) 自由にアクセスできます。

しかし、外側の関数は内側の関数内で定義された変数や関数にアクセスできません。これは、内側の関数の変数に対する一種のセキュリティ機構を提供します。

また、内側の関数は外側の関数のスコープにアクセスできることから、もし内側の関数が外側の関数よりも長く生存できた場合、外側の関数内で定義された変数や関数は外側の関数よりも長く残る可能性があります。クロージャは、内側の関数が何かしらの形で外側の関数のスコープ外のどこかで使用可能になった場合に作られます。

```js
var pet = function (name) {
  // 外側の関数は変数 "name" を定義
  var getName = function () {
    return name; // 内側の関数は外側の関数の変数 "name" にアクセス可能
  };
  return getName; // 内側の関数を返すことで、外側の関数に公開する
};
myPet = pet("Vivie");

myPet(); // "Vivie" を返す
```

上記のコードより複雑なコードにすることもできます。外側の関数の内部にある変数を操作するメソッドを含む、オブジェクトを返すことができます。

```js
var createPet = function (name) {
  var sex;

  return {
    setName: function (newName) {
      name = newName;
    },

    getName: function () {
      return name;
    },

    getSex: function () {
      return sex;
    },

    setSex: function (newSex) {
      if (
        typeof newSex === "string" &&
        (newSex.toLowerCase() === "male" || newSex.toLowerCase() === "female")
      ) {
        sex = newSex;
      }
    },
  };
};

var pet = createPet("Vivie");
pet.getName(); // Vivie

pet.setName("Oliver");
pet.setSex("male");
pet.getSex(); // male
pet.getName(); // Oliver
```

上記の例で、外側の関数の変数 `name` は内側の関数からアクセスでき、また内側の関数を通さずに内側の変数へアクセスする他の方法はありません。内側の関数の内部変数は、内側の関数の安全な保存領域として振る舞います。それらは内側の関数と連動するデータを、「永続的」かつ「安全に」保持します。関数は変数を割り当てる必要さえなく、また名前を持つ必要もありません。

```js
var getCode = (function () {
  var apiCode = "0]Eal(eh&2"; // 外側の関数が変更できないようにしたいコード

  return function () {
    return apiCode;
  };
})();

getCode(); // シークレットコードを返す
```

**メモ:** クロージャを使用する際に注意すべき落とし穴がいくつかあります。

取り囲まれている関数で外部スコープの変数と同じ名前の変数を定義した場合、外部スコープにある変数を再び参照する方法がなくなります。 (プログラムが内部スコープを終了するまで、内部スコープ変数は外部変数を「上書き」します。)

```js
var createPet = function (name) {
  // 外側の関数で "name" という変数を定義します。
  return {
    setName: function (name) {
      // 内側の関数も "name" という変数を定義します
      name = name; // 外側の関数で定義した "name" へどのようにしてアクセスするのか？
    },
  };
};
```

arguments オブジェクトの使用
-------------------

関数の引数 (argument) は、配列風オブジェクトで管理されます。関数内では、次のようにして渡された引数を指定することができます。

```js
arguments[i];
```

ここで `i` は引数の順序を表す数で、 `0` から始まります。関数に渡された第 1 引数は `arguments[0]` となります。引数の総数は `arguments.length` で表されます。

`arguments` オブジェクトを使用すると、宣言時の引数の数よりも多くの引数を用いて関数を呼び出すことができます。これによって関数に渡す引数の数が前もってわからない場合にしばしば役立ちます。 `arguments.length` を使用することで、実際に関数に渡された引数の数を特定することができます。そして、 `arguments` オブジェクトを使用して各引数にアクセスできます。

例えば、複数の文字列を連結する関数を考えてみましょう。この関数の唯一の正式な引数は，連結する項目を区切る文字を指定する文字列です。この関数は次のように定義されています。

```js
function myConcat(separator) {
  var result = ""; // リストを初期化する
  var i;
  // 引数について繰り返し
  for (i = 1; i < arguments.length; i++) {
    result += arguments[i] + separator;
  }
  return result;
}
```

この関数に引数をいくつも渡すことができます。そして、各引数を文字列の「リスト」に連結します。

```js
// "red, orange, blue, " を返す
myConcat(", ", "red", "orange", "blue");

// "elephant; giraffe; lion; cheetah; " を返す
myConcat("; ", "elephant", "giraffe", "lion", "cheetah");

// "sage. basil. oregano. pepper. parsley. " を返す
myConcat(". ", "sage", "basil", "oregano", "pepper", "parsley");
```

**メモ:** 変数 `arguments` は「配列風の変数」であり、配列ではありません。添字が数値であることと `length` プロパティがあることで、配列風となってはいます。しかし、配列操作のメソッドのすべてを持っているわけではありません。

さらなる情報については、JavaScript リファレンスの `Function` オブジェクトをご覧ください。

関数の引数
-----

ECMAScript 2015 から、新しい形の引数が 2 つあります。それが*デフォルト引数*と*残余引数*です。

### デフォルト引数

JavaScript では、関数の引数は既定で `undefined` となります。しかし、別の既定値が設定されていれば便利だという状況もあるでしょう。デフォルト引数がここで役に立ちます。

#### デフォルト引数がない場合 (ECMAScript 2015 以前)

以前、既定値を設定する一般的な方法は、関数の本体で引数の値をテストし、`undefined` だった場合にある値を割り当てる、というものでした。

以下の例では、 `b` の値が与えられなかった場合、 `a*b` を評価する際にこの値は `undefined` となるため、 `multiply` を呼び出すと `NaN` が返されます。しかしながら、この例の 2 行目でこの問題を回避しています。

```js
function multiply(a, b) {
  b = typeof b !== "undefined" ? b : 1;

  return a \* b;
}

multiply(5); // 5
```

#### デフォルト引数がある場合 (ECMAScript 2015 以降)

*デフォルト引数*を使えば、関数本体での引数チェックはもう必要ありません。これからは、関数の最初で単純に `b` に `1` を代入することができます。

```js
function multiply(a, b = 1) {
  return a \* b;
}

multiply(5); // 5
```

詳細については、リファレンスのデフォルト引数をご覧ください。

### 残余引数

残余引数の構文によって、不特定多数の引数を配列のように表すことができます。

次の例では、2 つ目から最後までの引数をまとめるのに*残余引数*を使っています。そして最初の引数を使って乗算します。

```js
function multiply(multiplier, ...theArgs) {
  return theArgs.map((x) => multiplier \* x);
}

var arr = multiply(2, 1, 2, 3);
console.log(arr); // [2, 4, 6]
```

アロー関数
-----

アロー関数式 (以前、そして今も誤って**ファットアロー関数**とも呼ばれる) は関数式と比較してより短い構文を持ち、`this`、arguments、super、new.target の値を持ちません。アロー関数は常に無名関数です。 hacks.mozilla.org によるブログ記事、 "ES6 In Depth: Arrow functions" も参照してください。

アロー関数の導入には 2 つの要素が絡んでいます。それは*短縮形の関数*と `this` との*結びつけがない*ことです。

### 短縮形の関数

関数パターンによっては、短縮形の関数がうってつけです。比較してみましょう。

```js
var a = ["Hydrogen", "Helium", "Lithium", "Beryllium"];

var a2 = a.map(function (s) {
  return s.length;
});

console.log(a2); // logs [8, 6, 7, 9]

var a3 = a.map((s) => s.length);

console.log(a3); // logs [8, 6, 7, 9]
```

### 独自の `this` を持たない

アロー関数の導入以前は、すべての新しい関数には独自の this 値が定義されていました (コンストラクターの場合は新しいオブジェクトに、 strict モード の関数呼び出しの場合は undefined に、関数が「オブジェクトのメソッド」として呼び出された場合はその基底オブジェクトに、といったように) 。これはオブジェクト指向プログラミングにとっては厄介です。

```js
function Person() {
  // この Person() コンストラクターは自身を `this` と定義します。
  this.age = 0;

  setInterval(function growUp() {
    // strict モードでない場合、この growUp() 関数は
    // Person() コンストラクターによる定義とは異なり、
    // グローバルオブジェクトを `this` として定義します。
    this.age++;
  }, 1000);
}

var p = new Person();
```

ECMAScript 3/5 では、`this` の値をアクセス可能な別の値に割り当てることでこの問題を解決します。

```js
function Person() {
  var self = this; // `self` の代わりに `that` を選ぶ人もいます。
  // どちらか一方を選び、そちらだけを使うようにしましょう。
  self.age = 0;

  setInterval(function growUp() {
    // このコールバックは、その値が期待通りのオブジェクトを指す
    // 変数 `self` を参照しています。
    self.age++;
  }, 1000);
}
```

代わりに、束縛関数を使って変数を束縛すれば `growUp()` 関数に適切な `this` を渡すことができます。

アロー関数は自身の `this` を持ちません、つまり関数を取り囲む実行コンテキストの `this` の値が使われます。このため、下記のコードでは、`setInterval` に渡される関数内の `this` は、それを取り囲む関数の `this` と同じ値を持ちます。

```js
function Person() {
  this.age = 0;

  setInterval(() => {
    this.age++; // `this` は的確に person オブジェクトを参照する
  }, 1000);
}

var p = new Person();
```

定義済み関数
------

JavaScript には、定義済みの最上位関数がいくつかあります。

`eval()`

**`eval()`** メソッドは文字列として書き表された JavaScript のコードを評価します。

`uneval()`

**`uneval()`** メソッドはオブジェクトのソースコードを表す文字列を生成します。

`isFinite()`

このグローバル関数 **`isFinite()`** は渡された値が有限数であるかを判定します。必要であれば、引数は初めに数値へと変換されます。

`isNaN()`

**`isNaN()`** 関数は値が `NaN` (非数) であるかどうかを判定します。注: `isNaN` 関数内での強制型変換は変わったルールを持っています。値が非数であるかを判定するには、代わりに ECMAScript 2015 で定義された `Number.isNaN()` か、 `typeof` を使うことができます。

`parseFloat()`

**`parseFloat()`** 関数は引数の文字列を解釈して浮動小数点数を返します。

`parseInt()`

**`parseInt()`** 関数は引数の文字列を解釈して指定された基数 (数学的記数法における基数) による整数を返します。

`decodeURI()`

**`decodeURI()`** 関数は前もって `encodeURI` 関数によって、または同様の方法で作られた URL (Uniform Resource Identifier) をデコードします。

`decodeURIComponent()`

**`decodeURIComponent()`** メソッドは前もって `encodeURIComponent` 関数によって、あるいは同様の方法で作られた部分的な URI をデコードします。

`encodeURI()`

**`encodeURI()`** メソッドは、特定の文字をそれぞれ UTF-8 文字エンコーディングで表された 1 から 4 つのエスケープシーケンス (4 つのエスケープシーケンスはサロゲートペア文字のみ) に置き換えることで URI をエンコードします。

`encodeURIComponent()`

**`encodeURIComponent()`** メソッドは、特定の文字をそれぞれ UTF-8 文字エンコーディングで表された 1 から 4 つのエスケープシーケンス (4 つのエスケープシーケンスはサロゲートペア文字のみ) に置き換えることで部分的な URI をエンコードします。

`escape()`

非推奨の **`escape()`** メソッドはある文字列を 16 進数によるエスケープシーケンスで置換した新しい文字列を計算します。代わりに `encodeURI` または `encodeURIComponent` を使用してください。

`unescape()`

非推奨の **`unescape()`** メソッドはある文字列中の 16 進数によるエスケープシーケンスを、それが表す所定の文字に置換した新しい文字列を計算します。エスケープシーケンスは `escape` といった関数によって提供されているかもしれません。 `unescape()` は非推奨なので、代わりに `decodeURI()` または `decodeURIComponent` を使用してください。

* « 前のページ
* 次のページ »


正規表現 - JavaScript

正規表現
====

* « 前のページ
* 次のページ »

 正規表現とは、文字列内で文字の組み合わせを照合するために用いられるパターンです。
 JavaScript では、正規表現はオブジェクトでもあります。これらのパターンは `RegExp` の `exec()` および `test()` メソッドや、`String` の `match()`、`matchAll()`、`replace()`、`replaceAll()`、`search()`、`split()` メソッドで使用できます。
 本章では、 JavaScript の正規表現について説明します。

正規表現の作成
-------

正規表現は 2 通りの方法で作成することができます。

* 次のように、スラッシュで囲まれたパターンからなる正規表現リテラルを使用します。

```js
const re = /ab+c/;
```

正規表現リテラルはスクリプトの読み込み時にその正規表現をコンパイルします。
 正規表現が変化しない場合、この方法を使うとよいパフォーマンスが得られます。
* また、次のように `RegExp` オブジェクトのコンストラクター関数を呼び出す方法があります。

```js
const re = new RegExp("ab+c");
```

コンストラクター関数を使用すると、実行時にその正規表現をコンパイルします。
 正規表現パターンが変わることが分かっている場合や、パターンが分からない場合、ユーザー入力など別なところからパターンを取得する場合は、コンストラクター関数を使用してください。
正規表現パターンの記述
-----------

 正規表現パターンは、 `/abc/` のような単純な文字、または `/ab*c/` や `/Chapter (\d+)\.\d*/` のような単純な文字と特殊文字との組み合わせからなります。
 最後の例には記憶装置として用いられる丸括弧があります。
 パターンのこの部分に一致した箇所は、後で使用できるように記憶されます。詳しくはグループの使用を参照してください。

**メモ:** すでに正規表現の形式に慣れている方は、早見表を見て特定のパターンや構造を素早く検索することもできます。

### 単純なパターンの使い方

 単純なパターンとは、直接一致するものを探したい文字で構成されたものです。例えば `/abc/` というパターンは、文字列の中で `"abc"` という並びが正確に現れる（すべての文字が連続しており、その順で並んでいる）場合のみ、文字の組み合わせに一致します。
 `"Hi, do you know your abc's?"` や `"The latest airplane designs evolved from slabcraft."` 等の文字列には一致します。
 どちらの場合でも、 `"abc"` という部分文字列に一致します。
 `"Grab crab"` という文字列の場合、 `"ab c"` という部分文字列を含んでいますが、正確な `"abc"` という部分文字列を含んでいるわけではないので、一致しません。

### 特殊文字の使い方

 直接の一致よりも高度な何かに一致するものを検索する場合、例えば 1 個以上の b を探したり、ホワイトスペースを見つけたりする場合、パターンに特殊文字を含めることができます。
 例えば、 1 個の `"a"` に 0 個以上の `"b"` が続き、さらに `"c"` が続くものに一致させる場合、 `/ab*c/` というパターンを使用するでしょう。 `"b"` の後の `*` は「直前のアイテムの 0 回以上の出現」を意味します。
 `"cbbabbbbcdebc"` という文字列では、このパターンは `"abbbbc"` という部分文字列に一致します。

以下のページで、正規表現で使用できる特殊文字の完全なリストとその意味を詳しく説明します。

アサーション

アサーションには、行や単語の始まりと終わりを示す境界や、何らかの方法で一致する可能性を示すパターン（先読み、後追い、条件式など）が含まれます。

文字クラス

異なるタイプの文字を判別します。例えば、アルファベットと数字を判別する。

グループと後方参照

グループは複数のパターンを全体としてグループ化し、キャプチャグループは正規表現パターンを使用して文字列と一致させる際に、追加のサブ一致情報を提供します。後方参照は、同じ正規表現で以前に捕捉されたグループを参照します。

数量詞

一致させる文字や式の数を示します。

Unicode プロパティエスケープ

大文字と小文字、数学記号、句読点など、 Unicode 文字のプロパティに基づき区別します。

正規表現で利用可能なすべての特殊文字を一つの表で見たい場合は、以下を参照してください。

正規表現における特殊文字| 文字 / 構造 | 対応する記事 |
| --- | --- |
| `\`, `.`, `\cX`, `\d`,
 `\D`, `\f`, `\n`, `\r`,
 `\s`, `\S`, `\t`, `\v`,
 `\w`, `\W`, `\0`, `\xhh`,
 `\uhhhh`, `\uhhhhh`, `[\b]` | 文字クラス |
| `^`, `$`, `x(?=y)`,
 `x(?!y)`, `(?<=y)x`,
 `(?<!y)x`, `\b`, `\B` | アサーション |
| `(x)`, `(?:x)`, `(?<Name>x)`,
 `x|y`, `[xyz]`, `[^xyz]`,
 `\*Number*` | グループと後方参照 |
| `*`, `+`, `?`,
 `x{*n*}`, `x{*n*,}`,
 `x{*n*,*m*}` | 数量詞 |
| `\p{*UnicodeProperty*}`,
 `\P{*UnicodeProperty*}` | Unicode プロパティのエスケープ |

**メモ:** もっと大きな早見表もあります (個別の記事の一部を集約しただけです)。

### エスケープ

 特殊文字を文字として使う必要がある場合 (例えば、実際に `"*"` を検索する場合)、その前にバックスラッシュを付けてエスケープする必要があります。
 例えば、 `"a"` に `"*"` が続き、さらに `"b"` が続くものを検索するには、 `/a\*b/` と使用します。バックスラッシュは `"*"` を「エスケープ」し、特殊文字ではなく文字として扱うようにします。

 同様に、もし正規表現リテラルを書いていてスラッシュ ('/') に一致させる必要がある場合は、スラッシュをエスケープする必要があります（そうしないとスラッシュでパターンが終了します）。
 例えば、 "/example/" という文字列とそれに続く 1 文字以上のアルファベットを探すには、 `/\/example\/[a-z]+/i` とします。それぞれのスラッシュ前のバックスラッシュが、スラッシュを文字として扱わせます。

 バックスラッシュ文字に一致させるには、バックスラッシュをエスケープする必要があります。
 例えば、 "C:" という文字列で "C" が任意の英字になる場合は、 `/[A-Z]:\\/` を使用します。最初のバックスラッシュがその次の文字をエスケープするので、この表現は単一のバックスラッシュを検索します。

`RegExp` コンストラクターに文字列リテラルを渡して使用する場合は、バックスラッシュは文字列リテラルでのエスケープ文字でもあることを思い出してください。つまり、バックスラッシュを正規表現で用いるには文字列リテラルレベルでエスケープする必要があります。
 `/a\*b/` と `new RegExp("a\\*b")` は同じ表現を生成するものであり、 "a" の次に "\*"、その次に "b" があるものを探します。

エスケープ文字がパターンに含まれていない場合は、 `String.prototype.replace()` を使用して追加することができます。

```js
function escapeRegExp(string) {
  return string.replace(/[.\*+?^${}()|[\]\\]/g, "\\$&"); // $& は一致した部分文字列全体を意味します
}
```

 正規表現の後の "g" はグローバルサーチを行うオプション/フラグで、文字列全体を見て一致したものをすべて返します。
 下のフラグを用いた高度な検索に詳しく説明されています。

*なぜこれが JavaScript に組み込まれていないのでしょうか？* RegExp にそのような関数を追加する提案があります。

### 括弧の使用

 正規表現パターンの一部を括弧で囲むことで、一致した部分文字列を記憶しておくことができます。
 いったん記憶されれば、後からその部分文字列を呼び出すことができます。これに関してはグループと後方参照で説明しています。

JavaScriptでの正規表現の使い方
--------------------

正規表現は、 `RegExp` の `test()` と `exec()` メソッド、 `String` の `match()`、`replace()`、`search()`、`split()` メソッドとともに使用します。

| メソッド | 説明 |
| --- | --- |
| `exec()` | 文字列内で一致するものの検索を実行します。結果情報の配列を返します。一致するものがなければ `null` を返します。 |
| `test()` | 文字列内で一致するものがあるか検査します。 `true` または `false` を返します。 |
| `match()` | キャプチャグループを含む、すべての一致するものを含む配列を返します。一致するものがない場合は `null` を返します。 |
| `matchAll()` | キャプチャグループを含む、すべての一致するものを含むイテレーターを返します。 |
| `search()` | 文字列内で一致するものがあるか検査します。一致した位置を返します。検索に失敗した場合は `-1` を返します。 |
| `replace()` | 文字列内で一致するものを一つ検索し、一致した部分文字列を置換する部分文字列で置換します。 |
| `replaceAll()` | 文字列内で一致するものすべてを検索し、一致した部分文字列を置換する部分文字列で置換します。 |
| `split()` | 正規表現または固定文字列を用いて文字列を分割し、部分文字列の配列に入れます。 |

 あるパターンが文字列に存在するかを知りたいときは、`test()` または `search()` メソッドを使用してください。詳細な情報が知りたいときは (実行時間が長くなりますが) `exec()` または `match()` メソッドを使用してください。
 `exec()` や `match()` を使用して一致した場合、これらのメソッドは配列を返し、関連する正規表現オブジェクトと定義済みオブジェクトである `RegExp` オブジェクトのプロパティを更新します。
 一致しなかった場合、 `exec` メソッドは `null` （`false` に変換される値）を返します。

次の例では、`exec()` メソッドを使用して文字列を検索します。

```js
const myRe = /d(b+)d/g;
const myArray = myRe.exec("cdbbdbsbz");
```

正規表現のプロパティにアクセスする必要がない場合、 `myArray` を作成するもう一つの方法はこのスクリプトの通りです。

```js
const myArray = /d(b+)d/g.exec("cdbbdbsbz");
// 'cdbbdbsbz'.match(/d(b+)d/g) と同様。ただし、
// 'cdbbdbsbz'.match(/d(b+)d/g) は配列 [ "dbbd" ] を出力するのに対し、
// /d(b+)d/g.exec('cdbbdbsbz') は配列 [ 'dbbd', 'bb', index: 1, input: 'cdbbdbsbz' ] を出力する。
```

(異なる動作についての詳しい情報は`exec()` のグローバル検索フラグの使用を参照してください。)

ある文字列から正規表現を組み立てたい場合は、次のスクリプトのような方法があります。

```js
const myRe = new RegExp("d(b+)d", "g");
const myArray = myRe.exec("cdbbdbsbz");
```

これらのスクリプトでは一致したものがあると、配列を返すとともに次表で示されるプロパティを更新します。

正規表現の実行結果| オブジェクト | プロパティまたはインデックス | 説明 | この例の場合 |
| --- | --- | --- | --- |
| `myArray` |  | 一致した文字列と、すべての記憶された部分文字列です。 | `['dbbd', 'bb', index: 1, input: 'cdbbdbsbz']` |
| `index` | 入力文字列で一致した位置を示す、0 から始まる位置です。 | `1` |
| `input` | 元の文字列です。 | `'cdbbdbsbz'` |
| `[0]` | 最後に一致した文字列です。 | `'dbbd'` |
| `myRe` | `lastIndex` |
 次の検索が始まる位置です。
 （このプロパティは、g オプションを用いる正規表現でのみセットされます。
 これについてはフラグを用いた高度な検索で説明します。）
  | `5` |
| `source` | パターンのテキストです。正規表現の実行時ではなく作成時に更新されます。 | `'d(b+)d'` |

 この例の 2 つ目の形式で示したように、オブジェクト初期化子で作成した正規表現は、変数に代入せずに使用することができます。
 しかし、そうすると出現するたびに新しい正規表現になります。
 このため、変数に代入せずにこの形式を使用すると、その後、その正規表現のプロパティにアクセスできません。
 例えば、次のようなスクリプトがあるとします。

```js
const myRe = /d(b+)d/g;
const myArray = myRe.exec("cdbbdbsbz");
console.log(`The value of lastIndex is ${myRe.lastIndex}`);

// "The value of lastIndex is 5"
```

しかし、このスクリプトの場合は次のようになります。

```js
const myArray = /d(b+)d/g.exec("cdbbdbsbz");
console.log(`The value of lastIndex is ${/d(b+)d/g.lastIndex}`);

// "The value of lastIndex is 0"
```

 この 2 つの文中の `/d(b+)d/g` は異なる正規表現オブジェクトであるため、 `lastIndex` プロパティの値も異なります。
 オブジェクト初期化子で作成した正規表現のプロパティにアクセスする必要がある場合は、まずその正規表現を変数に代入する必要があります。

### フラグを用いた高度な検索

 正規表現には、グローバル検索や大文字小文字を区別しない検索などの機能を実現する 6 種類のオプションフラグがあります。
 これらのフラグは、個別に使用することも一緒に使用することもでき、順序は問いません。正規表現の一部に含まれます。

| フラグ | 説明 | 対応するプロパティ |
| --- | --- | --- |
| `d` | 一致した部分文字列の位置を生成します。 | `hasIndices` |
| `g` | グローバル検索を行います。 | `global` |
| `i` | 大文字・小文字を区別しない検索です。 | `ignoreCase` |
| `m` | 複数行の検索です。 | `multiline` |
| `s` | `.` が改行文字に一致するようにします。 | `dotAll` |
| `u` | "unicode" です。パターンを一連の Unicode コードポイントとして扱います。 | `unicode` |
| `y` | 対象文字列の現在の位置から始まる部分に一致するものを探す「先頭固定」 (sticky) 検索を行います。 `sticky` を参照してください。 | `sticky` |

フラグを正規表現に含めるには、次のようにしてください。

```js
const re = /pattern/flags;
```

または

```js
const re = new RegExp("pattern", "flags");
```

フラグは正規表現を作る際になくてはならないものであることに注意してください。後から加えたり取り除いたりすることはできません。

例えば `re = /\w+\s/g` は、1 個以上の文字とそれに続くスペースを探す正規表現を作成します。また、正規表現は文字列全体を通してこの組み合わせを探します。

```js
const re = /\w+\s/g;
const str = "fee fi fo fum";
const myArray = str.match(re);
console.log(myArray);

// ["fee ", "fi ", "fo "]
```

この例ではこの行、

```js
const re = /\w+\s/g;
```

をこの行、

```js
const re = new RegExp("\\w+\\s", "g");
```

に置き換えることができます。得られる結果は同じです。

`m` フラグは、複数行の入力文字列を複数行として扱うことを指定するために使用します。
 `m` フラグを使用すると、 `^` と `$` は、文字列全体ではなく、入力文字列内の任意の行の先頭または末尾に一致します。

#### exec() におけるグローバル検索の使用

`RegExp.prototype.exec()` メソッドに `g` フラグを付けると、それぞれ一致した値とその位置を繰り返し返します。

```js
const str = "fee fi fo fum";
const re = /\w+\s/g;

console.log(re.exec(str)); // ["fee ", index: 0, input: "fee fi fo fum"]
console.log(re.exec(str)); // ["fi ", index: 4, input: "fee fi fo fum"]
console.log(re.exec(str)); // ["fo ", index: 7, input: "fee fi fo fum"]
console.log(re.exec(str)); // null
```

これに対して、 `String.prototype.match()` メソッドは、すべての一致値を一度に返しますが、その位置は含まれません。

```js
console.log(str.match(re)); // ["fee ", "fi ", "fo "]
```

#### Unicode 正規表現の使用

"u" フラグは "unicode" 正規表現を作成するために使われます。つまり、 Unicode テキストに一致するように対応している正規表現です。これは主に Unicode プロパティエスケープ の使用によって実現され、これは "unicode" 正規表現の中でだけ対応します。

例えば、次のような正規表現を使用して、任意の Unicode の「語」と照合することができます。

```js
/\p{L}\*/u;
```

Unicode 正規表現と非 Unicode 正規表現との間には、他にも注意すべき違いがいくつかあります。

* Unicode の正規表現はいわゆる "identity escape" に対応していません。つまり、バックスラッシュをエスケープする必要がなく、事実上無視されるパターンです。例えば、 `/\a/` は文字 'a' に一致する有効な正規表現ですが、 `/\a/u` はそうではありません。
* 波括弧は数量詞として使用されない場合は、エスケープする必要がありま す。例えば、`/{/` は中括弧 '{' に一致する有効な正規表現ですが、`/{/u` はそうではありません - 代わりに、中括弧をエスケープして `/\{/u` を使用しなければなりません。
* `-` の文字は文字クラスの中では異なった解釈をされます。特に、 Unicode の正規表現では、 `-` は文字クラスの先頭または末尾に現れた場合にのみ、リテラルの `-` として解釈されます（範囲指定の一部にはなりません）。例えば、 `/[\w-:]/` は単語、`-`、または `:` に一致する有効な正規表現ですが、 `/\w-:/u` は無効な正規表現です。 `\w` から `:` という範囲は文字の範囲としてきちんと定義されていないので、無効な正規表現だからです。

Unicode の正規表現は、同様に異なる動作をします。 `RegExp.prototype.unicode` には、これに関するより詳しい説明があります。

例
-

**メモ:** 複数の例が次の場所にあります。

* `exec()`、`test()`、`match()`、`matchAll()`、`search()`、`replace()`、`split()` のリファレンスページ
* ガイド記事の文字クラス、アサーション、グループと後方参照、数量詞、Unicode プロパティエスケープ

### 特殊文字を用いた入力の確認

 次の例では、ユーザーが電話番号を入力することを想定しています。
 ユーザーが [チェック] ボタンを押すと、スクリプトはその番号の有効性をチェックします。
 番号が有効な場合 (正規表現で指定された文字列に一致した場合)、スクリプトはユーザーへの感謝と番号の確認を示すメッセージを表示します。
 番号が無効な場合、スクリプトはユーザーに電話番号が無効であることを通知します。

この正規表現は次のものを探します。

1. データの行の先頭: `^`
2. 3 桁の数字 `\d{3}` または `|` 左括弧 `\(` の次に 3 桁の数字 `\d{3}` の次に閉じ括弧 `\)` で、これはキャプチャグループでないもの `(?:)` に入っています。
3. 続いてダッシュ 1 つ、スラッシュ、小数点のうちの何れかがキャプチャグループ `()` に入っているもの
4. 続いて 3 桁の数字 `\d{3}`
5. 続いて (最初の) キャプチャグループ内で記憶されているものに一致するもの `\1`
6. 続いて 4 桁の数字 `\d{4}`
7. 続いてデータの行の末尾: `$`

#### HTML

```html
<p>
  電話番号（市外局番含む）を入力して "チェック" をクリックしてください。
  <br />
  適切な形式は ###-###-#### などです。
</p>
<form id="form">
  <input id="phone" />
  <button type="submit">チェック</button>
</form>
<p id="output"></p>
```

#### JavaScript

```js
const form = document.querySelector("#form");
const input = document.querySelector("#phone");
const output = document.querySelector("#output");

const re = /^(?:\d{3}|\(\d{3}\))([-/.])\d{3}\1\d{4}$/;

function testInfo(phoneInput) {
  const ok = re.exec(phoneInput.value);

  output.textContent = ok
    ? `ありがとう、あなたの電話番号は ${ok[0]}`
    : `${phoneInput.value} は市外局番付き電話番号ではありません！`;
}

form.addEventListener("submit", (event) => {
  event.preventDefault();
  testInfo(input);
});
```

#### 結果

ツール
---

RegExr

正規表現を学び、構築し、テストするためのオンラインツールです。

Regex tester

オンライン正規表現ビルダー/デバッガー

Regex interactive tutorial

オンラインのインタラクティブなチュートリアル、早見表、プレイグラウンド。

Regex visualizer

オンラインのビジュアルな正規表現テスターです。

* « 前のページ
* 次のページ »