constructor - JavaScript

constructor
===========

Baseline Widely available
-------------------------

This feature is well established and works across many devices and browser versions. It’s been available across browsers since March 2017.

* Learn more
* See full compatibility
* Report feedback
**`constructor`** メソッドは、クラスで作成されたオブジェクトインスタンスの生成と初期化を行うための特殊なメソッドです。

**メモ:** このページでは `constructor` の構文を紹介します。すべてのオブジェクトに存在する `constructor` プロパティについては、 `Object.prototype.constructor` を参照してください。

試してみましょう
--------

構文
--

```js
constructor() { /\* … \*/ }
constructor(argument0) { /\* … \*/ }
constructor(argument0, argument1) { /\* … \*/ }
constructor(argument0, argument1, /\* …, \*/ argumentN) { /\* … \*/ }
```

追加の構文上の制約があります。

* `constructor` という名前のクラスメソッドは、ゲッター、セッター、非同期、ジェネレーターメソッドになることはできません。
* 1 つのクラスが複数の `constructor` メソッドを持つことはできません。
解説
--

コンストラクターを使用すると、インスタンス化されたオブジェクトに対して、他のメソッドを呼び出す前に行う必要のある独自の初期化を行うことができます。

```js
class Person {
  constructor(name) {
    this.name = name;
  }

  introduce() {
    console.log(`こんにちは、私は${this.name}です。`);
  }
}

const otto = new Person("オットー");

otto.introduce(); // こんにちは、私はオットーです。
```

独自のコンストラクターを提供しなかった場合は、既定のコンストラクターが提供されます。クラスが基底クラスである場合、既定のコンストラクターは空です。

```js
constructor() {}
```

クラスが派生クラスの場合、既定のコンストラクターが親コンストラクターを呼び出し、与えられた引数を渡します。

```js
constructor(...args) {
  super(...args);
}
```

**メモ:** 上記のような明示的なコンストラクターと既定のコンストラクターの異なる点は、後者が実際には配列イテレーターを呼び出して引数のスプレッドを行わないことです。

それがこのようなコードを動作させることができます。

```js
class ValidationError extends Error {
  printCustomerMessage() {
    return `Validation failed :-( (details: ${this.message})`;
  }
}

try {
  throw new ValidationError("Not a valid phone number");
} catch (error) {
  if (error instanceof ValidationError) {
    console.log(error.name); // これは ValidationError の代わりのエラー
    console.log(error.printCustomerMessage());
  } else {
    console.log("Unknown error", error);
    throw error;
  }
}
```

`ValidationError` クラスは、独自の初期化を行う必要がないため、明示的なコンストラクターは必要ありません。
 既定のコンストラクターは、与えられた引数から親の `Error` の初期化を行います。

 ただし、独自のコンストラクターを提供し、クラスが親クラスから派生している場合は、 `super()` を使用して親クラスのコンストラクターを明示的に呼び出す必要があります。
 例えば、以下のようになります。

```js
class ValidationError extends Error {
  constructor(message) {
    super(message); // 親クラスのコンストラクターの呼び出し
    this.name = "ValidationError";
    this.code = "42";
  }

  printCustomerMessage() {
    return `検証に失敗しました :-( (details: ${this.message}, code: ${this.code})`;
  }
}

try {
  throw new ValidationError("正しい電話番号ではありません。");
} catch (error) {
  if (error instanceof ValidationError) {
    console.log(error.name); // これは ValidationError になる
    console.log(error.printCustomerMessage());
  } else {
    console.log("未知のエラーです", error);
    throw error;
  }
}
```

クラスで `new` を使用すると、以下の段階を踏みます。

1. （派生クラスの場合） `super()` 呼び出しが評価される前の `constructor` 本体。この部分はまだ初期化されていないので、 `this` にアクセスしてはいけません。
2. （派生クラスの場合） `super()` 呼び出しが評価され、同じ処理で親クラスが初期化されます。
3. 現在のクラスのフィールドが初期化されます。
4. `super()` 呼び出し後の `constructor` 本体（基底クラスの場合は本体全体）が評価されます。

`constructor` 本体の中では、 `this` で作成されるオブジェクトにアクセスしたり `new` で呼び出されるクラスに `new.target` でアクセスしたりすることができます。メソッド（ゲッター、セッターを含む）とプロトタイプチェーン は `constructor` が実行される前に `this` で初期化されているので、スーパークラスのコンストラクターからサブクラスのメソッドにアクセスすることもできることに注意してください。しかし、これらのメソッドが `this` を使用している場合、 `this` はまだ完全に初期化されていません。これは、派生クラスのパブリックフィールドを読むと `undefined` になり、プライベートフィールドを読むと `TypeError` になるということです。

```js
new (class C extends class B {
  constructor() {
    console.log(this.foo());
  }
} {
  #a = 1;
  foo() {
    return this.#a; // TypeError: Cannot read private member #a from an object whose class did not declare it
    // これは、クラスが宣言していないのではなく、スーパークラスの
    // コンストラクターが実行されている時点で、プライベートフィールドが
    // まだ初期化されていないため。
  }
})();
```

`constructor` メソッドは返値を持つことができます。基底クラスはコンストラクターから何らかの値を返すことができますが、派生クラスはオブジェクトまたは `undefined` を返すか、 `TypeError` を発生させなければなりません。

```js
class ParentClass {
  constructor() {
    return 1;
  }
}

console.log(new ParentClass()); // ParentClass {}
// 返値はオブジェクトではないので無視される。 これはコンストラクター関数と同じ。

class ChildClass extends ParentClass {
  constructor() {
    return 1;
  }
}

console.log(new ChildClass()); // TypeError: Derived constructors may only return object or undefined
```

親クラスのコンストラクターがオブジェクトを返した場合、そのオブジェクトは派生クラスのクラスフィールドを定義する際の値として使用します。このトリックは「返値の上書き」と呼ばれ、派生クラスのフィールド（プライベートなものも含む）を無関係なオブジェクトに定義することができます。

`constructor` は通常のメソッド構文に従うので、デフォルト引数や残余引数などをすべて使用することができます。

```js
class Person {
  constructor(name = "名無し") {
    this.name = name;
  }
  introduce() {
    console.log(`こんにちは、私は${this.name}`);
  }
}

const person = new Person();
person.introduce(); // こんにちは、私は名無し
```

コンストラクターはリテラル名でなければなりません。計算されたプロパティ名はコンストラクターにはなれません。

```js
class Foo {
  // これは計算プロパティ名です。コンストラクターとしてピックアップされることはありません。
  ["constructor"]() {
    console.log("called");
    this.a = 1;
  }
}

const foo = new Foo(); // ログ出力なし
console.log(foo); // Foo {}
foo.constructor(); // "called" と出力
console.log(foo); // Foo { a: 1 }
```

非同期メソッド、ジェネレータメソッド、アクセサ、クラスフィールドは `constructor` と名付けることは禁止されています。プライベートな名前を `#constructor` と呼び出すことはできません。 `constructor` という名前のメンバーはプレーンなメソッドでなければなりません。

例
-

### constructor メソッドの使用

このコードスニペットは、classes sample (ライブデモ) から転載しています。

```js
class Square extends Polygon {
  constructor(length) {
    // ここでは、ポリゴンの幅と高さを指定された長さにして、親クラスの
    // コンストラクターを呼び出しています。
    super(length, length);
    // メモ: 派生クラスでは、`this` を使用する前に `super()` を呼び出す
    // 必要があります。これを省略すると ReferenceError が発生します。
    this.name = "Square";
  }

  get area() {
    return this.height \* this.width;
  }

  set area(value) {
    this.height = value \*\* 0.5;
    this.width = value \*\* 0.5;
  }
}
```

### 異なるプロトタイプにバインドされたコンストラクターでの super を呼び出し

`super()` は現在のクラスのプロトタイプであるコンストラクターを呼び出します。現在のクラスのプロトタイプを変更した場合、 `super()` は新しいプロトタイプのコンストラクターを呼び出します。現在のクラスの `prototype` プロパティを変更しても、 `super()` が呼び出すコンストラクターには影響しません。

```js
class Polygon {
  constructor() {
    this.name = "Polygon";
  }
}

class Rectangle {
  constructor() {
    this.name = "Rectangle";
  }
}

class Square extends Polygon {
  constructor() {
    super();
  }
}

// Polygon の代わりに（基本クラスである） Rectangle を継承するようにする
Object.setPrototypeOf(Square, Rectangle);

const newInstance = new Square();

// newInstance はまだ Polygon のインスタンスです。
// Square.prototype のプロトタイプを変更していないので、
// newInstance のプロトタイプチェーンは以下のままです。
// newInstance --> Square.prototype --> Polygon.prototype
console.log(newInstance instanceof Polygon); // true
console.log(newInstance instanceof Rectangle); // false

// ただし、 super() はコンストラクターとして Rectangle を呼び出すため、
// newInstance の name プロパティは Rectangle のロジックで初期化されます。
console.log(newInstance.name); // Rectangle
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-static-semantics-constructormethod |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* クラスの使用ガイド
* クラス
* 静的初期化ブロック
* `class`
* `super()`
* `Object.prototype.constructor`


プライベートプロパティ - JavaScript

プライベートプロパティ
===========

**プライベートプロパティ**は、パブリックである通常のクラスプロパティ、例えばクラスフィールドやクラスメソッドなどに対するものです。プライベートプロパティはハッシュ `#` 接頭辞を使用して作成され、クラスの外部から合法的に参照することはできません。これらのクラスプロパティのプライバシーカプセル化は JavaScript 自身によって強制されます。

プライベートのプロパティは、この構文が存在する以前はネイティブではありませんでした。プロトタイプ継承では、 `WeakMap` オブジェクトやクロージャでその振る舞いをエミュレートすることができますが、使いやすさの面からは `#` 構文にはかないません。

構文
--

```js
class ClassWithPrivate {
  #privateField;
  #privateFieldWithInitializer = 42;

  #privateMethod() {
    // …
  }

  static #privateStaticField;
  static #privateStaticFieldWithInitializer = 42;

  static #privateStaticMethod() {
    // …
  }
}
```

さらにいくつかの構文上の制約があります。

* クラス内で宣言するプライベート識別子はすべて固有のものである必要があります。名前空間は、静的プロパティとインスタンスプロパティの間で共有されます。唯一の例外は、 2 つの宣言がゲッターとセッターのペアを定義している場合です。
* プライベート識別子は `#constructor` にすることができません。
解説
--

ほとんどのクラスプロパティには、プライベートの対応するものがあります。

* プライベートフィールド
* プライベートメソッド
* プライベート静的フィールド
* プライベート静的メソッド
* プライベートゲッター
* プライベートセッター
* プライベート静的ゲッター
* プライベート静的セッター

これらの機能をまとめてプライベートプロパティと呼びます。しかし、JavaScript でコンストラクターをプライベートにすることはできません。クラスの外部でクラスが構築されないようにするには、プライベートフラグを使用する必要があります。

プライベートプロパティは **# 名前**（「ハッシュ-名前」と読みます）で宣言され、接頭辞として `#` が付けられます。ハッシュ接頭辞はプロパティ名の一部です。古いアンダースコア接頭辞規約 `_privateField` との関係を思い描いてください。しかし、普通の文字列プロパティではないので、ブラケット記法を使って動的にアクセスすることはできません。

スコープ外から `#` 付きの名を参照すると構文エラーになります。また、呼び出される前に宣言されていないプライベートフィールドを参照したり、宣言されているフィールドを `delete` で削除しようとしても構文エラーになります。

```js
class ClassWithPrivateField {
  #privateField;

  constructor() {;
    delete this.#privateField; // Syntax error
    this.#undeclaredField = 42; // Syntax error
  }
}

const instance = new ClassWithPrivateField();
instance.#privateField; // Syntax error
```

JavaScript は動的言語ですが、ハッシュ識別子の構文が特殊であり、構文レベルで通常のプロパティとは異なるため、このコンパイル時チェックを行うことができます。

**メモ:** Chrome コンソールで実行するコードは、クラス外からプライベートプロパティにアクセスすることができます。これは JavaScript の構文制限を開発者ツール限定で緩和したものです。

プロパティを持っていないオブジェクトからプライベートプロパティにアクセスすると、通常のプロパティのように `undefined` を返すのではなく、`TypeError` が発生します。

```js
class C {
  #x;

  static getX(obj) {
    return obj.#x;
  }
}

console.log(C.getX(new C())); // undefined
console.log(C.getX({})); // TypeError: Cannot read private member #x from an object whose class did not declare it
```

この例では、静的関数の中や、外部で定義したクラスのインスタンスでもプライベートプロパティにアクセスできることも示しています。

`in` 演算子を使用すると、プライベートフィールド（またはプライベートメソッド）が存在するかどうかをチェックできます。そのプライベートフィールドが存在すれば `true` を返し、そうでなければ `false` を返します。

```js
class C {
  #x;
  constructor(x) {
    this.#x = x;
  }
  static getX(obj) {
    if (#x in obj) return obj.#x;

    return "obj must be an instance of C";
  }
}
console.log(C.getX(new C("foo"))); // "foo"
console.log(C.getX(new C(0.196))); // 0.196
console.log(C.getX(new C(new Date()))); // the current date and time
console.log(C.getX({})); // "obj must be an instance of C"
```

オブジェクトが現在のクラスのプライベートプロパティを 1 つでも持っていることが見つかった場合（`try...catch`または`in`チェックのいずれか）、他にもプライベートプロパティをすべて持っている必要があります。あるクラスのプライベートプロパティを持つオブジェクトは、一般的にそのクラスによって構築されたことを意味しています（常にではありません）。

プライベートプロパティは、現在のクラス本体内でのみアクセスすることができ、サブクラスには継承されないため、プロトタイプ継承モデルにはありません。クラスが異なると、プライベートプロパティは同じ名前でも全く異なるものであり、相互運用はできません。クラスごとに管理される、インスタンスに付加された外部メタデータとして考えてください。このため、 `Object.freeze()` や `Object.seal()` は、プライベートプロパティには影響しません。

プライベートフィールドがいつ、どのように初期化されるかについての詳細は、プライベートクラスフィールドを参照してください。

例
-

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

プライベートフィールドには、プライベートインスタンスフィールドとプライベート静的フィールドがあります。プライベートフィールドは、クラス宣言の内部からのみアクセスすることができます。

#### プライベートインスタンスフィールド

プライベートインスタンスフィールドは、パブリック版と次の点で似ています。

* 基底クラスでコンストラクターが実行される前か、サブクラスで `super()` を呼び出した直後に追加されます。
* そのクラスのインスタンスでのみ利用できます。

```js
class ClassWithPrivateField {
  #privateField;

  constructor() {
    this.#privateField = 42;
  }
}

class Subclass extends ClassWithPrivateField {
  #subPrivateField;

  constructor() {
    super();
    this.#subPrivateField = 23;
  }
}

new Subclass(); // 開発者ツールでは Subclass {#privateField: 42, #subPrivateField: 23} と表示
```

**メモ:** 基底クラス `ClassWithPrivateField` の `#privateField` は `ClassWithPrivateField` のプライベートメンバーであり、派生クラス `Subclass` からはアクセスできません。

#### オーバーライドしたオブジェクトの返却

クラスのコンストラクターは異なるオブジェクトを返すことができ、そのオブジェクトは派生クラスのコンストラクターの新しい `this` として使用することができます。派生クラスは、返されたオブジェクトにおいてプライベートフィールドを定義することができます。つまり、無関係なオブジェクトにプライベートフィールドを「刻印」することが可能です。

```js
class Stamper extends class {
  // コンストラクターが指定されたオブジェクトを返す基底クラス
  constructor(obj) {
    return obj;
  }
} {
  // この宣言は、基底クラスのコンストラクターが返すオブジェクトに
  // プライベートフィールドを「刻印」する
  #stamp = 42;
  static getStamp(obj) {
    return obj.#stamp;
  }
}

const obj = {};
new Stamper(obj);
// `Stamper` は `Base` を呼び出して `obj` を返す。次に
// `Stamper` は `obj` に `#stamp` を定義する

console.log(obj); // 一部の開発者ツールでは {#stamp: 42} と表示
console.log(Stamper.getStamp(obj)); // 42
console.log(obj instanceof Stamper); // false

// プライベートプロパティに 2 度刻印することはできません。
new Stamper(obj); // Error: Initializing an object twice is an error with private fields
```

**警告:** これはとても混乱を招きかねないことです。一般的に、コンストラクターから任意のものを返すのは避けるようにしましょう。特に `this` に関係のないものを返すのは避けるようにしましょう。

### プライベート静的フィールド

プライベート静的フィールドは、パブリック版と次の点で似ています。

* クラスが評価される際にクラスのコンストラクターに追加されます。
* クラス自身からのみ利用できます。

```js
class ClassWithPrivateStaticField {
  static #privateStaticField = 42;

  static publicStaticMethod() {
    return ClassWithPrivateStaticField.#privateStaticField;
  }
}

console.log(ClassWithPrivateStaticField.publicStaticMethod()); // 42
```

プライベート静的フィールドには制限があります。プライベート静的フィールドを定義したクラスのみが、そのフィールドにアクセスできます。 `this` を使用すると、予期しない動作をする可能性があります。次の例では、 `SubClass.basePublicStaticMethod()` を呼び出そうとしたときに `this` が `Subclass` クラスを（`BaseClassWithPrivateStaticField` クラスではなく）参照してしまい、 `TypeError` が発生します。

```js
class ClassWithPrivateStaticField {
  static #privateStaticField = 42;

  static publicStaticMethod() {
    return this.#privateStaticField;
  }
}

class Subclass extends ClassWithPrivateStaticField {}

Subclass.publicStaticMethod(); // TypeError: Cannot read private member #privateStaticField from an object whose class did not declare it
```

これは、そのメソッドに `super` を付けて呼び出すのと同じです。 `super` のメソッドはスーパークラスを `this` として呼び出すわけではないからです。

```js
class ClassWithPrivateStaticField {
  static #privateStaticField = 42;

  static publicStaticMethod() {
    // super を呼び出しても、 `this` は Subclass を参照している
    return this.#privateStaticField;
  }
}

class Subclass extends ClassWithPrivateStaticField {
  static callSuperMethod() {
    return super.publicStaticMethod();
  }
}

Subclass.callSuperMethod(); // TypeError: Cannot read private member #privateStaticField from an object whose class did not declare it
```

静的プライベートフィールドには常に `this` ではなく、クラス名でアクセスするようにしてください。

### プライベートメソッド

プライベートメソッドには、プライベートインスタンスメソッドとプライベート静的メソッドがあります。プライベートメソッドは、クラス宣言の内部からのみアクセスすることができます。

#### プライベートインスタンスメソッド

プライベートインスタンスメソッドは、パブリック版と次の点で異なります。

* インスタンスフィールドが導入される前に、直ちに導入されます。
* クラスのインスタンスでのみ利用可能であり、 `.prototype` プロパティでは利用できません。

```js
class ClassWithPrivateMethod {
  #privateMethod() {
    return 42;
  }

  publicMethod() {
    return this.#privateMethod();
  }
}

const instance = new ClassWithPrivateMethod();
console.log(instance.publicMethod()); // 42
```

プライベートインスタンスメソッドは、ジェネレーター、非同期、非同期ジェネレーターの関数にすることができます。プライベートゲッターとセッターも可能で、パブリックのゲッターとセッターと同じ構文に従います。

```js
class ClassWithPrivateAccessor {
  #message;

  get #decoratedMessage() {
    return `🎬${this.#message}🛑`;
  }
  set #decoratedMessage(msg) {
    this.#message = msg;
  }

  constructor() {
    this.#decoratedMessage = "hello world";
    console.log(this.#decoratedMessage);
  }
}

new ClassWithPrivateAccessor(); // 🎬hello world🛑
```

パブリックメソッドと異なり、プライベートメソッドはクラスの `.prototype` プロパティからアクセスすることはできません。

```js
class C {
  #method() {}

  static getMethod(x) {
    return x.#method;
  }
}

console.log(C.getMethod(new C())); // [Function: #method]
console.log(C.getMethod(C.prototype)); // TypeError: Receiver must be an instance of class C
```

#### プライベート静的メソッド

プライベート静的メソッドは、パブリック版と次の点で似ています。

* クラスの評価時点でクラスのコンストラクターに追加されます。
* クラス自身からのみ利用できます。

```js
class ClassWithPrivateStaticMethod {
  static #privateStaticMethod() {
    return 42;
  }

  static publicStaticMethod() {
    return ClassWithPrivateStaticMethod.#privateStaticMethod();
  }
}

console.log(ClassWithPrivateStaticMethod.publicStaticMethod()); // 42
```

プライベート静的メソッドは、ジェネレーター関数、非同期関数、非同期ジェネレーター関数、などがあります。

前述のプライベート静的フィールドの制限は、プライベート静的メソッドにも当てはまり、**`this`** を同様に使用すると予期しない動作が発生する可能性があります。次の例では、 `Derived.publicStaticMethod2()` を呼び出そうとすると、これは `Base` クラスではなく `Derived` クラスを参照するため、`TypeError` が発生します。

```js
class ClassWithPrivateStaticMethod {
  static #privateStaticMethod() {
    return 42;
  }

  static publicStaticMethod() {
    return this.#privateStaticMethod();
  }
}

class Subclass extends ClassWithPrivateStaticMethod {}

console.log(Subclass.publicStaticMethod()); // TypeError: Cannot read private member #privateStaticMethod from an object whose class did not declare it
```

### プライベートコンストラクターをシミュレーション

他の多くの言語では、コンストラクターをプライベートとして指定する機能があり、クラス自身の外部でインスタンスを作成できないようにすることができます。 JavaScript にはこれを行うネイティブな方法はありませんが、プライベート静的フラグを使用することで実現できます。

```js
class PrivateConstructor {
  static #isInternalConstructing = false;

  constructor() {
    if (!PrivateConstructor.#isInternalConstructing) {
      throw new TypeError("PrivateConstructor は構築できません");
    }
    PrivateConstructor.#isInternalConstructing = false;
    // More initialization logic
  }

  static create() {
    PrivateConstructor.#isInternalConstructing = true;
    const instance = new PrivateConstructor();
    return instance;
  }
}

new PrivateConstructor(); // TypeError: PrivateConstructor は構築できません
PrivateConstructor.create(); // PrivateConstructor {}
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # prod-PrivateIdentifier |
| ECMAScript Language Specification # prod-00OK517S |

ブラウザーの互換性
---------

### javascript.classes.private\_class\_fields

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

### javascript.classes.private\_class\_fields\_in

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

### javascript.classes.private\_class\_methods

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* クラスの使用ガイド
* クラス
* パブリッククラスフィールド
* `class`
* Private Syntax FAQ (TC39 class-fields proposal)
* The semantics of all JS class elements (Shu-yu Guo, 2018)
* Public and private class fields (v8.dev, 2018)


パブリッククラスフィールド - JavaScript

パブリッククラスフィールド
=============

パブリックフィールドは、静的なものもインスタンスのものも書き込み可能、列挙可能、構成可能です。そのため、プライベートなものとは異なり、プロトタイプの継承に参加します。

構文
--

```js
class ClassWithField {
  instanceField;
  instanceFieldWithInitializer = "instance field";
  static staticField;
  static staticFieldWithInitializer = "static field";
}
```

それ以外にも構文上の制約があります。

* 静的プロパティ（フィールドまたはメソッド）の名前を `prototype` とすることはできません。
* クラスフィールド（静的またはインスタンス）の名前を `constructor` とすることはできません。
解説
--

このページでは、パブリックインスタンスフィールドについて詳しく紹介します。

* パブリック静的フィールドについては、 `static` を参照してください。
* プライベートフィールドについては、プライベートプロパティを参照してください。
* パブリックメソッドについては、メソッド定義を参照してください。
* パブリックアクセサーについては、ゲッターおよびセッターを参照してください。

パブリックインスタンスフィールドは、作成されたクラスのすべてのインスタンスに存在します。パブリックフィールドを宣言することで、そのフィールドが常に存在することを保証することができ、クラスの定義がより自己文書化されます。

パブリックインスタンスフィールドは、基底クラスではコンストラクターが実行される前の時点でインスタンスに追加され、サブクラスでは `super()` が返された直後に追加されます。初期化子のないフィールドは `undefined` に初期化されます。プロパティと同様に、フィールド名は計算することができます。

```js
const PREFIX = "prefix";

class ClassWithField {
  field;
  fieldWithInitializer = "instance field";
  [`${PREFIX}Field`] = "prefixed field";
}

const instance = new ClassWithField();
console.log(Object.hasOwn(instance, "field")); // true
console.log(instance.field); // undefined
console.log(instance.fieldWithInitializer); // "instance field"
console.log(instance.prefixField); // "prefixed field"
```

計算されたフィールド名は、クラス定義時点で一度だけ評価されます。これは、クラスごとに常に固定された一連のフィールド名を持つことを意味しており、2つのインスタンスが計算された名前によって異なるフィールド名を持つことはありません。計算式の `this` 値はクラス定義を囲む `this` であり、クラス名を参照することは `ReferenceError` となります。この式では `await` と `yield` は期待通りに動作します。

```js
class C {
  [Math.random()] = 1;
}

console.log(new C());
console.log(new C());
// Both instances have the same field name
```

フィールド初期化子の中では、`this`は作成中のクラスインスタンスを参照し、`super`は基底クラスの `prototype` プロパティを参照します。このプロパティには基底クラスのインスタンスメソッドが格納されていますが、インスタンスフィールドは格納されていません。

```js
class Base {
  baseField = "base field";
  anotherBaseField = this.baseField;
  baseMethod() {
    return "base method output";
  }
}

class Derived extends Base {
  subField = super.baseMethod();
}

const base = new Base();
const sub = new Derived();

console.log(base.anotherBaseField); // "base field"

console.log(sub.subField); // "base method output"
```

フィールドの初期化式は、新しいインスタンスが作成されるたびに評価されます。（`this` の値はインスタンスごとに異なるので、初期化式はインスタンス固有のプロパティにアクセスすることができます。）

```js
class C {
  obj = {};
}

const instance1 = new C();
const instance2 = new C();
console.log(instance1.obj === instance2.obj); // false
```

式は同期的に評価されます。初期化式で `await` や `yield` を使用することはできません。（初期化式は暗黙的に関数に包まれていると考えてください。）

クラスのインスタンスフィールドは、それぞれのコンストラクターが実行される前に追加されるので、コンストラクター内でフィールドの値にアクセスすることができます。しかし、派生クラスのインスタンスフィールドは `super()` を返した後に定義されるので、基底クラスのコンストラクターが派生クラスのフィールドにアクセスすることはできません。

```js
class Base {
  constructor() {
    console.log("Base constructor:", this.field);
  }
}

class Derived extends Base {
  field = 1;
  constructor() {
    super();
    console.log("Derived constructor:", this.field);
    this.field = 2;
  }
}

const instance = new Derived();
// Base constructor: undefined
// Derived constructor: 1
console.log(instance.field); // 2
```

フィールドは 1 つずつ追加されます。フィールド初期化子はその上のフィールドの値を参照することはできますが、その下のフィールドの値を参照することはできません。インスタンスメソッドと静的メソッドはすべて事前に追加され、アクセスすることができますが、初期化されているフィールドより下のフィールドを参照している場合、呼び出すと期待した動作をしないことがあります。

```js
class C {
  a = 1;
  b = this.c;
  c = this.a + 1;
  d = this.c + 1;
}

const instance = new C();
console.log(instance.d); // 3
console.log(instance.b); // undefined
```

**メモ:** これはプライベートフィールドではより重要です。初期化されていないプライベートフィールドにアクセスすると、たとえプライベートフィールドが下記で宣言されていても `TypeError` が発生するからです。（プライベートフィールドが宣言されていない場合は、早期に `SyntaxError` となります。）

クラスフィールドは `[[DefineOwnProperty]]` の意味づけ（本質的には `Object.defineProperty()`）を使用して追加されるため、派生クラスのフィールド宣言は基底クラスのセッターを呼び出すことはありません。この動作は、コンストラクターで `this.field = …` を使用するのとは異なります。

```js
class Base {
  set field(val) {
    console.log(val);
  }
}

class DerivedWithField extends Base {
  field = 1;
}

const instance = new DerivedWithField(); // No log

class DerivedWithConstructor extends Base {
  constructor() {
    super();
    this.field = 1;
  }
}

const instance2 = new DerivedWithConstructor(); // Logs 1
```

**メモ:** クラスフィールドの仕様が最終的に `[[DefineOwnProperty]]` の意味づけで決定される以前は、 Babel や tsc を含むほとんどのトランスパイラーはクラスフィールドを `DerivedWithConstructor` 形式に変換しており、クラスフィールドが標準化された後に微妙なバグが発生していました。

例
-

### クラスフィールドの使用

クラスフィールドはコンストラクターの引数に依存できないので、フィールド初期化子は通常、インスタンスごとに同じ値として評価されます（`Date.now()` やオブジェクト初期化子のように、同じ式が時刻ごとに異なる値として評価できる場合を除きます）。

```js
class Person {
  name = nameArg; // nameArg はコンストラクターのスコープ外
  constructor(nameArg) {}
}
```

```js
class Person {
  // すべてのインスタンスが同じ名前になる
  name = "Dragomir";
}
```

しかし、空であってもクラスフィールドを宣言することは有益です。フィールドの存在を示すことで、人間の読者だけでなく型チェッカーもクラスの形状を静的に分析できるようになるからです。

```js
class Person {
  name;
  age;
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
}
```

上のコードは冗長なように見えますが、 `this` が動的に変更される場合を考えてみましょう。明示的にフィールド宣言を行うと、インスタンスに必ず存在するフィールドが明確になります。

```js
class Person {
  name;
  age;
  constructor(properties) {
    Object.assign(this, properties);
  }
}
```

初期化子は基底クラスが実行された後に評価されるので、基底クラスのコンストラクターで作成したプロパティにアクセスすることができます。

```js
class Person {
  name;
  age;
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
}

class Professor extends Person {
  name = `Professor ${this.name}`;
}

console.log(new Professor("Radev", 54).name); // "Professor Radev"
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # prod-FieldDefinition |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* クラスの使用ガイド
* クラス
* プライベートプロパティ
* `class`
* The semantics of all JS class elements (Shu-yu Guo, 2018)
* Public and private class fields (v8.dev, 2018)


静的初期化ブロック - JavaScript

静的初期化ブロック
=========

**静的初期化ブロック**はクラス内で宣言されます。これは、クラスの初期化の時に評価される文を格納します。これにより、静的プロパティよりも柔軟な初期化ロジックが可能になり、 `try...catch` を使用したり、 1 つの値から複数のフィールドを設定したりすることができます。初期化は現在のクラス宣言のコンテキストで実行され、プライベートプロパティにアクセスすることができます。つまり、インスタンスのプライベートフィールドを持つクラスと、同じスコープで宣言された他のクラスや関数との間で情報を共有するためにも使用できます（C++ の "friend" クラスに似ています）。

試してみましょう
--------

構文
--

```js
class ClassWithSIB {
  static {
    // …
  }
}
```

解説
--

静的初期化ブロックを使わない場合、クラス宣言の後で静的メソッドを呼び出すことで、複雑な静的初期化を行うことができます。

```js
class MyClass {
  static init() {
    // プライベート静的フィールドにアクセスすることができる
  }
}

MyClass.init();
```

しかし、この手法では実装の詳細（`init()` メソッド）がクラスのユーザーに公開されてしまいます。一方、クラスの外部で宣言された初期化ロジックはプライベート静的フィールドにアクセスすることはできません。静的初期化ブロックでは、任意の初期化ロジックをクラス内で宣言し、クラスの評価中に実行することができます。

`class` は、そのクラス本体に任意の数の `static {}` 初期化ブロックを置くことができます。
 これらのブロックは、宣言された順に、静的フィールド初期化子とともに評価されます。
 スーパークラスの静的初期化は、そのサブクラスの初期化よりも先に実行されます。

静的ブロックの内部で宣言された変数のスコープは、そのブロックのローカルなものです。ここには初期化ブロック内で宣言された `var`, `function`, `const`, `let` は、そのブロックのローカル変数であるため、ブロック内の `var` 宣言は巻き上げされることはありません。

```js
var y = "Outer y";

class A {
  static field = "Inner y";
  static {
    var y = this.field;
  }
}

// 静的ブロックで定義された var は巻き上げられない
console.log(y); // 'Outer y'
```

 静的ブロック内の `this` は、そのクラスのコンストラクター オブジェクトを参照します。
 `super.プロパティ` を使用して、スーパークラスの静的プロパティにアクセスすることができます。
 ただし、クラスの静的初期化ブロック内で `super()` を呼び出したり、 `arguments` オブジェクトを使用したりするのは構文エラーであることに注意してください。

式は同期的に評価されます。初期化子式で（`await` や `yield`）を使用することはできません。（初期化子式は暗黙に関数に包まれていると考えてください）。

静的ブロックのスコープは、クラス本体の字句スコープの中で入れ子になり、構文エラーを発生させることなく、クラス内で宣言されたプライベート名にアクセスすることができます。

静的フィールド初期化子と静的初期化ブロックは、 1 つずつ評価されます。フィールド初期化子は、それより上のフィールド値を参照することはできますが、それより下のフィールド値を参照することはできません。静的メソッドはすべて事前に追加され、アクセスすることができますが、初期化されるフィールドより下のフィールドを参照している場合、呼び出すと期待した動作をしないことがあります。

**メモ:** これはプライベート静的フィールドではより重要です。初期化されていないプライベートフィールドにアクセスすると、たとえそのプライベートフィールドが下で宣言されていたとしても、 `TypeError` が発生するからです。（プライベートフィールドが宣言されていない場合は、早期に `SyntaxError` となります。）

静的初期化ブロックはデコレーターを持つことができません（クラス自身は持つことができます）。

例
-

### 複数のブロック

 下記コードは、静的初期化ブロックと静的フィールド初期化子を挟み込んだクラスを示すものです。
 出力は、ブロックとフィールドが実行順に評価されることを示しています。

```js
class MyClass {
  static field1 = console.log("static field1");
  static {
    console.log("static block1");
  }
  static field2 = console.log("static field2");
  static {
    console.log("static block2");
  }
}
// 'static field1'
// 'static block1'
// 'static field2'
// 'static block2'
```

スーパークラスの静的な初期化は、サブクラスの初期化よりも最初に行われることに注意してください。

### this と super の使用

 静的ブロック内の `this` は、そのクラスのコンストラクター オブジェクトを参照します。
 このコードは、パブリック静的フィールドにアクセスする方法を示しています。

```js
class A {
  static field = "static field";
  static {
    console.log(this.field);
  }
}
// 'static field'
```

`super.property` 構文を `static` ブロックの中で使用すると、スーパークラスの静的プロパティを参照することができます。

```js
class A {
  static field = "static field";
}

class B extends A {
  static {
    console.log(super.field);
  }
}
// 'static field'
```

### プライベートプロパティへのアクセス

下記は、クラス外のオブジェクトからクラスのプライベートインスタンスフィールドにアクセスを許可する例です（v8.dev blogより）。

```js
let getDPrivateField;

class D {
  #privateField;
  constructor(v) {
    this.#privateField = v;
  }
  static {
    getDPrivateField = (d) => d.#privateField;
  }
}

console.log(getDPrivateField(new D("private"))); // 'private'
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # prod-ClassStaticBlock |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* クラスの使用ガイド
* クラス
* `static`
* `class`
* Class static initialization blocks (v8.dev blog)
* ES2022 feature: class static initialization blocks (Dr. Axel Rauschmayer, 2021)


extends - JavaScript

extends
=======

Baseline Widely available
-------------------------

This feature is well established and works across many devices and browser versions. It’s been available across browsers since March 2017.

* Learn more
* See full compatibility
* Report feedback
**`extends`** キーワードは、クラス宣言やクラス式の中で、他のクラスの子であるクラスを生成するために使用します。

試してみましょう
--------

構文
--

```js
class ChildClass extends ParentClass { /\* … \*/ }
```

`ParentClass`

コンストラクター関数（クラスを含む）または `null` と評価される式。

解説
--

`extends` キーワードは、組み込みオブジェクトと同様にカスタムクラスをサブクラス化するために使用することができます。

`new` で呼び出すことができ、 `prototype` プロパティを持つコンストラクターであれば、親クラスの候補になることができます。例えば、バインド済み関数や `Proxy` は構築可能ですが、これらは `prototype` プロパティを持たないので、サブクラス化できません。

```js
function OldStyleClass() {
  this.someProperty = 1;
}
OldStyleClass.prototype.someMethod = function () {};

class ChildClass extends OldStyleClass {}

class ModernClass {
  someProperty = 1;
  someMethod() {}
}

class AnotherChildClass extends ModernClass {}
```

`ParentClass`の `prototype` プロパティは `Object` または `null` でなければなりませんが、オブジェクトでない `prototype` は本来の動作をしないので、実際にはほとんど気にすることはないでしょう。（`new` 演算子では無視されます。）

```js
function ParentClass() {}
ParentClass.prototype = 3;

class ChildClass extends ParentClass {}
// Uncaught TypeError: Class extends value does not have valid prototype property 3

console.log(Object.getPrototypeOf(new ParentClass()));
// [Object: null prototype] {}
// Not actually a number!
```

`extends` は `ChildClass` と `ChildClass.prototype` の両方のプロトタイプを設定します。

|  | `ChildClass` のプロトタイプ | `ChildClass.prototype` のプロトタイプ |
| --- | --- | --- |
| `extends` 節がない | `Function.prototype` | `Object.prototype` |
| `extends null` | `Function.prototype` | `null` |
| `extends ParentClass` | `ParentClass` | `ParentClass.prototype` |

```js
class ParentClass {}
class ChildClass extends ParentClass {}

// 静的プロパティの継承が可能
Object.getPrototypeOf(ChildClass) === ParentClass;
// インスタンスプロパティの継承が可能
Object.getPrototypeOf(ChildClass.prototype) === ParentClass.prototype;
```

`extends` の右辺は識別子である必要はありません。コンストラクターとして評価される式なら何でも使用することができます。これはミックスインを作成するのに有益なことが多いです。 `extends` 式の `this` 値はクラス定義の外側の `this` であり、このクラスは初期化されていないので、クラス名を参照すると `ReferenceError` になります。この式では `await` および `yield` は期待通りに動作します。

```js
class SomeClass extends class {
  constructor() {
    console.log("基底クラス");
  }
} {
  constructor() {
    super();
    console.log("派生クラス");
  }
}

new SomeClass();
// 基底クラス
// 派生クラス
```

基底クラスはコンストラクターから何らかのものを返すことができますが、派生クラスはオブジェクトを返すか `undefined` を返さなければなりません。

```js
class ParentClass {
  constructor() {
    return 1;
  }
}

console.log(new ParentClass()); // ParentClass {}
// オブジェクトではないため、返値は無視される
// これは関数コンストラクターと整合する

class ChildClass extends ParentClass {
  constructor() {
    super();
    return 1;
  }
}

console.log(new ChildClass()); // TypeError: Derived constructors may only return object or undefined
```

親クラスのコンストラクターがオブジェクトを返す場合、クラスフィールドをさらに初期化するときに、そのオブジェクトが派生クラスの `this` 値として使用されます。このトリックは「返値の上書き」と呼ばれ、派生クラスのフィールド（プライベートフィールドを含む）を無関係なオブジェクトに定義することができます。

### 組み込みクラスのサブクラス化

**警告:** 標準化委員会は、これまでの仕様にあった組み込みクラスにおけるサブクラス化メカニズムは過剰に設計されており、パフォーマンスとセキュリティへの無視できない影響を発生させているという見解を固めました。新しい組み込みメソッドはサブクラスについてあまり考慮されておらず、エンジンの実装者は一部のサブクラス化メカニズムを除去するかどうか調査しています。組み込みクラスを拡張する際には、継承の代わりにコンポジションを使用することを検討してください。

クラスを拡張する際に期待されることをいくつか示します。

* 静的ファクトリーメソッド（`Promise.resolve()` や `Array.from()`）をサブクラスで呼び出した場合、返されるインスタンスが常にサブクラスのインスタンスになること。
* 新しいインスタンスを返すインスタンスメソッド（`Promise.prototype.then()` や `Array.prototype.map()` など）をサブクラスで呼び出した場合、返されるインスタンスは常にサブクラスのインスタンスになること。
* インスタンスメソッドの移譲先は、可能な限り最小限の基本的なメソッドの集合になること。例えば、 `Promise` のサブクラスの場合、 `then()` をオーバーライドすると、自動的に `catch()` の動作が変化すること。または、 `Map` のサブクラスの場合、 `set()` をオーバーライドすると、 `Map()` コンストラクターの動作が自動的に変更さえること。

しかし、上記のような期待を適切に実装するには、只ならぬ努力が必要です。

* まず、返されるインスタンスを構築するコンストラクターを取得するために、静的メソッドで `this` の値を読み取ることが要求されることです。これは `[p1, p2, p3].map(Promise.resolve)` が `Promise.resolve` 内の `this` が未定義であるためにエラーを発生することになります。これを修正する方法としては、 `Array.from()` がそうであるように、 `this` がコンストラクターでない場合に基底クラスで代替処理をすることですが、それでも基底クラスが特殊ケースであることを意味しています。
* 2 つ目は、インスタンスメソッドがコンストラクター関数を取得するために `this.constructor` を読み込むことを要求されることです。しかし、コンストラクターのプロパティは書き込みと設定の両方が可能であり、保護されていないため、 `new this.constructor()` は古いコードを壊す可能性があります。そのため、組み込みメソッドをコピーする場合の多くは、代わりにコンストラクターの `@@species` プロパティを使用しています（既定では、単にコンストラクター自身である `this` を返します）。しかし、 `@@species` によって任意のコードを実行したり、任意のタイプのインスタンスを作成したりすることができるため、セキュリティ上の問題があり、サブクラスの意味づけが非常に複雑になります。
* 3 つ目はカスタムコードを目に見える形で呼び出すことになり、多くのオプティマイザーの実装が難しくなります。例えば、 `Map()` コンストラクターが *x* 要素の反復可能オブジェクトで呼び出された場合、内部ストレージに要素をコピーするだけではなく、目に見える形で `set()` メソッドを *x* 回呼び出さなければなりません。

これらの問題は組み込みクラスに固有のものではありません。自分自身で作成したクラスについても、同じような決定をしなければならないことがあるでしょう。しかし、組み込みクラスでは、最適化とセキュリティがより大きな関心事です。新しい組み込みメソッドは常に基底クラスを構築し、可能な限りいくつかのカスタムメソッドを呼び出します。上記の期待値を達成しながら組み込みクラスをサブクラス化したい場合は、既定値の動作が組み込まれているメソッドをすべてオーバーライドする必要があります。既定では継承されているため、基底クラスに新しいメソッドを追加すると、サブクラスの意味づけが崩れる可能性があります。したがって、組み込みクラスを拡張するためのより良い方法は、*コンポジション* を使用することです。

### null を拡張

`extends null` は、`Object.prototype` を継承しないオブジェクトを簡単に作成できるようにするために設計されました。しかし、コンストラクター内で `super()` を呼び出すべきかどうかが未確定なため、オブジェクトを返さないコンストラクターの実装を使用して、実際にそのようなクラスを構築することは可能ではありません。 TC39 委員会はこの機能を再び使えるようにするために作業しています。

```js
new (class extends null {})();
// TypeError: Super constructor null of anonymous class is not a constructor

new (class extends null {
  constructor() {}
})();
// ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor

new (class extends null {
  constructor() {
    super();
  }
})();
// TypeError: Super constructor null of anonymous class is not a constructor
```

代わりに、コンストラクターから明示的にインスタンスを返す必要があります。

```js
class NullClass extends null {
  constructor() {
    // new.target を使用することで、派生クラスが正しいプロトタイプチェーンを
    // 持つことができる
    return Object.create(new.target.prototype);
  }
}

const proto = Object.getPrototypeOf;
console.log(proto(proto(new NullClass()))); // null
```

例
-

### extends の使用

最初の例では、 `Square` と呼ばれるクラスを `Polygon` と呼ばれるクラスから作成します。この例は、ライブデモ（ソース）から転載しています。

```js
class Square extends Polygon {
  constructor(length) {
    // ここでは、親クラスのコンストラクターを呼び出し、
    // Polygon の幅と高さの寸法を渡します。
    super(length, length);
    // 注: 派生クラスでは、 'this' を使う前に super() を
    // 呼び出さなくてはなりません。さもないと参照エラーになります。
    this.name = "Square";
  }

  get area() {
    return this.height \* this.width;
  }
}
```

### プレーンなオブジェクトの拡張

クラスは通常の（構築不可能な）オブジェクトを継承することはできません。このオブジェクトのすべてのプロパティを継承したインスタンスで利用できるようにして、通常のオブジェクトを継承したい場合は、代わりに `Object.setPrototypeOf()` を使用することができます。

```js
const Animal = {
  speak() {
    console.log(`${this.name}が鳴きます。`);
  },
};

class Dog {
  constructor(name) {
    this.name = name;
  }
}

Object.setPrototypeOf(Dog.prototype, Animal);

const d = new Dog("ミッチー");
d.speak(); // ミッチーが鳴きます。
```

### 組み込みオブジェクトでの extends の使用

この例では、組み込みの `Date` オブジェクトを拡張します。この例は、ライブデモ (ソース) から転載しています。

```js
class MyDate extends Date {
  getFormattedDate() {
    const months = [
      "Jan", "Feb", "Mar", "Apr", "May", "Jun",
      "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
    ];
    return `${this.getDate()}-${months[this.getMonth()]}-${this.getFullYear()}`;
  }
}
```

### `Object` の拡張

JavaScript のオブジェクトはすべて既定では `Object.prototype` を継承しているので、一見すると `extends Object` と書くのは冗長に見えます。 `extends` をまったく書かない場合と異なる形で言えば、コンストラクター自体が `Object.keys()` のような静的メソッドを `Object` から継承していることくらいです。しかし、どの `Object` の静的メソッドも `this` の値を使用していないため、これらの静的メソッドを継承することに有益な値はありません。

`Object()` コンストラクターはサブクラスのシナリオを特殊化します。 `super()` によって暗黙的に呼び出された場合、常に `new.target.prototype` をプロトタイプとする新しいオブジェクトを初期化します。 `super()` に渡す値は無視されます。

```js
class C extends Object {
  constructor(v) {
    super(v);
  }
}

console.log(new C(1) instanceof Number); // false
console.log(C.keys({ a: 1, b: 2 })); // [ 'a', 'b' ]
```

この動作を、サブクラスを特殊化しないカスタムラッパーと比較してみてください。

```js
function MyObject(v) {
  return new Object(v);
}
class D extends MyObject {
  constructor(v) {
    super(v);
  }
}
console.log(new D(1) instanceof Number); // true
```

### species

派生配列クラス `MyArray` で `Array` オブジェクトを返したい場合もあります。 species パターンを使うと、既定のコンストラクターを上書きすることができます。

例えば、`Array.prototype.map()` のような既定のコンストラクターを返すメソッドを使用する場合、これらのメソッドは `MyArray` オブジェクトの代わりに、親の `Array` オブジェクトを返すようにします。シンボル `Symbol.species` を使用すると、これを行うことができます。

```js
class MyArray extends Array {
  // 親の Array コンストラクターの species を上書き
  static get [Symbol.species]() {
    return Array;
  }
}

const a = new MyArray(1, 2, 3);
const mapped = a.map((x) => x \* x);

console.log(mapped instanceof MyArray); // false
console.log(mapped instanceof Array); // true
```

この動作は、多くの組み込みコピーメソッドで実装されています。この機能の注意点については、組み込みクラスのサブクラス化の説明を参照してください。

### ミックスイン

抽象サブクラスまたはミックスインは、クラスのテンプレートです。クラスはスーパークラスを 1 つしか持つことができないので、例えばツールクラスからの多重継承は不可能です。機能はスーパークラスが提供しなければなりません。

スーパークラスを入力とし、そのスーパークラスを拡張したサブクラスを出力とする関数が、ミックスインを実装するために使用することができます。

```js
const calculatorMixin = (Base) =>
  class extends Base {
    calc() {}
  };

const randomizerMixin = (Base) =>
  class extends Base {
    randomize() {}
  };
```

これらのミックスインを使用するクラスは、次のように書くことができます。

```js
class Foo {}
class Bar extends calculatorMixin(randomizerMixin(Foo)) {}
```

### 継承を避ける

オブジェクト指向プログラミングにおいて、継承はとても強い結合関係です。これは基底クラスのすべての振る舞いが既定でサブクラスに継承されることを意味します。例えば、 `ReadOnlyMap` の実装を考えてみましょう。

```js
class ReadOnlyMap extends Map {
  set() {
    throw new TypeError("A read-only map must be set at construction time.");
  }
}
```

`Map()` コンストラクターはインスタンスの `set()` メソッドを呼び出すからです。

```js
const m = new ReadOnlyMap([["a", 1]]); // TypeError: A read-only map must be set at construction time.
```

インスタンスが構築済みかどうかを示すためにプライベートなフラグを使用することで、これを回避することができます。しかし、この設計のより重大な問題は、リスコフの置換原則を破ってしまうことです。これは、サブクラスはスーパークラスと置換可能であるべきだという状態です。もし関数が `Map` オブジェクトを期待するのであれば、 `ReadOnlyMap` オブジェクトも使用することができるはずです。

継承はしばしば円-楕円問題を引き起こします。なぜなら、どちらの型も、多くの共通の特徴を共有しているにもかかわらず、他の型の振る舞いを完全に内包していないからです。一般的に、継承を使用するとてもよい理由がない限り、代わりにコンポジションを使用する方がよいでしょう。コンポジションとは、あるクラスが他のクラスのオブジェクトへの参照を持っていて、そのオブジェクトを実装の詳細としてのみ使用していることを意味しています。

```js
class ReadOnlyMap {
  #data;
  constructor(values) {
    this.#data = new Map(values);
  }
  get(key) {
    return this.#data.get(key);
  }
  has(key) {
    return this.#data.has(key);
  }
  get size() {
    return this.#data.size;
  }
  \*keys() {
    yield\* this.#data.keys();
  }
  \*values() {
    yield\* this.#data.values();
  }
  \*entries() {
    yield\* this.#data.entries();
  }
  \*[Symbol.iterator]() {
    yield\* this.#data[Symbol.iterator]();
  }
}
```

この場合、 `ReadOnlyMap` クラスは `Map` のサブクラスではありませんが、同じメソッドを実装しています。これはコードの重複を意味しますが、 `ReadOnlyMap` クラスは `Map` クラスと強く割り当てられているわけではなく、 `Map` クラスが変更されても簡単に壊れることはありません。例えば、 `Map` クラスが `set()` を呼び出さない `emplace()` メソッドを追加した場合、後者が `emplace()` もオーバーライドするように更新されない限り、 `ReadOnlyMap` クラスは読み取り専用ではなくなります。さらに、`ReadOnlyMap` オブジェクトは `set` メソッドをすべて持たないので、実行時にエラーを発生するよりも正確です。

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-class-definitions |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* クラスの使用ガイド
* クラス
* `constructor`
* `class`
* `super`


static - JavaScript

static
======

Baseline Widely available
-------------------------

This feature is well established and works across many devices and browser versions. It’s been available across browsers since March 2017.

* Learn more
* See full compatibility
* Report feedback
**`static`** キーワードは、クラスに静的メソッドや静的プロパティを定義します。静的メソッドも静的プロパティもクラスのインスタンスからは呼び出されません。その代わりに、クラスそのものから呼び出されます。静的メソッドは多くの場合、オブジェクトの生成や複製を行う関数などのユーティリティ関数です。静的プロパティはキャッシュ、固定的な構成、その他の各インスタンスに複製する必要のないデータです。

静的メソッドは多くの場合、オブジェクトの生成や複製を行う関数などのユーティリティ関数です。静的プロパティはキャッシュ、固定的な構成、その他の各インスタンスに複製する必要のないデータです。

**メモ:** クラスの文脈において、 MDN Web Docs のコンテンツではプロパティとフィールドという用語を同等のものとして使用しています。

試してみましょう
--------

構文
--

```js
class ClassWithStatic {
  static staticField;
  static staticFieldWithInitializer = value;
  static staticMethod() {
    // …
  }
}
```

それ以外にも構文上の制約があります。

* 静的プロパティ（フィールドまたはメソッド）の名前を `prototype` とすることはできません。
* クラスフィールド（静的またはインスタンス）の名前を `constructor` とすることはできません。
解説
--

このページでは、静的メソッド、静的アクセサ、静的フィールドを含む、クラスのパブリック静的プロパティを紹介します。

* プライベートな静的機能については、プライベートプロパティを参照してください。
* インスタンスの機能については、メソッド定義、ゲッター、セッター、パブリッククラスフィールドを参照してください。

パブリック静的機能は、`static` キーワードを使用して宣言します。これらはクラス評価時に、 `[[DefineOwnProperty]]` の意味づけ（これは本質的に `Object.defineProperty()` です）を使用して、クラスのコンストラクターに追加されます。これらは、コンストラクターから再びアクセスします。

静的メソッドの多くは、インスタンスを作成したり複製したりするなどの、ユーティリティ関数です。パブリック静的フィールドは、作成するすべてのクラスインスタンスではなく、クラスごとに一つだけフィールドを存在させたい場合に有益です。これは、キャッシュや固定の構成値、 あるいはインスタンスをまたがって複製する必要のないデータなどに有益です。

静的フィールド名は計算できます。計算式の `this` 値はクラス定義の周囲の `this` であり、クラス名を参照すると、クラスがまだ初期化されていないため `ReferenceError` になります。この式では `await` と `yield` は期待どおりに動作します。

静的フィールドは初期化子を持つことができます。初期化子を持たない静的フィールドは `undefined` に初期化されます。パブリック静的フィールドはサブクラスでは再初期化されませんが、プロトタイプチェーン経由でアクセスすることができます。

```js
class ClassWithStaticField {
  static staticField;
  static staticFieldWithInitializer = "静的フィールド";
}

class SubclassWithStaticField extends ClassWithStaticField {
  static subStaticField = "サブクラスのフィールド";
}

console.log(Object.hasOwn(ClassWithStaticField, "staticField")); // true
console.log(ClassWithStaticField.staticField); // undefined
console.log(ClassWithStaticField.staticFieldWithInitializer); // "静的フィールド"
console.log(SubclassWithStaticField.staticFieldWithInitializer); // "静的フィールド"
console.log(SubclassWithStaticField.subStaticField); // "サブクラスのフィールド"
```

フィールド初期化子では、 `this` は現在のクラス（その名前からもアクセスすることができます）を参照し、 `super` は基底クラスのコンストラクターを参照します。

```js
class ClassWithStaticField {
  static baseStaticField = "基底クラスの静的フィールド";
  static anotherBaseStaticField = this.baseStaticField;

  static baseStaticMethod() {
    return "基底クラスの静的フィールドの出力";
  }
}

class SubClassWithStaticField extends ClassWithStaticField {
  static subStaticField = super.baseStaticMethod();
}

console.log(ClassWithStaticField.anotherBaseStaticField); // "基底クラスの静的フィールド"
console.log(SubClassWithStaticField.subStaticField); // "基底クラスの静的フィールドの"
```

式は同期的に評価されます。初期化子式で（`await` や `yield`）を使用することはできません。（初期化子式は暗黙に関数に包まれていると考えてください）。

静的フィールド初期化子と静的初期化ブロックは、 1 つずつ評価されます。フィールド初期化子は、それより上のフィールド値を参照することはできますが、それより下のフィールド値を参照することはできません。静的メソッドはすべて事前に追加され、アクセスすることができますが、初期化されるフィールドより下のフィールドを参照している場合、呼び出すと期待した動作をしないことがあります。

**メモ:** これはプライベート静的フィールドではより重要です。初期化されていないプライベートフィールドにアクセスすると、たとえそのプライベートフィールドが下で宣言されていたとしても、 `TypeError` が発生するからです。（プライベートフィールドが宣言されていない場合は、早期に `SyntaxError` となります。）

例
-

### クラスでの静的メンバーの使用

次の例はいくつかのことを説明しています。

1. 静的メンバー（メソッドまたはプロパティ）がクラスでどのように定義されるか
2. 静的メンバーを持つクラスがサブクラスを作れるか
3. 静的メンバーがどう呼び出せて、どう呼び出せないか

```js
class Triple {
  static customName = "Tripler";
  static description = "I triple any number you provide";
  static calculate(n = 1) {
    return n \* 3;
  }
}

class SquaredTriple extends Triple {
  static longDescription;
  static description = "I square the triple of any number you provide";
  static calculate(n) {
    return super.calculate(n) \* super.calculate(n);
  }
}

console.log(Triple.description); // 'I triple any number you provide'
console.log(Triple.calculate()); // 3
console.log(Triple.calculate(6)); // 18

const tp = new Triple();

console.log(SquaredTriple.calculate(3)); // 81 (not affected by parent's instantiation)
console.log(SquaredTriple.description); // 'I square the triple of any number you provide'
console.log(SquaredTriple.longDescription); // undefined
console.log(SquaredTriple.customName); // 'Tripler'

// This throws because calculate() is a static member, not an instance member.
console.log(tp.calculate()); // 'tp.calculate is not a function'
```

### 静的メンバーの別な静的メソッドからの呼び出し

同じクラス内の静的メソッドまたはプロパティを静的メソッドから呼び出すには、 `this` キーワードを使います。

```js
class StaticMethodCall {
  static staticProperty = "static property";
  static staticMethod() {
    return "Static method and " + this.staticProperty + " has been called";
  }
  static anotherStaticMethod() {
    return this.staticMethod() + " from another static method";
  }
}
StaticMethodCall.staticMethod();
// 'Static method and static property has been called'

StaticMethodCall.anotherStaticMethod();
// 'Static method and static property has been called from another static method'
```

### クラスのコンストラクターや他のメソッドからの静的メソッドの呼び出し

静的メソッドは静的ではないメソッドの `this` キーワードを使用して直接アクセスすることができません。呼び出すにはクラス名を使用して `クラス名.静的メソッド名()` / `クラス名.静的プロパティ名` のようにするか、 `constructor` プロパティのメソッドとして `this.constructor.静的メソッド名()` / `this.constructor.静的プロパティ名` のようにしてください。

```js
class StaticMethodCall {
  constructor() {
    console.log(StaticMethodCall.staticProperty); // 'static property'
    console.log(this.constructor.staticProperty); // 'static property'
    console.log(StaticMethodCall.staticMethod()); // 'static method has been called.'
    console.log(this.constructor.staticMethod()); // 'static method has been called.'
  }

  static staticProperty = "static property";
  static staticMethod() {
    return "static method has been called.";
  }
}
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-class-definitions |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* `class` 式
* `class` 宣言
* クラス


右シフト代入 (>>=) - JavaScript

右シフト代入 (>>=)
============

右シフト代入演算子 (`>>=`) は、指定された数だけビットを右に移動し、結果を変数に代入します。

試してみましょう
--------

構文
--

```js
x >>= y; // x = x >> y
```

例
-

### 右シフト代入の使用

```js
let a = 5; // (00000000000000000000000000000101)
a >>= 2; // 1 (00000000000000000000000000000001)

let b = -5; // (-00000000000000000000000000000101)
b >>= 2; // -2 (-00000000000000000000000000000010)
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-assignment-operators |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* JavaScript ガイドの代入演算子
* 右シフト演算子


減算代入 (-=) - JavaScript

減算代入 (-=)
=========

減算代入演算子 (`-=`) は、変数から右辺のオペランドの値を減算し、結果を変数に代入します。

試してみましょう
--------

構文
--

```js
x -= y; // x = x - y
```

例
-

### 減算代入の使用

```js
// 次の変数を想定
// bar = 5

bar -= 2; // 3
bar -= "foo"; // NaN
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-assignment-operators |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* JavaScript ガイドの代入演算子
* 減算演算子


グループ化演算子 ( ) - JavaScript

グループ化演算子 ( )
============

グループ化演算子 `( )` は、式での評価の優先順位を制御します。

試してみましょう
--------

構文
--

```js
( )
```

解説
--

グループ化演算子は、式または部分式の周りに括弧のペアで構成され、通常の演算子の優先順位を上書きし、より低い優先順位の式をより高い優先順位の式の前に評価できるようにします。その名の通り、括弧の中にあるものをグループ化します。

例
-

### グループ化演算子の使用

最初に乗算と除算をし、次に加算と引き算をする優先順位を、最初に加算を評価するように上書きします。

```js
var a = 1;
var b = 2;
var c = 3;

// default precedence
a + b \* c; // 7
// evaluated by default like this
a + (b \* c); // 7

// now overriding precedence
// addition before multiplication
(a + b) \* c; // 9

// which is equivalent to
a \* c + b \* c; // 9
```

 これらの例では、評価の左から右への順序が維持されていることに注意してください。つまり、*演算子*の評価順序は変わっていますが、*オペランド*の評価順序は変わっていません。
 例えば次のコードを見てください。

```js
a() \* (b() + c());
```

関数 `a` は関数 `b` よりも前に、また関数 `b` は関数 `c` よりも前に呼び出されます。

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-grouping-operator |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* 演算子の優先順位
* `delete`
* `typeof`


instanceof - JavaScript

instanceof
==========

**`instanceof` 演算子**は、あるコンストラクターの `prototype` プロパティが、あるオブジェクトのプロトタイプチェーンの中のどこかに現れるかどうかを検査します。返値は論理値です。

試してみましょう
--------

構文
--

```js
object instanceof constructor;
```

### 引数

`object`

検査するオブジェクトです。

`constructor`

検査対象の関数です。

解説
--

`instanceof` 演算子は、`object` のプロトタイプチェーンに `constructor.prototype` が存在することを検査します。

```js
// コンストラクターを定義
function C() {}
function D() {}

let o = new C();

// true : Object.getPrototypeOf(o) === C.prototype であるため
o instanceof C;

// false : D.prototype は o のプロトタイプチェーンのどこにも存在しないため
o instanceof D;

o instanceof Object; // true : なぜなら...
C.prototype instanceof Object; // true であるため

C.prototype = {};
let o2 = new C();

o2 instanceof C; // true

// false : C.prototype は o のプロトタイプチェーンの
// どこにも存在しないため
o instanceof C;

D.prototype = new C(); // 継承を使用
let o3 = new D();
o3 instanceof D; // true
o3 instanceof C; // true : o3 のプロトタイプチェーンに C.prototype があるため
```

なお、 `instanceof` の値の検査結果はコンストラクターの `prototype` プロパティが変化すると変わることがあります。また、オブジェクトのプロトタイプを `Object.setPrototypeOf` を用いて変更した場合や、標準外の `__proto__` プロパティを用いた場合も変わることがあります。

### `instanceof` と複数のコンテキスト (例: frame や window)

スコープが異なると、実行環境が変わります。つまり、組み込まれているものも変わります（別々なグローバルオブジェクト、別々なコンストラクター、など）。これにより予期せぬ結果になる場合があります。例えば、`[] instanceof window.frames[0].Array` は `false` を返します。 `Array.prototype !== window.frames[0].Array.prototype` であり、配列は前者を継承しているからです。

これは、始めはわかりにくいかもしれませんが、スクリプトで複数のフレームやウィンドウを扱い、オブジェクトをあるコンテキストから別のコンテキストへ関数を経由して渡すようになると、正当かつ重要な事項になります。例えば、`Array.isArray(myObj)` を使用すると、与えられたオブジェクトが実際に配列であるかどうかを安全にチェックできます。

例えば、別のコンテキストで Node が SVGElement であるかどうかをチェックするには、`myNode instanceof myNode.ownerDocument.defaultView.SVGElement` を使用してください。

例
-

### instanceof を String に対して使用

以下の例では、 `instanceof` を `String` オブジェクトに使用した場合の動作を示しています。

```js
let literalString = "これは文字列リテラルです";
let stringObject = new String("コンストラクターで作成された String です");

literalString instanceof String; // false : 文字列リテラルは String ではない
stringObject instanceof String; // true

literalString instanceof Object; // false : 文字列リテラルは Object ではない
stringObject instanceof Object; // true

stringObject instanceof Date; // false
```

### instanceof を Date に対して使用

以下の例では、 `instanceof` を `Date` オブジェクトに使用した場合の動作を示しています。

```js
let myDate = new Date();

myDate instanceof Date; // true
myDate instanceof Object; // true
myDate instanceof String; // false
```

### Object.create() で生成された Object

以下の例では、 `instanceof` を `Object.create()` で生成したオブジェクトに使用した場合の動作を示しています。

```js
function Shape() {}

function Rectangle() {
  Shape.call(this); // スーパークラスのコンストラクターを呼び出す。
}

Rectangle.prototype = Object.create(Shape.prototype);

Rectangle.prototype.constructor = Rectangle;

let rect = new Rectangle();

rect instanceof Object; // true
rect instanceof Shape; // true
rect instanceof Rectangle; // true
rect instanceof String; // false

let literalObject = {};
let nullObject = Object.create(null);
nullObject.name = "My object";

literalObject instanceof Object; // true : すべてのオブジェクトリテラルは Object.prototype をプロトタイプとして持つ
({}) instanceof Object; // true : 上記と同じ
nullObject instanceof Object; // false : プロトタイプはプロトタイプチェーンの末尾 (null)
```

### `mycar` が `Car` 型および `Object` 型であることを示す

以下のコードは、`Car` オブジェクト型とそのインスタンスである `mycar` を生成しています。`instanceof` 演算子で、`mycar` は `Car` 型および `Object` 型であることを示します。

```js
function Car(make, model, year) {
  this.make = make;
  this.model = model;
  this.year = year;
}
let mycar = new Car("Honda", "Accord", 1998);
let a = mycar instanceof Car; // true を返す
let b = mycar instanceof Object; // true を返す
```

### instanceof の否定

あるオブジェクトが特定のコンストラクターの `instanceof` でないことを検査するには、次のようにします。

```js
if (!(mycar instanceof Car)) {
  // 次のようなことをします。
  // mycar = new Car(mycar)
}
```

これは実際には次のものとは異なります。

```js
if (!mycar instanceof Car)
```

これは常に `false` になります。（`!mycar` は `instanceof` の前に評価されるため、常に論理値が `Car` のインスタンスであるかどうかを検査しようとします。）

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-relational-operators |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* `typeof`
* `Symbol.hasInstance`
* `Object.prototype.isPrototypeOf`


クラス式 - JavaScript

クラス式
====

**クラス式**は、 ECMAScript 2015 でクラスを定義する方法の 1 つです。関数式と同じように、クラス式は名前を付けることも付けないこともできます。名前を付けた場合、クラス名はクラス内部のみのローカルです。

JavaScript のクラスはプロトタイプベースの継承が使われます。

試してみましょう
--------

構文
--

```js
const MyClass = class [className] [extends otherClassName] {
  // クラス本体
}
```

解説
--

クラス式の構文は、クラス宣言（文） と似ています。 `class` 文では、 `class` 式の本体が厳格モードで実行されます。

しかし、クラス式とクラス文ではいくつかの相違点があります。

* クラス式ではクラス名（「束縛識別子」 (binding identifier)）を省略できますが、クラス文では省略できません。
* クラス式は `SyntaxError` を**発生させずに**クラスを再宣言することができます。これはクラス文の場合はできません。

`constructor` メソッドは省略可能です。クラス式で生成されたクラスは、常に `typeof` が "`function`" の値を返します。

```js
"use strict";
let Foo = class {}; // コンストラクタープロパティは省略可能
Foo = class {}; // 再宣言が可能

typeof Foo; // "function" を返す
typeof class {}; // "function" を返す

Foo instanceof Object; // true
Foo instanceof Function; // true
class Foo {} // SyntaxError が発生 (クラス宣言は再宣言ができない)
```

例
-

### 簡単なクラス式

以下は、名前のない簡単なクラス式です。変数 `Foo` を使って参照できます。

```js
const Foo = class {
  constructor() {}
  bar() {
    return "Hello World!";
  }
};

const instance = new Foo();
instance.bar(); // "Hello World!"
Foo.name; // "Foo"
```

### 名前付きクラス式

クラス内部で現在のクラスを参照したい場合は、*名前付きクラス式*を作成してください。この名前は、そのクラス式自身のスコープ内だけで見ることができます。

```js
const Foo = class NamedFoo {
  constructor() {}
  whoIsThere() {
    return NamedFoo.name;
  }
};
const bar = new Foo();
bar.whoIsThere(); // "NamedFoo"
NamedFoo.name; // ReferenceError: NamedFoo is not defined
Foo.name; // "NamedFoo"
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-class-definitions |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* 関数式
* クラス宣言
* クラス


in 演算子 - JavaScript

in 演算子
======

**`in` 演算子**は、指定されたプロパティが指定されたオブジェクトにある場合に `true` を返します。

試してみましょう
--------

構文
--

```js
prop in object;
```

### 引数

`prop`

プロパティ名または配列のインデックスを表す文字列式またはシンボルです（シンボルではない場合は、文字列に強制変換されます）。

`object`

オブジェクト（またはそのプロトタイプチェーン）に、指定された名前（`prop`）のプロパティが含まれているかどうかを確認するオブジェクト。

例
-

### 基本的な使い方

次の例で `in` 演算子の使用法を示します。

```js
// 配列
let trees = ["redwood", "bay", "cedar", "oak", "maple"];
0 in trees; // true を返す
3 in trees; // true を返す
6 in trees; // false を返す
"bay" in trees; // false を返す (添字の指す値ではなく、添字の数値を指定しなければならない)
"length" in trees; // true を返す (length は Array のプロパティ)
Symbol.iterator in trees; // true を返す (配列は反復可能。 ES2015 以上で動作する)

// 定義済みオブジェクト
"PI" in Math; // true を返す

// ユーザー定義オブジェクト
let mycar = { make: "Honda", model: "Accord", year: 1998 };
"make" in mycar; // true を返す
"model" in mycar; // true を返す
```

`in` 演算子の右側には、オブジェクトを指定しなければなりません。例えば、`String` コンストラクターで作成した文字列は指定できますが、文字列リテラルは指定できません。

```js
let color1 = new String("green");
"length" in color1; // true を返す

let color2 = "coral";
// エラーが発生 (color2 は String オブジェクトではない)
"length" in color2;
```

### 削除済みあるいは未定義状態のプロパティへの `in` の使用

`delete` 演算子で削除されたプロパティについては、`in` 演算子は `false` を返します。

```js
let mycar = { make: "Honda", model: "Accord", year: 1998 };
delete mycar.make;
"make" in mycar; // false を返す

let trees = new Array("redwood", "bay", "cedar", "oak", "maple");
delete trees[3];
3 in trees; // false を返す
```

`undefined` を設定しているが削除されていないプロパティについて、`in` 演算子は true を返します。

```js
let mycar = { make: "Honda", model: "Accord", year: 1998 };
mycar.make = undefined;
"make" in mycar; // true を返す
```

```js
let trees = new Array("redwood", "bay", "cedar", "oak", "maple");
trees[3] = undefined;
3 in trees; // true を返す
```

`in` 演算子は、空の配列スロットに対して `false` を返します。直接アクセスしても `undefined` が返されます。

```js
let empties = new Array(3);
empties[2]; // undefined を返す
2 in empties; // false を返す
```

これを避けるためには、新しい配列が常に空でない値で埋められるようにするか、配列の終わりを超える位置に書き込まないようにしてください。

```js
let empties = new Array(3).fill(undefined);
2 in empties; // true を返す
```

### 継承されたプロパティ

`in` 演算子は、プロトタイプチェーンのプロパティに対して `true` を返します。(*継承されていない*プロパティのみをチェックする場合は、代わりに `Object.prototype.hasOwnProperty()` を使用してください)。

```js
"toString" in {}; // true を返す
```

### プライベートフィールドとメソッド

`in` 演算子を使用して、特定のクラスのプライベートフィールドまたはメソッドがクラスで定義されているかどうかを調べることができます。そのメソッドが存在すれば演算子は `true` を返し、そうでなければ `false` を返します。

**メモ:** クラスの定義されていない*プライベート*フィールドやメソッドにアクセスしようとすると、コードで `throw` が発生します。存在しない可能性があるプライベートフィールドを `in` 演算子でチェックすると、 `try/catch` を使用するより簡潔にすることができます。

以下のコードは、指定されたクラスが特定のプライベートメソッドやフィールドを持っているかどうかをチェックする静的関数です。

```js
class ClassWithPrivateFeatures {
  #a;
  #b = null;
  #c() {}
  get #d() {}
  static f(o) {
    return #a in o && #b in o && #c in o && #d in o;
  }
}
ClassWithPrivateFeatures.f(new ClassWithPrivateFeatures()); // true を返す
ClassWithPrivateFeatures.f({}); // false を返す
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-relational-operators |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* `for...in`
* `delete`
* `Object.prototype.hasOwnProperty()`
* `Reflect.has()`
* プロパティの列挙可能性と所有権


ビット論理積 (&) - JavaScript

ビット論理積 (&)
==========

**ビット論理積 (`&`)** 演算子は、両方のオペランドの対応するビットのいずれもが `1` である位置のビットで `1` を返します。

試してみましょう
--------

構文
--

```js
x & y
```

解説
--

演算子 `&` は数値と長整数の 2 種類のオペランドに対してオーバーロードされています。数値の場合、演算子は 32 ビット整数を返します。長整数の場合、演算子は長整数を返します。まず、両方のオペランドを数値に変換 して、それらの型をテストします。両方のオペランドが長整数になった場合、長整数の AND を実行します。そうでない場合は、両方のオペランドを 32 ビット整数に変換し、ビット単位の AND を行います。一方のオペランドが長整数になり、もう一方が数値になると `TypeError` が発生します。

この演算子は、オペランドのビット表現を 2 の補数で演算します。最初のオペランドの各ビットは、2 番目のオペランドの対応するビットとペアになります。第 1 ビットと第 1 ビット、第 2 ビットと第 2 ビットといった具合です。演算子は各ビットのペアに適用され、結果はビットごとに構成されます。

AND演算の真理値表は以下の通りです。

| x | y | x AND y |
| --- | --- | --- |
| 0 | 0 | 0 |
| 0 | 1 | 0 |
| 1 | 0 | 0 |
| 1 | 1 | 1 |
```

     9 (10 進数) = 00000000000000000000000000001001 (2 進数)
    14 (10 進数) = 00000000000000000000000000001110 (2 進数)
                   --------------------------------
14 & 9 (10 進数) = 00000000000000000000000000001000 (2 進数) = 8 (10 進数)
```

32 ビットを超える数値は、最上位ビットが破棄されます。例えば、以下の 32 ビットを超える整数は 32 ビット整数に変換されます。
```

Before: 11100110111110100000000000000110000000000001
After:              10100000000000000110000000000001
```

長整数では切り捨ては行われません。概念的には、正の長整数は先頭の `0` ビットが無限にあり、負の長整数は先頭の `1` ビットが無限にあると理解してください。

任意の数値 `x` と `-1` とのビットごとの AND 演算は、32 ビット整数に変換された `x` を返します。代わりに `Math.trunc()` を使用してください。

例
-

### ビット論理積の使用

```js
// 9 (00000000000000000000000000001001)
// 14 (00000000000000000000000000001110)

14 & 9;
// 8 (00000000000000000000000000001000)

14n & 9n; // 8n
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # prod-BitwiseANDExpression |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* ビット演算子 (JavaScript ガイド)
* ビット論理積代入 (`&=`)


Null 合体代入 (??=) - JavaScript

Null 合体代入 (??=)
===============

Null 合体代入 (`x ??= y`) 演算子は、`x` が nullish (`null` または `undefined`) である場合にのみ代入を行います。

試してみましょう
--------

構文
--

```js
expr1 ??= expr2;
```

解説
--

### 短絡評価 (ショートサーキット)

Null 合体演算子は左から右に評価され、次のルールを使って短絡評価の可能性があるかどうかテストされます。

`(null や undefined ではない式) ?? expr` は、左辺が `null` でも `undefined` でもないことが証明されたら、左辺の式が短絡評価されます。

短絡評価とは、上記の `expr` 部分が**評価されない**ことを意味します。したがって、評価された場合の副作用は発生しません (例えば、`expr` が関数呼び出しである場合、呼び出しは行われません)。

Null 合体代入も短絡評価されます。これは、`x ??= y` が以下と等価であることを意味します。

```js
x ?? (x = y);
```

そして、常に代入が行われる以下と等価ではありません。

```js
x = x ?? y;
```

例
-

### Null 合体代入演算子の使用

```js
function config(options) {
  options.duration ??= 100;
  options.speed ??= 25;
  return options;
}

config({ duration: 125 }); // { duration: 125, speed: 25 }
config({}); // { duration: 100, speed: 25 }
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-assignment-operators |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* Null 合体演算子 (`??`)
* Nullish
* 真値
* 偽値


カンマ演算子 (,) - JavaScript

カンマ演算子 (,)
==========

**カンマ演算子** (**`,`**) は、それぞれの演算対象を（左から右に）評価し、最後のオペランドの値を返します。これにより、複数の式が評価される複合式を作成することができ、複合式の最終値はそのメンバー式の一番右端の値となります。これは、`for` ループに複数の引数を提供する場合によく使用されます。

試してみましょう
--------

構文
--

```js
expr1, expr2, expr3...
```

引数
--

`expr1`, `expr2`, `expr3`...

1 つ以上の式で、最後の式が複合式の値として返されます。

使用上の注意
------

カンマ演算子は、単一の式が求められる場所で複数の式を記述したい場合に使うことができます。この演算子が最もよく使われるのは、 `for` ループで複数の引数を与えたいときです。

カンマ演算子は、配列、オブジェクト、関数の引数や引数の内部にあるカンマとは大きく異なります。

例
-

例えば次のコードでは、 `a` が、1 辺 10 要素からなる 2 次元配列内の要素を一度に 2 つ 変化させる為に、変数宣言部分でカンマ演算子を用いています。

このコードは、配列における対角線の要素の値を出力するものです。

```js
for (var i = 0, j = 9; i <= 9; i++, j--)
  console.log("a[" + i + "][" + j + "] = " + a[i][j]);
```

代入を行う際にカンマを使うと、カンマ演算子が通常どおりに働いていないかのように見える場合があります (カンマ演算子が式の中にないため)。以下の例では `a` には `b = 3` の値 (すなわち 3) が設定されますが、さらに `c = 4` が評価されて、その結果 (すなわち 4) がコンソールに返されます。これは演算子の優先順位と結合性のためです。

```js
var a, b, c;

(a = b = 3), (c = 4); // コンソールに 4 が返る
console.log(a); // 3 (もっとも左)

var x, y, z;

x = ((y = 5), (z = 6)); // コンソールに 6 が返る
console.log(x); // 6 (もっとも右)
```

### 処理と返値

カンマ演算子が行うことのもうひとつの例が、値を返す前の処理です。前述のとおり最後の要素のみを返しますが、その他すべての要素も評価します。よって、以下のようなことができます。

```js
function myFunc() {
  var x = 0;

  return (x += 1, x); // return ++x と同じ
}
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-comma-operator |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* `for` ループ


Null 合体演算子 (??) - JavaScript

Null 合体演算子 (??)
===============

**Null 合体演算子 (`??`)** は論理演算子の一種です。この演算子は左辺が `null` または `undefined` の場合に右の値を返し、それ以外の場合に左の値を返します。

これは論理 OR 演算子 (`||`) の特殊形と見なすことができます。そちらは左辺の値が `null` や `undefined` だけでなく、何らかの偽値であった場合に右辺値を返すものです。つまり、 `||` を使って別の変数 `foo` に何らかの既定値を与える場合、一部の偽値（例えば `''` や `0`）を使用可能とみなすと、予想外の動作に遭遇することがあります。詳しい例は以下を参照してください。

Null 合体演算子は演算子の優先順位が下から 5 番目で、 `||` のすぐ下、条件（三項）演算子のすぐ上とします。

試してみましょう
--------

構文
--

```js
leftExpr ?? rightExpr;
```

例
-

### Null 合体演算子の使用

次の例では、既定値を設定していますが、`null` や `undefined` 以外の値は保持されます。

```js
const nullValue = null;
const emptyText = ""; // falsy
const someNumber = 42;

const valA = nullValue ?? "default for A";
const valB = emptyText ?? "default for B";
const valC = someNumber ?? 0;

console.log(valA); // "default for A"
console.log(valB); // "" (空文字列は null でも undefined でもないため)
console.log(valC); // 42
```

### 変数に既定値を代入する

以前は、変数に既定値を代入したい場合の一般的なパターンは、論理 OR 演算子（`||`）を使用することでした。

```js
let foo;

// foo には何も値が代入されていないので、 undefined のままです
let someDummyText = foo || "Hello!";
```

しかし、`||` が論理演算子であるため、左辺の値は評価によって強制的に論理値になり、偽値（`0`, `''`, `NaN`, `null`, `undefined`）が返されることはありません。この動作は、 `0` や `''`, `NaN` を有効な値と考えている場合、予期せぬ結果を引き起こす可能性があります。

```js
let count = 0;
let text = "";

let qty = count || 42;
let message = text || "hi!";
console.log(qty); // 42 であり 0 ではない
console.log(message); // "hi!" であり "" ではない
```

Null 合体演算子は、左辺の値が `null` もしくは `undefined` のどちらか（その他の falsy な値は含みません）に評価された場合にのみ右辺の値を返すことで、この潜在的な危険を回避します。

```js
let myText = ""; // 空文字列（偽値）

let notFalsyText = myText || "Hello world";
console.log(notFalsyText); // Hello world

let preservingFalsy = myText ?? "Hi neighborhood";
console.log(preservingFalsy); // '' (myText は undefined でも null でもない)
```

### 短絡評価

OR 演算子や AND 演算子と同様に、左辺が `null` でも `undefined` でもないことが判明した場合、右辺の式は評価されません。

```js
function A() {
  console.log("A was called");
  return undefined;
}
function B() {
  console.log("B was called");
  return false;
}
function C() {
  console.log("C was called");
  return "foo";
}

console.log(A() ?? C());
// "A was called"、 "C was called" のあと "foo" と出力
// A() は undefined を返すため、両方の式が評価されるため

console.log(B() ?? C());
// "B was called" のあと "false" と出力
// B() は false を返すため（そして null も undefined も返さない）、
// 右辺の式は評価されない
```

### AND 演算子、OR 演算子とつなげて使わない

AND 演算子 (`&&`) と OR 演算子 (`||`) を直接 `??` と組み合わせて使うことはできません。このような場合 `SyntaxError` が発生します。

```js
null || undefined ?? "foo"; // SyntaxError が発生
true || undefined ?? "foo"; // SyntaxError が発生
```

ただし、カッコを付けて明示的に優先順位を示すのは正しいやり方です。

```js
(null || undefined) ?? "foo"; // "foo" を返す
```

### オプション連鎖演算子 (`?.`) との関係

Null 合体演算子は、 `undefined` と `null` を特定の値として扱いますが、オプション連鎖演算子 (`?.`) も同様の扱いをします。この演算子は、`null` または `undefined` である可能性のあるオブジェクトのプロパティにアクセスするのに便利です。

```js
let foo = { someFooProp: "hi" };

console.log(foo.someFooProp?.toUpperCase() ?? "not available"); // "HI"
console.log(foo.someBarProp?.toUpperCase() ?? "not available"); // "not available"
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # prod-CoalesceExpression |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* オプション連鎖演算子
* 論理 OR (`||`) 演算子
* デフォルト引数


import.meta - JavaScript

import.meta
===========

**`import.meta`** オブジェクトはコンテキスト固有のメタデータを JavaScript のモジュールに公開します。これには、モジュールの URL のようなモジュールに関する情報が含まれています。

構文
--
```

import.meta
```

説明
--

構文は、`import` キーワードとドット、プロパティ名の `meta` で構成されています。通常、ドットの左側はプロパティアクセスが実行されるオブジェクトですが、ここでの `import` はオブジェクトではありません。

`import.meta` オブジェクトは ECMAScript 実装によって生成され、プロトタイプは `null` です。オブジェクトは拡張でき、そのプロパティは書き込み、構成、列挙可能です。

例
-

### import.meta を使用する

`my-module.mjs` モジュールを指定します。

```html
<script type="module" src="my-module.js"></script>
```

`import.meta` オブジェクトを使用してモジュールのメタ情報にアクセスできます。

```js
console.log(import.meta); // { url: "file:///home/user/my-module.js" }
```

モジュールのベース URL を示す `url` プロパティを持つオブジェクトを返します。これは、外部スクリプトの場合はスクリプトを取得した URL、インラインスクリプトの場合はそれを含むドキュメントのベース URL です。

これには、クエリパラメータまたはハッシュ（つまり、`?` または `#`）が含まれることに注意してください。

例えば、以下のような HTML で

```html
<script type="module">
 import "./index.mjs?someURLInfo=5";
</script>
```

以下の JavaScript ファイルは、`someURLInfo` パラメータをログに記録します。

```js
// index.mjs
new URL(import.meta.url).searchParams.get("someURLInfo"); // 5
```

ファイルが別のファイルをインポートする場合も同様です。

```js
// index.mjs
import "./index2.mjs?someURLInfo=5";

// index2.mjs
new URL(import.meta.url).searchParams.get("someURLInfo"); // 5
```

メモ: 後者の例のように Node.js はクエリパラメータ（またはハッシュ）を渡しますが、Node 14.1.0 以降、クエリパラメータを持つ URL を `node --experimental-modules index.mjs?someURLInfo=5` という形式で読み込むとエラーになることに注意してください（この文脈では URL ではなくファイルとして扱われます）。

このようなファイル固有の引数の受け渡しは、アプリケーション全体の `location.href`（HTML ファイルパスの後にクエリ文字列やハッシュを追加したもの [Node.js では `process.argv` を介して]）で使用されているものを補完する場合があります。

仕様
--

| Specification |
| --- |
| ECMAScript Language Specification # prod-ImportMeta |
| HTML Standard # hostgetimportmetaproperties |

ブラウザー実装状況
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* `import`
* `export`


等価 (==) - JavaScript

等価 (==)
=======

等価演算子 (`==`) は、二つのオペランドが等しいことを検査し、論理値で結果を返します。厳密等価演算子とは異なり、オペランドの型が異なる場合には型の変換を試みてから比較を行います。

試してみましょう
--------

構文
--

```js
x == y;
```

解説
--

等価演算子 (`==` および `!=`) は、抽象等価比較アルゴリズムを使用して 2 つのオペランドを比較します。これは、およそ次のようにまとめることができます。

* 両方のオペランドがオブジェクトである場合、同じオブジェクトを指している場合に限り `true` を返します。
* 一方のオペランドが `null` で、もう一方が `undefined` であった場合は `true` を返します。
* オペランドの型が異なる場合は、比較前に同じ型に変換を試みます。
    + 数値と文字列を比較する場合、文字列を数値に変換しようとします。
    + 一方のオペランドが論理値である場合、その論理値のオペランドが `true` である場合は 1 に、 `false` である場合は +0 に変換します。
    + オペランドのうちの一方がオブジェクトで、もう一方が数値または文字列である場合は、そのオブジェクトの `valueOf()` および `toString()` メソッドを使用してプリミティブに変換を試みます。
* オペランドが同じ型である場合は、次のよう比較します。
    + 文字列型: 両方のオペランドが同じ文字を同じ順序で持っている場合のみ、 `true` を返します。
    + 数値型: 両方のオペランドが同じ値を持っている場合のみ、 `true` を返します。 `+0` と `-0` は同じ値と見なされます。一方のオペランドが `NaN` である場合は `false` を返します。
    + 論理型: 両方のオペランドが共に `true` であるか、共に `false` である場合のみ `true` になります。

この演算子と厳密等価 (`===`) 演算子の最も顕著な違いは、厳密等価演算子が型変換を試みない点です。厳密等価演算は、オペランドの型が異なる場合は常に異なるものと見なします。

例
-

### 型変換がない場合の比較

```js
1 == 1; // true
"hello" == "hello"; // true
```

### 型変換がある場合の比較

```js
"1" == 1; // true
1 == "1"; // true
0 == false; // true
0 == null; // false
0 == undefined; // false
0 == !!null; // true (論理 NOT 演算子を参照)
0 == !!undefined; // true (論理 NOT 演算子を参照)
null == undefined; // true

const number1 = new Number(3);
const number2 = new Number(3);
number1 == 3; // true
number1 == number2; // false
```

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

```js
const object1 = { key: "value" };
const object2 = { key: "value" };

object1 == object2; // false
object2 == object2; // true
```

### 文字列と String オブジェクトの比較

`new String()` を使用して構築された文字列はオブジェクトであることに注意してください。文字列リテラルとの比較を行うと、 `String` オブジェクトは文字列リテラルに変換され、その中身が比較されます。ただし、両方のオペランドが `String` オブジェクトであった場合は、オブジェクトとして比較され、同じオブジェクトを参照している場合だけ比較に成功します。

```js
const string1 = "hello";
const string2 = String("hello");
const string3 = new String("hello");
const string4 = new String("hello");

console.log(string1 == string2); // true
console.log(string1 == string3); // true
console.log(string2 == string3); // true
console.log(string3 == string4); // false
console.log(string4 == string4); // true
```

### Date と文字列の比較

```js
const d = new Date("December 17, 1995 03:24:00");
const s = d.toString(); // for example: "Sun Dec 17 1995 03:24:00 GMT-0800 (Pacific Standard Time)"
console.log(d == s); //true
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-equality-operators |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* 不等価演算子
* 厳密等価演算子
* 厳密不等価演算子


delete 演算子 - JavaScript

delete 演算子
==========

JavaScript の **`delete` 演算子**は、オブジェクトからプロパティを削除します。同じプロパティへの参照がそれ以上保持されていない場合は、自動的に解放されます。

試してみましょう
--------

構文
--

```js
delete expression;
```

`expression` は下記のように、プロパティへの参照として評価されるべきものです。

```js
delete object.property;
delete object["property"];
```

### 引数

`object`

オブジェクト名、またはオブジェクトとして評価される式です。

`property`

削除するプロパティです。

### 返値

プロパティが自分自身の構成不可のプロパティであった場合、 strict モードでなければ `false` を返します。それ以外の場合は `true` を返します。

### 例外

strict モードでは、プロパティが編集不可の場合、`TypeError` が発生します。

解説
--

一般的に信じられていることとは異なり (おそらく C++ における delete のような他のプログラミング言語の影響ですが)、`delete` 演算子は、直接的にメモリーを解放することは**ありません**。メモリーの管理は参照が切れることで間接的に行われます。詳細はメモリー管理を参照してください。

**`delete`** 演算子は指定したプロパティをオブジェクトから取り除きます。削除に成功すると `true` を返し、そうでなければ `false` を返します。

ただし、次のようなシナリオを考慮することが重要です。

* 削除しようとしたプロパティが存在しない場合、`delete` は何もせずに `true` を返します。
* そのオブジェクトのプロトタイプチェーンに同名のプロパティが存在する場合、削除後はプロトタイプチェーンのプロパティをオブジェクトが使うようになります (つまり、`delete` は自身のプロパティにのみ効果があります)。
* グローバルスコープや関数スコープから `var` で宣言されたプロパティは削除できません。
    + そのため、`delete` はグローバルスコープ内の関数を削除できません (関数定義の一部であるか関数式の一部であるかにかかわらず)。
    + (グローバルスコープを除く) オブジェクトの一部である関数は `delete` で削除できます。
* `let` や `const` で宣言された任意のプロパティはそれらが宣言されたスコープから削除できません。
* 編集不可能なプロパティは削除できません。これには `Math` や `Array`、`Object` のような組み込みオブジェクトのプロパティや `Object.defineProperty()` のようなメソッドで編集不可として生成されたプロパティが含まれます。

次のスニペットがシンプルな例です。

```js
var Employee = {
  age: 28,
  name: "abc",
  designation: "developer",
};

console.log(delete Employee.name); // true を返す
console.log(delete Employee.age); // true を返す

// When trying to delete a property that does
// not exist, true is returned
console.log(delete Employee.salary); // true を返す
```

### 編集不可のプロパティ

プロパティが編集不可に設定されているとき、`delete` は何もせずに `false` を返します。strict モードでは、これは `TypeError` を生成します。

```js
var Employee = {};
Object.defineProperty(Employee, "name", { configurable: false });

console.log(delete Employee.name); // false を返す
```

`var` や `let`、`const` は、`delete` 演算子で削除できない編集不可のプロパティを生成します:

```js
var nameOther = "XYZ";

// We can access this global property using:
Object.getOwnPropertyDescriptor(window, "nameOther");

// output: Object {value: "XYZ",
// writable: true,
// enumerable: true,
// configurable: false}

// Since "nameOther" is added using with the
// var keyword, it is marked as "non-configurable"

delete nameOther; // return false
```

strict モードでは、例外が発生します。

### strict モードとそれ以外の違い

strict モードのとき、`delete` が変数や関数の引数、関数名への直接参照に使われた場合、`SyntaxError` が発生します。したがって、 strict モードでエラーが発生することを防ぐためには、 `delete` 演算子を `delete object.property` または `delete object['property']` の形で使用する必要があります。

```js
Object.defineProperty(globalThis, "variable1", {
  value: 10,
  configurable: true,
});
Object.defineProperty(globalThis, "variable2", {
  value: 10,
  configurable: false,
});

// strict モードでは SyntaxError
console.log(delete variable1); // true

// strict モードでは SyntaxError
console.log(delete variable2); // false
```

```js
function func(param) {
  // strict モードでは SyntaxError
  console.log(delete param); // false
}

// strict モードでは SyntaxError
console.log(delete func); // false
```

### ブラウザーの互換性の注意

ECMAScript はオブジェクトに対して反復処理を行った時の順序を実装系依存であるとしているにもかかわらず、主要なブラウザーはいずれも、(少なくともプロトタイプ上にないプロパティについては) 最初に追加されたプロパティを最初に処理する順序に対応しているようです。しかし Internet Explorer では、プロパティに対して `delete` を用いたときにややこしい結果になることがあり、これが他のブラウザーが単純なオブジェクトを整列された連想配列のように用いることの障害になります。Internet Explorer では、プロパティの*値*を `undefined` に設定しようとしたとき、後から同じ名前で再びプロパティを追加すると、そのプロパティは*元の*場所で処理されるようになります。削除済みのプロパティを再度追加した場合に予想されるような、最後の場所ではありません。

複数のブラウザーで同じ連想配列を使用したい場合は、可能であれば `Map` を使用してください。または、2 つに分けた配列 (片方はキー、もう片方は値) やプロパティを一つだけ持ったオブジェクトの配列を構築するなどの方法でこの構造をシミュレーションしてください。

例
-

```js
// adminName プロパティをグローバルスコープに生成
adminName = "xyz";

// empCount プロパティをグローバルスコープに生成
// var を使用しているため、これは構成不可となります。 let や const でも同じことになります。
var empCount = 43;

EmployeeDetails = {
  name: "xyz",
  age: 5,
  designation: "Developer",
};

// adminName はグローバルスコープのプロパティです。
// var を使用せずに生成されたため、構成可能になっているので
// 削除することができます。
delete adminName; // true を返す

// 対照的に、 empCount は var が使用されたので
// 構成可能ではありません。
delete empCount; // false を返す

// delete を使用してオブジェクトからプロパティを削除することができます。
delete EmployeeDetails.name; // true を返す

// プロパティが存在しない場合であっても、 delete は "true" を返します。
delete EmployeeDetails.salary; // true を返す

// delete は組み込み静的プロパティには効果がありません。
delete Math.PI; // false を返す

// EmployeeDetails はグローバルスコープのプロパティです。
// "var" を使用せずに定義されたため、構成可能となっています。
delete EmployeeDetails; // true を返す

function f() {
  var z = 44;

  // delete はローカル変数名には効果がありません。
  delete z; // false を返す
}
```

### `delete` とプロトタイプチェーン

次の例では、プロトタイプチェーン上に同じ名前を持つプロパティがある場合に、オブジェクトの自身のプロパティを削除しています。

```js
function Foo() {
  this.bar = 10;
}

Foo.prototype.bar = 42;

var foo = new Foo();

// foo.bar は自身のプロパティに関連付けられて
// います。
console.log(foo.bar); // 10

// foo オブジェクトにある自身のプロパティを
// 削除します。
delete foo.bar; // true を返す

// foo.bar がプロトタイプチェーン上でまだ
// 利用できます。
console.log(foo.bar); // 42

// プロトタイプ上のプロパティを削除します。
delete Foo.prototype.bar; // true を返す

// "bar" プロパティは Foo 上で削除されたので
// 継承されなくなりました。
console.log(foo.bar); // undefined
```

### 配列の要素の削除

配列の要素を削除したとき、配列の `length` は影響を受けません。これは配列の最後の要素を削除しても保持されます。

`delete` 演算子が配列の要素を削除すると、要素は配列からなくなります。 次の例では、`trees[3]` が `delete` で削除されます。

```js
var trees = ["redwood", "bay", "cedar", "oak", "maple"];
delete trees[3];
if (3 in trees) {
  // これは実行されない
}
```

ある配列の要素を存在したまま未定義の値としたい場合は、`delete` 演算子の代わりに `undefined` 値を使用してください。次の例では、`trees[3]` に `undefined` を割り当てていますが、配列のその要素は存在したままです。

```js
var trees = ["redwood", "bay", "cedar", "oak", "maple"];
trees[3] = undefined;
if (3 in trees) {
  // これは実行される
}
```

代わりに、配列の内容を変更して配列要素を削除したい場合は、``splice()`` メソッドを使用してください。次の例では、`splice()` を使用して配列から `trees[3]` を削除しています。

```js
var trees = ["redwood", "bay", "cedar", "oak", "maple"];
trees.splice(3, 1);
console.log(trees); // ["redwood", "bay", "cedar", "maple"]
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-delete-operator |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* In depth analysis on
delete
* `Reflect.deleteProperty()`
* `Map.prototype.delete()`


import() - JavaScript

import()
========

**`import()`** 構文は、よくダイナミックインポートと呼ばれますが、非同期かつ動的に、 ECMAScript モジュールを、潜在的にモジュールではない環境に読み込めるようにする関数風の式です。

宣言スタイルのものとは異なり、動的インポートは必要なときだけ評価され、より柔軟な構文が可能になります。

構文
--

```js
import(moduleName)
```

`import()` 呼び出しは関数呼び出しによく似た構文ですが、 `import` 自体はキーワードであり、関数ではありません。`const myImport = import` のようなエイリアスを作成することはできず、 `SyntaxError` が発生します。

### 引数

`moduleName`

インポート元モジュール。指定子の評価はホスト次第ですが、常に静的なインポート宣言と同じアルゴリズムに従います。

### 返値

モジュール名前空間オブジェクト、すなわち `moduleName` からのすべてのエクスポートを格納したオブジェクトで履行されるプロミスを返します。

`import()` の評価で同期的にエラーが発生することはありません。`moduleName` は文字列に強制されるので、強制が発生した場合、そのエラーとともにプロミスが拒否されます。

解説
--

import宣言の構文（`import something from "somewhere"`）は静的で、常にモジュールが 読み込まれた時点で評価される結果となります。ダイナミックインポートを使用すると、import宣言の構文の硬直性を回避し、条件付きまたはオンデマンドでモジュールを読み込むことができます。以下のような理由で、動的インポートが使用することがあります。

* 静的にインポートするとコードの読み込みが著しく遅くなる場合で、インポートしているコードが必要になる可能性が低い、または後日必要になる可能性がある場合。
* 静的にインポートすると、プログラムのメモリー使用量が大幅に増える場合で、インポートするコードが必要になる可能性が低い場合。
* 読み込むモジュールが読み込む時点で存在しない場合。
* インポート指定子文字列を動的に構築する必要がある場合。（静的インポートでは静的指定のみ対応しています。）
* インポートされるモジュールに副作用があり、ある条件を満たさない限りその副作用を望まない場合。 （モジュールに副作用を持たないことを推奨しますが、モジュールの依存関係でこれを制御できないこともあります）。
* モジュール以外の環境（例: `eval` やスクリプトファイル）にいるとき。

動的インポートは必要なときだけ使用してください。静的な形は、初期の依存関係を読み込むのに適しており、静的解析ツールやツリーシェイキングの恩恵を受けやすくなります。

ファイルがモジュールとして実行されていない場合（HTML ファイルで参照される場合、script タグに `type="module"` が必要）、静的な import 宣言は使用できませんが、非同期の動的 import 構文は常に利用できるので、モジュール以外の環境にもモジュールをインポートすることができます。

### モジュール名前空間オブジェクト

*モジュール名前空間オブジェクト* は、モジュールからのすべてのエクスポートを記述しているオブジェクトです。これは静的なオブジェクトで、モジュールが評価されるときに作成されます。モジュールの名前空間オブジェクトにアクセスする方法は 2 つあります。名前空間インポート (`import * as name from moduleName`)、または動的インポートの履行値を通じてです。

モジュール名前空間オブジェクトは封印された、プロトタイプが `null`のオブジェクトです。これは、オブジェクトのすべての文字列キーが、モジュールのエクスポートに対応し、余分なキーがないことを意味しています。すべてのキーは辞書順に列挙可能で（すなわち`Array.prototype.sort()` の既定の動作）、デフォルトエクスポートは `default` というキーで利用できます。さらに、モジュール名前空間オブジェクトには `@@toStringTag` プロパティがあり、値は `"Module"` で、 `Object.prototype.toString()` で使用されるものです。

文字列プロパティは構成不可能で、`Object.getOwnPropertyDescriptors()` を使用してその記述子を取得すると書き込みが可能になります。しかし、プロパティを新しい値に割り当てることはできないため、実質的に読み取り専用となります。この動作は、静的インポートが「ライブ結合」- 値をエクスポートするモジュールは再割り当てることができるが、インポートするモジュールはできない - を作成するという事実を反映したものです。構成不可、書き込み不可のプロパティは一定でなければならないため、プロパティの書き込み可否は、値が変化する可能性を反映します。例えば、変数のエクスポートされた値を再代入することができ、新しい値はモジュール名前空間オブジェクトで監視することができます。

それぞれのモジュール指定子は固有のモジュール名前空間オブジェクトに対応するため、一般的には以下のようになります。

```js
import \* as mod from "/my-module.js";

import("/my-module.js").then((mod2) => {
  console.log(mod === mod2); // true
});
```

ただし、1つだけ奇妙な場合があります。プロミスは決して thenable に履行されることはないので、もし `my-module.js` モジュールが `then()` という関数をエクスポートすると、その関数はダイナミックインポートのプロミスが履行されると自動的に呼ばれることになります。

```js
// my-module.js
export function then() {
  console.log("then() called");
}
```

```js
// main.js
import \* as mod from "/my-module.js";

import("/my-module.js").then((mod2) => {
  // Logs "then() called"
  console.log(mod === mod2); // false
});
```

例
-

### 副作用のあるモジュールだけをインポート

```js
(async () => {
  if (somethingIsTrue) {
    // 副作用のあるモジュールをインポート
    await import("/modules/my-module.js");
  }
})();
```

自分のプロジェクトで ESM をエクスポートするパッケージを使用する場合、副作用がある場合のみインポートすることもできます。この場合、パッケージのエントリーポイントファイル（およびこのファイルがインポートするすべてのファイル）内のコードのみが実行されます。

### デフォルトをインポート

返されたオブジェクトから "default" のキーを再構築し、名前を変更する必要があります。

```js
(async () => {
  if (somethingIsTrue) {
    const {
      default: myDefault,
      foo,
      bar,
    } = await import("/modules/my-module.js");
  }
})();
```

### ユーザー操作に応じたオンデマンドのインポート

この例では、ユーザーの操作（この場合はボタンのクリック）に基づいてページに機能を読み込ませ、そのモジュール内の関数を呼び出す方法を示しています。この機能を実装するための唯一の方法というわけではありません。`import()` 関数は `await` にも対応しています。

```js
const main = document.querySelector("main");
for (const link of document.querySelectorAll("nav > a")) {
  link.addEventListener("click", (e) => {
    e.preventDefault();

    import("/modules/my-module.js")
      .then((module) => {
        module.loadPageInto(main);
      })
      .catch((err) => {
        main.textContent = err.message;
      });
  });
}
```

### 環境に応じて様々な形のモジュールをインポート

サーバーサイドレンダリングなどの処理では、サーバーとブラウザーで異なるグローバルやモジュールと対話するため、異なるロジックを読み込む必要がある場合があります（例えば、ブラウザーのコードは `document` や `navigator` などのウェブ API に、サーバーコードはサーバーファイルシステムにアクセスすることができます）。条件付きの動的インポートによって、このようなことが可能になります。

```js
let myModule;

if (typeof window === "undefined") {
  myModule = await import("module-used-on-server");
} else {
  myModule = await import("module-used-in-browser");
}
```

### リテラルでない指定子を持つモジュールのインポート

動的インポートでは、モジュール指定子として、文字列リテラルに限らず、任意の式で指定することができます。

ここでは、 `/modules/module-0.js`、`/modules/module-1.js` など、10 個のモジュールを並列に読み込んで、それぞれがエクスポートする `load` 関数を呼び出しています。

```js
Promise.all(
  Array.from({ length: 10 }).map(
    (\_, index) => import(`/modules/module-${index}.js`),
  ),
).then((modules) => modules.forEach((module) => module.load()));
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-import-calls |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* `import` 宣言


async function 式 - JavaScript

async function 式
================

Baseline Widely available
-------------------------

This feature is well established and works across many devices and browser versions. It’s been available across browsers since April 2017.

* Learn more
* See full compatibility
* Report feedback
**`async function`** キーワードは、式の中で非同期関数を定義するために使用できます。

非同期関数は、`async function` 宣言またはアロー構文を使用して定義することもできます。

構文
--

```js
async function (param0) {
  statements
}
async function (param0, param1) {
  statements
}
async function (param0, param1, /\* …, \*/ paramN) {
  statements
}

async function name(param0) {
  statements
}
async function name(param0, param1) {
  statements
}
async function name(param0, param1, /\* …, \*/ paramN) {
  statements
}
```

**メモ:** 式文は `async function` キーワードを使用することができません。`async function` 宣言との混同を防ぐためです。`async function` キーワードは文を受け付けることができないコンテキストで現れた場合のみ、式の始まりになります。

### 引数

`name` 省略可

関数名です。関数が*無名*の場合は省略可能です。名前は関数の本体内のみのローカルです。

`paramN` 省略可

関数に渡される引数名です。引数の構文については、関数リファレンスを参照してください。

`statements` 省略可

関数本体を構成する文です。

解説
--

`async function` 式は `async function` 宣言とよく似ており、構文もほとんど同じです。async `function` 式と `async function` 宣言の主な違いは、`async function` 式が*関数名*を省略して*無名*関数を生成することができる点です。`async function` 式は、定義後直ちに実行される IIFE（即時実行関数式）として使用することもでき、最上位の await を模倣することができます。詳細は関数の章を見てください。

例
-

### シンプルな例

```js
function resolveAfter2Seconds(x) {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(x);
    }, 2000);
  });
}

// 変数に代入された非同期関数式
const add = async function (x) {
  const a = await resolveAfter2Seconds(20);
  const b = await resolveAfter2Seconds(30);
  return x + a + b;
};

add(10).then((v) => {
  console.log(v); // 4 秒後に 60 を表示
});

// IIFE として使用される非同期関数式
(async function (x) {
  const p1 = resolveAfter2Seconds(20);
  const p2 = resolveAfter2Seconds(30);
  return x + (await p1) + (await p2);
})(10).then((v) => {
  console.log(v); // 2 秒後に 60 を表示
});
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-async-function-definitions |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* `async function`
* `AsyncFunction`
* `await`


左シフト (<<) - JavaScript

左シフト (<<)
=========

**左シフト演算子 (`<<`)** は、1 つ目のオペランドを指定されたビット数だけ左にずらします。左にずらしてあふれたビットは廃棄されます。0 のビットが右からずれて入ります。

試してみましょう
--------

構文
--

```js
a << b;
```

解説
--

この演算子は、1 つ目のオペランドを指定されたビット数だけ左にずらします。左にずらしてあふれたビットは廃棄されます。 0 のビットが右からずれて入ります。

例えば `9 << 2` は 36 になります。

```js
.    9 (10 進数): 00000000000000000000000000001001 (2 進数)
                  --------------------------------
9 << 2 (10 進数): 00000000000000000000000000100100 (2 進数) = 36 (10 進数)
```

 任意の数 `x` を `y` ビット分だけ左にビット単位にずらすと、 `x * 2 ** y` になります。
 ですから、例えば `9 << 3` は `9 * (2 ** 3) = 9 * (8) = 72` になります。

例
-

### 左シフトの使用

```js
9 << 3; // 72

// 9 \* (2 \*\* 3) = 9 \* (8) = 72
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-left-shift-operator |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* ビット演算子 (JavaScript ガイド)
* 左シフト代入演算子


剰余 (%) - JavaScript

剰余 (%)
======

剰余演算子 (`%`) は、1 つ目のオペランドが 2 つ目のオペランドで除算されたときの余りである剰余を返します。これは常に被除数の符号を取ります。

試してみましょう
--------

構文
--

```js
x % y
```

解説
--

`%` 演算子のオペランドは、数値型と長整数型の 2 つの型ででオーバーロードされています。 これは、まず両方のオペランドを数値に変換し、それらの型を調べます。両方のオペランドが長整数型になった場合は長整数型の剰余を実行し、そうでない場合は数値型の剰余を実行します。一方のオペランドが長整数型になり、他方が数値型になった場合は `TypeError` が発生します。

`n % d` の演算では、`n` を被除数、`d` を除数と呼びます。この演算処理は、オペランドのいずれかが `NaN` であるか、 `n` が ±無限大であるか、または `d` が ±0 である場合に `NaN` を返します。

両方のオペランドが 0 ではなく有限であるとき、剰余 `r` は `r := n - d * q` として計算されます。ここで `q` は、 `r` ができるだけ 0 に近く、被除数 `n` と同じ符号を持つ整数です。

なお、多くの言語では '%' はリマインダー演算子ですが、言語によっては（例えば Python や Perl では）モジュロ演算子になります。モジュロは `k := n - d * q` と定義されます。ここで `q` は `k` が除数 `d` と同じ符号を持ち、かつ使用可能な限り 0 に近い整数です。 2 つのオペランドの符号が同じであれば、両者は等価になりますが、オペランドの符号が異なる場合、オペランドの符号が異なる場合、モジュロの結果は符号が常に *除数* と同じになり、リマインダーは被除数と同じになります。 JavaScript でモジュロを得るには、 `n % d` の代わりに `((n % d) + d) % d` を使用してください。 JavaScript では、ビット単位のシフト演算子（`<<`、`>>` など）の 2 つ目のオペランドを正規化するために、（専用の演算子のない）モジュロ演算が使用され、オフセットが常に正の値になります。

長整数型の除算では、被除数 `y` が `0n` の場合に `RangeError` が発生します。これはゼロによる剰余は `NaN` を返しますが、長整数には `NaN` の概念がないからです。

例
-

### 正の値の剰余

```js
13 % 5; // 3
1 % -2; // 1
1 % 2; // 1
2 % 3; // 2
5.5 % 2; // 1.5

3n % 2n; // 1n
```

### 負の値の剰余

```js
-13 % 5; // -3
-1 % 2; // -1
-4 % 2; // -0

-3n % 2n; // -1n
```

### NaN の剰余

```js
NaN % 2; // NaN
```

### 無限大の剰余

```js
Infinity % 2; // NaN
Infinity % 0; // NaN
Infinity % Infinity; // NaN
2 % Infinity; // 2
0 % Infinity; // 0
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-multiplicative-operators |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* 加算 (`+`)
* 減算 (`-`)
* 除算 (`/`)
* 乗算 (`*`)
* べき乗 (`**`)
* インクリメント (`++`)
* デクリメント (`--`)
* 単項マイナス (`-`)
* 単項プラス (`+`)
* Remainder operator vs. modulo operator by Dr. Axel Rauschmayer (2019)


単項プラス (+) - JavaScript

単項プラス (+)
=========

単項プラス演算子 (`+`) は、オペランドの前に置かれ、そのオペランドを評価し、それが数値以外の場合は数値に変換します。

試してみましょう
--------

構文
--

```js
+x;
```

解説
--

単項マイナス (`-`) も非数値を数値に変換できますが、単項プラスは数値に対して他の演算を行わないため、非数値を数値に変換する最も高速で好ましい方法です。これは、整数や浮動小数点の文字列表現や、非文字列値である `true`、`false`、`null` を変換することができます。10 進数と 16 進数 (接頭辞 0x) の両形式の整数と負の数 (ただし 16 進数を除く) に対応しています。BigInt 値に対してこの演算子を使用すると TypeError が発生します。特定の値を解析できない場合は、`NaN` と評価されます。

例
-

### 数値での使い方

```js
const x = 1;
const y = -1;

console.log(+x);
// 1
console.log(+y);
// -1
```

### 数値以外での使い方

```js
+true; // 1
+false; // 0
+null; // 0
+function (val) {
  return val;
}; // NaN
+1n; // BigInt 値は数値に変換できないためエラーになります
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-unary-plus-operator |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* 加算演算子
* 減算演算子
* 除算演算子
* 乗算演算子
* 剰余演算子
* べき乗演算子
* インクリメント演算子
* デクリメント演算子
* 単項マイナス演算子


論理否定 (!) - JavaScript

論理否定 (!)
========

論理否定 (`!`) 演算子 (論理反転、否定) は、真値を取ると偽値になり、その逆も同様です。これは通常論理型 (ブール型) の値に使用されます。論理型以外の値に使用した場合、単一のオペランドが `true` に変換できる場合は `false` を返し、それ以外は `true` を返します。

試してみましょう
--------

構文
--

```js
!expr;
```

解説
--

単一のオペランドが `true` に変換できる場合は `false` を返し、それ以外は `true` を返します。

ある値が `true` に変換できる場合、その値は真値 (truthy) と呼ばれます。ある値が `false` に変換できる場合、その値は偽値 (falsy) と呼ばれます。

false に変換することができる式の例を示します。

* `null`
* `NaN`
* `0`
* 空文字列 (`""` または `''` または ````)
* `undefined`

`!` 演算子は論理値以外のオペランドに対して使用することができますが、返値が常に論理型プリミティブに変換することが可能であるため、論理演算子と見なすことができます。返値 (または一般的な式) を対応する論理値に明示的に変換するには、二重の否定演算子または `Boolean` コンストラクターを使用してください。

例
-

### 否定の使用

以下のコードは `!` (論理否定) 演算子の例を示しています。

```js
n1 = !true; // !t は false を返す
n2 = !false; // !f は true を返す
n3 = !""; // !f は true を返す
n4 = !"Cat"; // !t は false を返す
```

### 二重否定 (`!!`)

複数の否定演算子を連続して使用することで、明示的にあらゆる値を対応する論理型プリミティブに変換することができます。変換は値の「真値性」または「偽値性」に基づいて行われます (truthy および falsy を参照)。

同じ変換は `Boolean` 関数を通じて行うこともできます。

```js
n1 = !!true; // !!truthy は true を返す
n2 = !!{}; // !!truthy は true: \*あらゆる\*オブジェクトは真値になります...
n3 = !!new Boolean(false); // ... .valueOF() が false の Boolean オブジェクトであっても
n4 = !!false; // !!falsy は false を返す
n5 = !!""; // !!falsy は false を返す
n6 = !!Boolean(false); // !!falsy は false を返す
```

### 否定同士の変換

以下の操作を**論理値**で行った場合、

```js
!!bCondition;
```

常に以下のものと等しくなります。

```js
bCondition;
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-logical-not-operator |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* `Boolean`
* 真値
* 偽値


単項マイナス (-) - JavaScript

単項マイナス (-)
==========

単項マイナス演算子 (`-`) はオペランドの前に置かれ、符号を反転します。

試してみましょう
--------

構文
--

```js
-x;
```

例
-

### 数値の符号を反転

```js
const x = 3;
const y = -x;

// y = -3
// x = 3
```

### 数値以外の符号を反転

単項マイナス演算子は、数値でないものを数値に変換することができます。

```js
const x = "4";
const y = -x;

// y = -4
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-unary-minus-operator |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* 加算演算子
* 減算演算子
* 除算演算子
* 乗算演算子
* 剰余演算子
* べき乗演算子
* インクリメント演算子
* デクリメント演算子
* 単項プラス演算子


代入 (=) - JavaScript

代入 (=)
======

単純代入演算子 (`=`) は、変数に値を代入するために使用されます。割り当て操作は、割り当てられた値として評価されます。代入演算子を使用して、単一の値を複数の変数に割り当てることができます。

試してみましょう
--------

構文
--

```js
x = y;
```

例
-

### 代入と連鎖

```ja
// 以下の変数を想定
//  x = 5
//  y = 10
//  z = 25

x = y     // x は 10
x = y = z // x, y そして z はすべて 25
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-assignment-operators |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* JavaScript ガイドの代入演算子


ビット否定 (~) - JavaScript

ビット否定 (~)
=========

ビット否定演算子 (`~`) は、オペランドの各ビットを反転します。他のビット演算子と同様、オペランドを 32 ビット符号付き整数に変換します。

試してみましょう
--------

構文
--

```js
~a;
```

解説
--

オペランドは 32 ビットの整数値に変換され、ビット (ゼロまたは 1) の並びによって表現されます。32 ビットを超える数値は最上位のビットが破棄されます。例えば、次の 32 ビットを超える整数は 32 ビット整数に変換されます。
```

変換前: 11100110111110100000000000000110000000000001
変換後:             10100000000000000110000000000001
```

オペランドの各ビットが反転されて結果になります。

`NOT` 演算の真理値表は次のようになります。

| a | NOT a |
| --- | --- |
| 0 | 1 |
| 1 | 0 |

```js
 9 (10 進数) = 00000000000000000000000000001001 (2 進数)
               --------------------------------
~9 (10 進数) = 11111111111111111111111111110110 (2 進数) = -10 (10 進数)
```

32 ビット符号付き整数のオペランドは、2 の補数によって反転されます。すなわち、最上位ビットが負の数であることを表します。

ある数 `x` のビット否定 は `-(x + 1)` になります。例えば、`~-5` は `4` になります。

数値に 32 ビット表現を使用するため `~-1` および `~4294967295` (2^32 - 1) はいずれも `0` になることに注意してください。

例
-

### ビット否定の使用

```js
~0; // -1
~-1; // 0
~1; // -2
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-bitwise-not-operator |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* ビット演算子 (JavaScript ガイド)


ビット論理積代入 (&=) - JavaScript

ビット論理積代入 (&=)
=============

**ビット論理積代入 (`&=`)** 演算子は、 2 つのオペランドで論理積を取り、その結果を左オペランドへ代入します。

試してみましょう
--------

構文
--

```js
x &= y
```

解説
--

`x &= y` は `x = x & y` と同等ですが、 `x` は一度しか評価されません。

例
-

### ビット論理積代入の使用

```js
let a = 5;
// 5: 00000000000000000000000000000101
// 2: 00000000000000000000000000000010
a &= 2; // 0

let b = 5n;
b &= 2n; // 0n
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-assignment-operators |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* JavaScript ガイドの代入演算子
* ビット論理積 (`&`)


論理積代入 (&&=) - JavaScript

論理積代入 (&&=)
===========

論理積代入 (`x &&= y`) 演算子は、`x` が真値である場合にのみ代入を行います。

試してみましょう
--------

構文
--

```js
expr1 &&= expr2;
```

解説
--

### 短絡評価 (ショートサーキット)

論理積演算子は左から右に評価され、次のルールを使って短絡評価の可能性があるかどうかテストされます。

`(偽値の式) && expr` は、偽値の式が短絡評価されます。

短絡評価とは、上記の `expr` 部分が**評価されない**ことを意味します。したがって、評価された場合の副作用は発生しません (例えば、`expr` が関数呼び出しである場合、呼び出しは行われません)。

論理積代入も短絡評価されます。これは、`x &&= y` が以下と等価であることを意味します。

```js
x && (x = y);
```

そして、常に代入が行われる以下とは等価ではありません。

```js
x = x && y;
```

例
-

### 論理積代入演算子の使用

```js
let x = 0;
let y = 1;

x &&= 0; // 0
x &&= 1; // 0
y &&= 1; // 1
y &&= 0; // 0
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-assignment-operators |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* 論理積演算子 (&&)
* Null 合体演算子 (`??`)
* ビット論理積代入 (`&=`)
* 真値
* 偽値


new.target - JavaScript

new.target
==========

**`new.target`** は擬似プロパティで、関数やコンストラクターが new 演算子を使用して呼び出されたかどうかを検出することができます。 new 演算子を使用して呼び出されたコンストラクターや関数の中では、 `new.target` はコンストラクターや関数への参照を返します。通常の関数呼び出しの場合、 `new.target` は `undefined` になります。

試してみましょう
--------

構文
--

```js
new.target;
```

解説
--

`new.target` の構文は、`new` キーワードとドット、 `target` 識別子で構成されています。通常、ドットの左側はプロパティアクセスが行われるオブジェクトですが、ここでの `new` はオブジェクトではありません。

`new.target` は、すべての関数で使用できる擬似プロパティです。

クラスのコンストラクターでは、構築されたクラスを参照します。

通常の関数では、new 演算子を介して呼び出されたと仮定して、関数自体を参照します。それ以外の場合、`new.target` は `undefined` になります。

アロー関数では、`new.target` は周囲のスコープから継承されます。

例
-

### 関数呼び出しにおける new.target の使用

通常の関数呼び出しでは (コンストラクター関数の呼び出しとは対照的に)、 `new.target` は `undefined` になります。これにより、関数が new でコンストラクターとして呼び出されたかを検出できます。

```js
function Foo() {
  if (!new.target) {
    throw "Foo() must be called with new";
  }
  console.log("Foo instantiated with new");
}

new Foo(); // "Foo instantiated with new" を出力
Foo(); // "Foo() must be called with new" 例外が発生
```

### コンストラクターにおける new.target

クラスのコンストラクターでは、`new.target` は `new` で直接実行されたコンストラクターを参照します。これは、コンストラクターが親クラスにあり、子コンストラクターから委任された場合も同様です。

```js
class A {
  constructor() {
    console.log(new.target.name);
  }
}

class B extends A {
  constructor() {
    super();
  }
}

let a = new A(); // logs "A"
let b = new B(); // logs "B"

class C {
  constructor() {
    console.log(new.target);
  }
}
class D extends C {
  constructor() {
    super();
  }
}

let c = new C(); // logs class C{constructor(){console.log(new.target);}}
let d = new D(); // logs class D extends C{constructor(){super();}}
```

上記の `C` および `D` クラスの例から、 `new.target` は初期化されたクラスのクラス定義を指しているように見えます。たとえば、`d` を `new D()` で初期化した場合は、 `D` のクラス定義が出力され、同様に `c` の場合は `C` のクラスが出力されます。

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-built-in-function-objects |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* 関数
* クラス
* `new`
* `this`


不等価 (!=) - JavaScript

不等価 (!=)
========

不等価演算子 (`!=`) は、2 つのオペランドが等しくないことを検査し、論理値で結果を返します。厳密不等価演算子とは異なり、異なる型のオペランドを変換して比較を行おうとします。

試してみましょう
--------

構文
--

```js
x != y;
```

解説
--

不等価演算子は、そのオペランドが等しくないことを検査します。これは等価演算子の逆に当たるので、以下の 2 行は常に同じ結果になります。

```js
x != y;

!(x == y);
```

比較アルゴリズムの詳細については、等価演算子のページを参照して下さい。

等価演算子と同様に、不等価演算子は異なる型のオペランドを変換して比較しようとします。

```js
3 != "3"; // false
```

これを防止し、異なる型が異なる結果を返すようにするには、代わりに厳密不等価演算子を使用してください。

```js
3 !== "3"; // true
```

例
-

### 型変換がない場合の比較

```js
1 != 2; // true
"hello" != "hola"; // true

1 != 1; // false
"hello" != "hello"; // false
```

### 型変換がある場合の比較

```js
"1" != 1; // false
1 != "1"; // false
0 != false; // false
0 != null; // true
0 != undefined; // true
0 != !!null; // false (論理 NOT 演算子を参照)
0 != !!undefined; // false (論理 NOT 演算子を参照)
null != undefined; // false

const number1 = new Number(3);
const number2 = new Number(3);
number1 != 3; // false
number1 != number2; // true
```

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

```js
const object1 = { key: "value" };
const object2 = { key: "value" };

object1 != object2; // true
object2 != object2; // false
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-equality-operators |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* 等価演算子
* 厳密等価演算子
* 厳密不等価演算子


オブジェクト初期化子 - JavaScript

オブジェクト初期化子
==========

オブジェクトは `new Object()`、`Object.create()`、*リテラル*表記法 (*初期化子*表記法) を使用して初期化されます。オブジェクト初期化子はオブジェクトのプロパティ名と関連した値のゼロ以上のペアのリストで、中括弧 (`{}`) で囲まれます。

試してみましょう
--------

構文
--

```js
let o = {};
let o = { a: "foo", b: 42, c: {} };

let a = "foo",
  b = 42,
  c = {};
let o = { a: a, b: b, c: c };

let o = {
  property: function (parameters) {},
  get property() {},
  set property(value) {},
};
```

### ECMAScript 2015 での新しい表記法

これらの表記をサポートするための互換性の表を参照してください。非サポート環境では、これらの表記は、構文エラーにつながります。

```js
// 略記プロパティ名 (ES2015)
let a = "foo",
  b = 42,
  c = {};
let o = { a, b, c };

// 略記メソッド名 (ES2015)
let o = {
  property(parameters) {},
};

// 計算プロパティ名 (ES2015)
let prop = "foo";
let o = {
  [prop]: "hey",
  ["b" + "ar"]: "there",
};
```

解説
--

オブジェクト初期化子は、`Object` の初期化を表す式です。オブジェクトはオブジェクトを表す*プロパティ*で構成されます。オブジェクトプロパティの値は、特定のプリミティブデータ型か他のオブジェクトのどちらかを含みます。

### オブジェクトリテラル表記法 vs JSON

オブジェクトリテラル表記法は **J**ava**S**cript **O**bject **N**otation (JSON) とは異なります。両者は似ていますが、ちがいがあります。

* JSON は、`"property": value` 構文を使用するプロパティ定義*のみ*を許可します。プロパティ名は二重引用符で囲まなければなりません。そして、その定義を略記にすることはできません。
* JSON で値とすることができるのは、文字列、数値、配列、`true`、`false`、`null`、別の (JSON) オブジェクトのみです。
* 関数の値（後述の「メソッド」を参照）は JSON では値を割り当てることができません。
* `Date` のようなオブジェクトは、 `JSON.parse()` の後で文字列になります。
* `JSON.parse()` では計算プロパティ名は拒否され、エラーが発生します。
例
-

### オブジェクトの生成

プロパティを持たない空のオブジェクトは、下記のように中括弧を記述することで生成されます。

```js
let object = {};
```

しかし、*リテラル*記法、*初期化子*記法の利点は、中括弧内にプロパティをもつオブジェクトを簡潔に生成できる点です。 `key: value` の組をカンマで区切ったリストで記述することができます。

以下のコードでは、 `"foo"`、`"age"`、`"baz"` の 3 つのプロパティをもつオブジェクトを生成します。これらのキーの値はそれぞれ、文字列の `"bar"`、数値の `42`、そして他のオブジェクトです。

```js
let object = {
  foo: "bar",
  age: 42,
  baz: { myProp: 12 },
};
```

### プロパティへのアクセス

オブジェクトを生成すると、読み取ったり変更したりしたくなるでしょう。オブジェクトのプロパティには、ドット記法またはブラケット記法でアクセスすることができます。（詳細については、プロパティへのアクセスをご覧ください。）

```js
object.foo; // "bar"
object["age"]; // 42
object.baz; // {myProp: 12}
object.baz.myProp; //12
```

### プロパティの定義

初期化構文を使用してプロパティを記述する方法について既に学びました。多くの場合、コード内には、オブジェクトに設定したい変数があります。下記のコードをご覧ください。

```js
let a = "foo",
  b = 42,
  c = {};

let o = {
  a: a,
  b: b,
  c: c,
};
```

ECMAScript 2015 では、同じことを実現するために利用できる短い記法があります。

```js
let a = "foo",
  b = 42,
  c = {};

// 略記プロパティ名 (ES2015)
let o = { a, b, c };

// In other words,
console.log(o.a === { a }.a); // true
```

#### 重複したプロパティ名

プロパティに対して同じ名前を使用するとき、二番目のプロパティは最初のプロパティを上書きします。

```js
let a = { x: 1, x: 2 };
console.log(a); // {x: 2}
```

ECMAScript 5 の厳格モードのコードでは、重複したプロパティの名前は `SyntaxError` とみなされます。実行時に重複を可能にする計算プロパティ名の導入により、 ECMAScript 2015 ではこの制限は取り除かれました。

```js
function haveES2015DuplicatePropertySemantics() {
  "use strict";
  try {
    ({ prop: 1, prop: 2 });

    // 厳格モードで重複するプロパティ名が許可されているため、エラーが発生しない場合。
    return true;
  } catch (e) {
    // 厳格モードで重複が禁止されているため、エラーが発生する場合。
    return false;
  }
}
```

### メソッドの定義

オブジェクトのプロパティは関数、ゲッターメソッド、セッターメソッドも参照することができます。

```js
let o = {
  property: function (parameters) {},
  get property() {},
  set property(value) {},
};
```

ECMAScript 2015 では、略記法が利用可能ですので、キーワード "`function`" は必要なくなりました。

```js
// メソッド名の略記法 (ES2015)
let o = {
  property(parameters) {},
};
```

ECMAScript 2015 では、ジェネレーター関数であるプロパティを簡潔に定義する方法があります。

```js
let o = {
  \*generator() {
    ...........
  }
};
```

ECMAScript 5 では、下記のように記述します（ただし、 ES5 にはジェネレーターがないことに注意してください）。

```js
let o = {
  generator: function\* () {
    ...........
  }
};
```

メソッドの詳細や例については、メソッド定義をご覧ください。

### 計算プロパティ名

ECMAScript 2015 から、オブジェクト初期化子構文でも、計算プロパティ名に対応します。括弧 `[]` の中に式を記述することができ、それが計算されてプロパティ名として使用されます。これは、プロパティの読み込みと設定に使用したことのある、プロパティアクセサー構文のブラケット表記を彷彿とさせるものです。

今では、オブジェクトリテラルでも同様な構文を使うことができます。

```js
// Computed property names (ES2015)
let i = 0;
let a = {
  ["foo" + ++i]: i,
  ["foo" + ++i]: i,
  ["foo" + ++i]: i,
};

console.log(a.foo1); // 1
console.log(a.foo2); // 2
console.log(a.foo3); // 3

const items = ["A", "B", "C"];
const obj = {
  [items]: "Hello",
};
console.log(obj); // A,B,C: "Hello"
console.log(obj["A,B,C"]); // "Hello"

let param = "size";
let config = {
  [param]: 12,
  ["mobile" + param.charAt(0).toUpperCase() + param.slice(1)]: 4,
};

console.log(config); // {size: 12, mobileSize: 4}
```

### スプレッドプロパティ

ECMAScript proposal の Rest/Spread プロパティ （ステージ 4） では、オブジェクトリテラルにスプレッドプロパティを追加します。 渡されたオブジェクトから新しいオブジェクトに独自の列挙可能なプロパティをコピーします。

`Object.assign()` を使うよりも短いコードで `prototype` を除いた浅いコピーの作成や、マージしたオブジェクトの作成を書くことができます。

```js
let obj1 = { foo: "bar", x: 42 };
let obj2 = { foo: "baz", y: 13 };

let clonedObj = { ...obj1 };
// Object { foo: "bar", x: 42 }

let mergedObj = { ...obj1, ...obj2 };
// Object { foo: "baz", x: 42, y: 13 }
```

**警告:** `Object.assign()` はセッターを起動しますが、スプレッド構文は起動しません。

### プロトタイプの変更

`__proto__: value` 形式、または `"__proto__": value` 形式でプロパティを定義しても、 `__proto__` という名をもつプロパティを生成しません。代わりに、与えられた値がオブジェクトまたは `null` の場合、その値に生成されたオブジェクトの `[[Prototype]]` を変更します（その値がオブジェクト、または null ではない場合、オブジェクトは変更されません）。

```js
let obj1 = {};
assert(Object.getPrototypeOf(obj1) === Object.prototype);

let obj2 = { \_\_proto\_\_: null };
assert(Object.getPrototypeOf(obj2) === null);

let protoObj = {};
let obj3 = { \_\_proto\_\_: protoObj };
assert(Object.getPrototypeOf(obj3) === protoObj);

let obj4 = { \_\_proto\_\_: "not an object or null" };
assert(Object.getPrototypeOf(obj4) === Object.prototype);
assert(!obj4.hasOwnProperty("\_\_proto\_\_"));
```

オブジェクトリテラルでは、単一のプロトタイプの変更のみが許可されています。すなわち、複数のプロトタイプを変更すると構文エラーになります。

「コロン」表記法を使用しないプロパティ定義は、プロトタイプの変更にはなりません。任意の他の名称を使用する同様の定義と同じように動作するプロパティ定義です。

```js
let __proto__ = "variable";

let obj1 = { __proto__ };
assert(Object.getPrototypeOf(obj1) === Object.prototype);
assert(obj1.hasOwnProperty("\_\_proto\_\_"));
assert(obj1.__proto__ === "variable");

let obj2 = {
  \_\_proto\_\_() {
    return "hello";
  },
};
assert(obj2.\_\_proto\_\_() === "hello");

let obj3 = { ["\_\_prot" + "o\_\_"]: 17 };
assert(obj3.__proto__ === 17);
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-object-initializer |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* メンバー演算子
* `get` / `set`
* メソッド定義
* 字句文法