diff --git a/files/ja/_redirects.txt b/files/ja/_redirects.txt index e0e316c754739d..3179efb3068144 100644 --- a/files/ja/_redirects.txt +++ b/files/ja/_redirects.txt @@ -3374,8 +3374,11 @@ /ja/docs/Web/API/isSecureContext /ja/docs/Web/API/Window/isSecureContext /ja/docs/Web/API/origin /ja/docs/Web/API/Window/origin /ja/docs/Web/API/performance_property /ja/docs/Web/API/Window/performance +/ja/docs/Web/API/queueMicrotask /ja/docs/Web/API/Window/queueMicrotask /ja/docs/Web/API/range.intersectsNode /ja/docs/Web/API/Range/intersectsNode /ja/docs/Web/API/range.setStart /ja/docs/Web/API/Range/setStart +/ja/docs/Web/API/reportError /ja/docs/Web/API/Window/reportError +/ja/docs/Web/API/structuredClone /ja/docs/Web/API/Window/structuredClone /ja/docs/Web/API/tableRow.insertCell /ja/docs/Web/API/HTMLTableRowElement/insertCell /ja/docs/Web/API/tableRow.rowIndex /ja/docs/Web/API/HTMLTableRowElement/rowIndex /ja/docs/Web/API/window.URL /ja/docs/Web/API/URL diff --git a/files/ja/web/api/domtokenlist/item/index.md b/files/ja/web/api/domtokenlist/item/index.md index 19d27b9ae6cece..c6c2e3955d8530 100644 --- a/files/ja/web/api/domtokenlist/item/index.md +++ b/files/ja/web/api/domtokenlist/item/index.md @@ -11,7 +11,7 @@ l10n: **`item()`** は {{domxref("DOMTokenList")}} インターフェイスのメソッドで、リスト内の項目をその位置から取得します。 > [!NOTE] -> このメソッドは[ブラケット記法](/ja/docs/Web/JavaScript/Reference/Operators/Property_accessors#ブラケット表記法)と等価です。 +> このメソッドは[ブラケット記法](/ja/docs/Web/JavaScript/Reference/Operators/Property_accessors#ブラケット記法)と等価です。 > したがって、 `aList.item(i)` は `aList[i]` と同じです。 ## 構文 diff --git a/files/ja/web/api/setinterval/index.md b/files/ja/web/api/setinterval/index.md index 7032fe289170f1..bd46d77512bc96 100644 --- a/files/ja/web/api/setinterval/index.md +++ b/files/ja/web/api/setinterval/index.md @@ -1,13 +1,14 @@ --- -title: setInterval() +title: setInterval() グローバル関数 +short-title: setInterval() slug: Web/API/setInterval l10n: - sourceCommit: c8485a8f94319d289a8892fd261d2fe38b623aa0 + sourceCommit: bb48907e64eb4bf60f17efd7d39b46c771d220a0 --- -{{APIRef("HTML DOM")}} +{{APIRef("HTML DOM")}}{{AvailableInWorkers}} -**`setInterval()`** メソッドは {{domxref("Window")}} および {{domxref("Worker")}} メソッドで提供され、一定の遅延間隔を置いて関数やコードスニペットを繰り返し呼び出します。 +**`setInterval()`** メソッドは {{domxref("Window")}} および {{domxref("WorkerGlobalScope")}} インターフェイスで提供され、一定の遅延間隔を置いて関数やコードスニペットを繰り返し呼び出します。 このメソッド、インターバルを一意に識別するインターバル ID を返します。よって {{domxref("clearInterval", "clearInterval()")}} を呼び出して、後でインターバルを削除できます。 @@ -19,9 +20,9 @@ setInterval(code, delay) setInterval(func) setInterval(func, delay) -setInterval(func, delay, arg0) -setInterval(func, delay, arg0, arg1) -setInterval(func, delay, arg0, arg1, /* … ,*/ argN) +setInterval(func, delay, arg1) +setInterval(func, delay, arg1, arg2) +setInterval(func, delay, arg1, arg2, /* …, */ argN) ``` ### 引数 @@ -29,20 +30,24 @@ setInterval(func, delay, arg0, arg1, /* … ,*/ argN) - `func` - : `delay` ミリ秒が経過するたびに実行する{{jsxref("function", "関数")}}です。最初の実行は `delay` ミリ秒後に行われます。 - `code` - - : 関数の代わりに文字列を含める構文も許容されており、 `delay` ミリ秒が経過するたびに文字列をコンパイルして実行します。 {{jsxref("Global_Objects/eval", "eval()")}} の使用にリスクがあるのと同じ理由で、この構文は**推奨しません**。 + - : 関数の代わりに文字列を含める構文も許容されており、 `delay` ミリ秒が経過するたびに文字列をコンパイルして実行します。 + この構文は**推奨しません**。{{jsxref("Global_Objects/eval", "eval()")}} の使用にセキュリティ上のリスクがあるのと同じ理由です。 - `delay` {{optional_inline}} - - : 指定した関数またはコードを実行する前にタイマーが待つべき時間をミリ秒 (1/1000 秒) 単位で指定します。引数が 10 より小さい場合は、10 を使用します。実際の遅延が長くなることがあります。例えば[遅延の制約](#遅延の制約)をご覧ください。 -- `arg0, …, argN` {{optional_inline}} + - : 指定した関数またはコードを実行する前にタイマーが待つべき時間をミリ秒 (1/1000 秒) 単位で指定します。指定されなかった場合の既定値は 0 です。 + `delay` 値で許される範囲についての詳細は、[遅延の制約](#遅延の制約)をご覧ください。 +- `arg1`, …, `argN` {{optional_inline}} - : タイマーが満了したときに、 _func_ で指定した関数に渡す追加の引数です。 ### 返値 返値 `intervalID` は 0 ではない正の整数値で、 `setInterval()` を呼び出して作成したタイマーを識別します。この値を {{domxref("clearInterval()")}} へ渡せば、インターバルを取り消すことができます。 -`setInterval()` と {{domxref("setTimeout()")}} は同じ ID プールを共有しており、 `clearInterval()` と {{domxref("clearTimeout", "clearTimeout()")}} は技術的に入れ替えて使用できることを意識すると役に立つでしょう。ただし明快さのために、コードを整備するときは混乱を避けるため、常に一致させるようにするべきです。 +`setInterval()` と {{domxref("setTimeout()")}} は同じ ID プールを共有しており、 `clearInterval()` と {{domxref("clearTimeout", "clearTimeout()")}} は技術的に入れ替えて使用できることを意識すると役に立つでしょう。 +ただし明快さのために、コードを整備するときは混乱を避けるため、常に一致させるようにするべきです。 > [!NOTE] -> 引数 `delay` は、符号付き 32 ビット整数に変換されます。 IDL における符号付き整数の定義によって、`delay` は事実上 2147483647ms に制限されます。 +> 引数 `delay` は、符号付き 32 ビット整数に変換されます。 +> IDL における符号付き整数の定義によって、`delay` は事実上 2147483647ms に制限されます。 ## 例 @@ -122,7 +127,8 @@ document.getElementById("stop").addEventListener("click", stopTextColor); ## "this" 問題 -`setInterval()` に(もっと言うと他のどんな関数でも)メソッドを渡すと、間違った [`this`](/ja/docs/Web/JavaScript/Reference/Operators/this) の値で呼び出されることがあります。この問題は [JavaScript リファレンス](/ja/docs/Web/JavaScript/Reference/Operators/this#オブジェクトのメソッドとして)で詳しく説明しています。 +`setInterval()` に(もっと言うと他のどんな関数でも)メソッドを渡すと、間違った [`this`](/ja/docs/Web/JavaScript/Reference/Operators/this) の値で呼び出されることがあります。 +この問題は [JavaScript リファレンス](/ja/docs/Web/JavaScript/Reference/Operators/this#コールバック)で詳しく説明しています。 ### 解説 @@ -139,10 +145,11 @@ myArray.myMethod(); // "zero,one,two" と表示 myArray.myMethod(1); // "one" と表示 setTimeout(myArray.myMethod, 1000); // "[object Window]" と 1 秒後に表示 setTimeout(myArray.myMethod, 1500, "1"); // "undefined" と 1.5 秒後に表示 -// passing the 'this' object with .call won't work + +// Passing the 'this' object with .call won't work // because this will change the value of this inside setTimeout itself -// while we want to change the value of this inside myArray.myMethod -// in fact, it will be an error because setTimeout code expects this to be the window object: +// while we want to change the value of this inside myArray.myMethod. +// In fact, it will be an error because setTimeout code expects this to be the window object: setTimeout.call(myArray, myArray.myMethod, 2000); // エラー: "NS_ERROR_XPC_BAD_OP_ON_WN_PROTO: Illegal operation on WrappedNative prototype object" setTimeout.call(myArray, myArray.myMethod, 2500, 2); // 同じエラー ``` @@ -196,7 +203,7 @@ IE に対応する必要がある場合は、[`Function.prototype.bind()`](/ja/d ## 関連情報 - [core-js にある `setInterval` のポリフィルで、コールバックに引数を渡すことができるもの](https://github.com/zloirock/core-js#settimeout-and-setinterval) -- {{domxref("setTimeout")}} -- {{domxref("clearTimeout")}} -- {{domxref("clearInterval")}} -- {{domxref("window.requestAnimationFrame")}} +- {{domxref("setTimeout()")}} +- {{domxref("clearTimeout()")}} +- {{domxref("clearInterval()")}} +- {{domxref("window.requestAnimationFrame()")}} diff --git a/files/ja/web/api/settimeout/index.md b/files/ja/web/api/settimeout/index.md index 2087794e2fec07..1e92b92e070af4 100644 --- a/files/ja/web/api/settimeout/index.md +++ b/files/ja/web/api/settimeout/index.md @@ -1,11 +1,12 @@ --- -title: setTimeout() +title: setTimeout() グローバル関数 +short-title: setTimeout() slug: Web/API/setTimeout l10n: - sourceCommit: c09b8e9dd0022a33cf84355704ca281d6a5f29f5 + sourceCommit: 8acf54a3eb1536134a39896c3ceb1578f9b4eea7 --- -{{APIRef("HTML DOM")}} +{{APIRef("HTML DOM")}}{{AvailableInWorkers}} グローバルの **`setTimeout()`** メソッドは、時間切れになると関数または指定されたコードの断片を実行するタイマーを設定します。 @@ -19,7 +20,7 @@ setTimeout(functionRef) setTimeout(functionRef, delay) setTimeout(functionRef, delay, param1) setTimeout(functionRef, delay, param1, param2) -setTimeout(functionRef, delay, param1, param2, /* … ,*/ paramN) +setTimeout(functionRef, delay, param1, param2, /* …, */ paramN) ``` ### 引数 @@ -44,11 +45,11 @@ setTimeout(functionRef, delay, param1, param2, /* … ,*/ paramN) 返される `timeoutID` は正の整数値で、 `setTimeout()` を呼び出して作成したタイマーを識別します。この値を {{domxref("clearTimeout","clearTimeout()")}} へ渡すことで、タイムアウトを取り消すことができます。 -`timeoutID` の値は、同じオブジェクト (ウィンドウやワーカー) において、後に `setTimeout()` や `setInterval()` を呼び出しても再使用されないことが保証されています。ただし、別なオブジェクトでは別の ID プールを使用します。 +`timeoutID` の値は、同じオブジェクト(ウィンドウやワーカー)においてタイマーが有効な間、後に `setTimeout()` や `setInterval()` を呼び出しても再使用されないことが保証されています。ただし、別なオブジェクトでは別の ID プールを使用します。 ## 解説 -タイムアウトは、 {{domxref("clearTimeout()")}} を使用して取り消すことができます。 +タイムアウトは、{{domxref("clearTimeout()")}} を使用して取り消すことができます。 関数を繰り返して(例えば _N_ ミリ秒ごとに)呼び出すには、 {{domxref("setInterval()")}} を使用することを検討してください。 @@ -62,7 +63,7 @@ setTimeout(() => { }, "1000"); ``` -しかし、多くの場合、暗黙の型強制は予期しない、驚くべき結果をもたらす可能性があります。例えば、以下のコードを実行すると、文字列 `"1 second"` は最終的に数字 `0` に強制され、その結果、コードは遅延ゼロで直ちに実行されます。 +しかし、多くの場合、暗黙の型強制は予期しない、驚くべき結果をもたらす可能性があります。例えば、以下のコードを実行すると、文字列 `"1 second"` は最終的に数字 `0` に変換され、その結果、コードは遅延ゼロで直ちに実行されます。 ```js example-bad setTimeout(() => { @@ -109,9 +110,9 @@ setTimeout(() => { ### "this" の問題 -`setTimeout()` にメソッドを渡すと、 `this` が期待とは異なる値で起動されることがあります。一般的な問題は [JavaScript リファレンス](/ja/docs/Web/JavaScript/Reference/Operators/this#オブジェクトのメソッドとして)で詳細に説明されています。 +`setTimeout()` にメソッドを渡すと、 `this` が期待とは異なる値で起動されることがあります。一般的な問題は [JavaScript リファレンス](/ja/docs/Web/JavaScript/Reference/Operators/this#コールバック)で詳細に説明されています。 -`setTimeout()` によって実行されるコードは、 `setTimeout` が呼び出された関数とは別の実行コンテキスト内から呼び出されます。呼び出された関数に `this` キーワードを設定する通常の規則を適用して、呼び出しあるいは `bind` で `this` を設定しなければ、厳格モードでなければ `global` (または `window`)、厳格モードでは undefined になります。これは、 `setTimeout` が呼び出された関数の `this` 値と同じにはなりません。 +`setTimeout()` によって実行されるコードは、`setTimeout` が呼び出された関数とは別の実行コンテキストから呼び出されます。呼び出された関数で `this` キーワードを設定する際の通常のルールが適用され、`this` を呼び出し時に設定していない場合、または `bind` で設定していない場合、`window`(または `global` )オブジェクトが既定で使用されます。これは、[厳格モード](/ja/docs/Web/JavaScript/Reference/Strict_mode)であっても同様です。これは、`setTimeout` を呼び出した関数の `this` の値と同じではありません。 以下の例をご覧ください。 @@ -199,7 +200,7 @@ setTimeout(() => { }, 500); ``` -{{domxref("setTimeout()")}} に渡した文字列はグローバルコンテキストで評価されます。そのため、{{domxref("setTimeout()")}} が呼び出されたコンテキストのローカルシンボルは、文字列を評価したコードからは利用できません。 +`setTimeout()` に渡した文字列はグローバルコンテキストで評価されます。そのため、`setTimeout()` が呼び出されたコンテキストのローカルシンボルは、文字列を評価したコードからは利用できません。 ### 遅延が指定値より長い理由 @@ -212,9 +213,17 @@ setTimeout(() => { この例では、 `setTimeout` の呼び出しを `0` ミリ秒の遅延でネストし、ハンドラーが呼び出されるたびに遅延時間を記録しています。最初の 4 回は遅延が約 0 ミリ秒、その後は約 4 ミリ秒になります。 ```html - -
previous this actual delay- + +
前回 | +今回 | +実際の遅延 | +
---|
コールバックを使う場合や、オブジェクトからメソッドを分割代入を利用して取り出す場合に、存在しない値がある可能性があり、その存在を検証するまで関数として呼び出せません。その場合 `?.` を利用することで、検証の必要性を回避できます。 +[ブラケット記法](/ja/docs/Web/JavaScript/Reference/Operators/Property_accessors#ブラケット記法)を使用して式のプロパティにアクセスする際にも、オプショナルチェーン演算子を使用することができます。 ```js -// Written as of ES2019 -function doSomething(onContent, onError) { - try { - // ... do something with the data - } catch (err) { - if (onError) { - // Testing if onError really exists - onError(err.message); - } - } -} +const nestedProp = obj?.["prop" + "Name"]; ``` +これは配列の添字でアクセスする際に角括弧を使用する必要があるため、配列に対して特に有益な機能です。 + ```js -// Using optional chaining with function calls -function doSomething(onContent, onError) { - try { - // ... do something with the data - } catch (err) { - onError?.(err.message); // no exception if onError is undefined - } +function printMagicIndex(arr) { + console.log(arr?.[42]); } + +printMagicIndex([0, 1, 2, 3, 4, 5]); // undefined +printMagicIndex(); // undefined; if not using ?., this would throw an error: "Cannot read properties of undefined (reading '42')" ``` -### オプショナルチェーン演算子と式の組み合わせ +### 無効なオプショナルチェーン + +オプショナルチェーン式の評価結果に値を代入しようとすることは不正な処理です。 + +```js-nolint example-bad +const object = {}; +object?.property = 1; // SyntaxError: Invalid left-hand side in assignment +``` + +[テンプレートリテラルタグ](/ja/docs/Web/JavaScript/Reference/Template_literals#tagged_templates)はオプションチェーンにはできません([SyntaxError: tagged template cannot be used with optional chain](/ja/docs/Web/JavaScript/Reference/Errors/Bad_optional_template)を参照)。 + +```js-nolint example-bad +String?.raw`Hello, world!`; +String.raw?.`Hello, world!`; // SyntaxError: Invalid tagged template on optional chain +``` + +{{jsxref("Operators/new", "new")}} 式のコンストラクターはオプションチェーンを使用できません([SyntaxError: new keyword cannot be used with an optional chain](/ja/docs/Web/JavaScript/Reference/Errors/Bad_new_optional) を参照)。 -[プロパティアクセサーのブラケット表記法](/ja/docs/Web/JavaScript/Reference/Operators/Property_Accessors#bracket_notation)を使用している式のプロパティにアクセスする際にも、オプショナルチェーン演算子を使用することができます。 +```js-nolint example-bad +new Intl?.DateTimeFormat(); // SyntaxError: Invalid optional chain from new expression +new Map?.(); +``` + +### 短絡評価 + +オプションチェーン式を使用する場合、左オペランドが `null` または `undefined` の場合、その式は評価されません。例えば次のようになります。 + +```js +const potentiallyNullObj = null; +let x = 0; +const prop = potentiallyNullObj?.[x++]; + +console.log(x); // x がインクリメントされていないので 0 +``` + +その後のプロパティへのアクセスも評価されません。 + +```js +const potentiallyNullObj = null; +const prop = potentiallyNullObj?.a.b; +// これはエラーを発生しません。最初のオプションチェーンで評価がすでに停止しているためです。 +``` + +これは下記のものと等価です。 ```js -let nestedProp = obj?.["prop" + "Name"]; +const potentiallyNullObj = null; +const prop = + potentiallyNullObj === null || potentiallyNullObj === undefined + ? undefined + : potentiallyNullObj.a.b; ``` -### オプショナルチェーン演算子は代入の左辺値では使用できない +ただし、この短絡評価の動作は、プロパティにアクセスする一連の「チェーン」を連続して行う場合のみ発生します。 チェーンの一部を[グループ化](/ja/docs/Web/JavaScript/Reference/Operators/Grouping)しても、その後のプロパティへのアクセスは引き続き評価されます。 ```js -let object = {}; -object?.property = 1; // Uncaught SyntaxError: Invalid left-hand side in assignment +const potentiallyNullObj = null; +const prop = (potentiallyNullObj?.a).b; +// TypeError: Cannot read properties of undefined (reading 'b') ``` -### オプショナルチェーンによる配列要素へのアクセス +これは下記のものと等価です。 ```js -let arrayItem = arr?.[42]; +const potentiallyNullObj = null; +const temp = potentiallyNullObj?.a; +const prop = temp.b; ``` +ただし、`temp` 変数は作成されません。 + ## 例 ### 基本的な例 @@ -125,22 +172,39 @@ let arrayItem = arr?.[42]; 次の例では、マップに存在しない `bar` メンバの `name` プロパティを取得しようとしています。したがって、結果は `undefined` になります。 ```js -let myMap = new Map(); +const myMap = new Map(); myMap.set("foo", { name: "baz", desc: "inga" }); -let nameBar = myMap.get("bar")?.name; +const nameBar = myMap.get("bar")?.name; ``` -### 短絡評価 +### オプションのコールバックやイベントハンドラーの扱い -式と一緒にオプショナルチェーン演算子を用いたとき、左側のオペランドが `null` または `undefined` である場合、その式は評価されなくなります。 +コールバックやオブジェクトからフェッチメソッドを[分割代入](/ja/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#オブジェクトの分割代入)で使用する場合、存在しない値を持つことができるため、その存在をテストしない限り、その値を関数として呼び出すことはできません。`?.` を使用すると、この余分なテストを避けることができます。 ```js -let potentiallyNullObj = null; -let x = 0; -let prop = potentiallyNullObj?.[x++]; +// オプショナルチェーンなしで書かれたコード +function doSomething(onContent, onError) { + try { + // データで何かを行う + } catch (err) { + // onError が本当に存在するかどうかを確認 + if (onError) { + onError(err.message); + } + } +} +``` -console.log(x); // 0 となる。 x は加算されていない +```js +// 関数呼び出しでオプショナルチェーンを使用 +function doSomething(onContent, onError) { + try { + // データで何かを行う + } catch (err) { + onError?.(err.message); // onError が定義されていない場合は例外なし + } +} ``` ### オプショナルチェーンをつなげて使う @@ -148,30 +212,37 @@ console.log(x); // 0 となる。 x は加算されていない 入れ子になったオブジェクトでは、オプショナルチェーン演算子を何度でも使うことができます。 ```js -let customer = { +const customer = { name: "Carl", details: { age: 82, location: "Paradise Falls", // 詳細な住所は不明 }, }; -let customerCity = customer.details?.address?.city; +const customerCity = customer.details?.address?.city; // … これはオプショナルチェーンの関数呼び出しでも動作します -let customerName = customer.name?.getName?.(); // メソッドが存在しないので、 customerName は undefined +const customerName = customer.name?.getName?.(); // メソッドが存在しないので、 customerName は undefined ``` ### Null 合体演算子と共に使う -{{JSxRef("Operators/Nullish_Coalescing_Operator", "Null 合体演算子", '', 1)}}はオプショナルチェーンの後につけることで、値が存在しなかったときの既定値を指定することができます。 +[Null 合体演算子](/ja/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing)をオプショナルチェーンの後につけることで、値が存在しなかったときの既定値を指定することができます。 ```js -let customer = { +function printCustomerCity(customer) { + const customerCity = customer?.city ?? "Unknown city"; + console.log(customerCity); +} + +printCustomerCity({ + name: "Nathan", + city: "Paris", +}); // "Paris" +printCustomerCity({ name: "Carl", details: { age: 82 }, -}; -const customerCity = customer?.city ?? "Unknown city"; -console.log(customerCity); // Unknown city +}); // "Unknown city" ``` ## 仕様書 @@ -184,4 +255,4 @@ console.log(customerCity); // Unknown city ## 関連情報 -- {{JSxRef("Operators/Nullish_Coalescing_Operator", "Null 合体演算子", '', 1)}} +- [Null 合体演算子 (`??`)](/ja/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing) diff --git a/files/ja/web/javascript/reference/operators/property_accessors/index.md b/files/ja/web/javascript/reference/operators/property_accessors/index.md index 1cef1dec18ba9d..be3face311305c 100644 --- a/files/ja/web/javascript/reference/operators/property_accessors/index.md +++ b/files/ja/web/javascript/reference/operators/property_accessors/index.md @@ -1,47 +1,49 @@ --- title: プロパティアクセサー slug: Web/JavaScript/Reference/Operators/Property_accessors +l10n: + sourceCommit: 387d0d4d8690c0d2c9db1b85eae28ffea0f3ac1f --- {{jsSidebar("Operators")}} -**プロパティアクセサー**はオブジェクトのプロパティへのアクセスを提供するもので、ドット表記法またはブラケット表記法を使用します。 +**プロパティアクセサー**はオブジェクトのプロパティへのアクセスを提供するもので、ドット記法またはブラケット記法を使用します。 {{EmbedInteractiveExample("pages/js/expressions-propertyaccessors.html", "taller")}} ## 構文 -```js -object.property; -object["property"]; +```js-nolint +object.propertyName +object[expression] +object.#privateProperty ``` ## 解説 -オブジェクトは実際には*連想配列* (別名 _map_、 _dictionary_、 _hash_、 _lookup table_) とみなすことができます。この配列における*キー*はオブジェクトのプロパティ名です。 - -一般的に、オブジェクトのプロパティについて説明する際には、プロパティとメソッドを区別します。しかし、プロパティとメソッドの区別は慣習的なものにすぎません。メソッドは呼び出すことができるプロパティです (例えば、値として {{jsxref("Function")}} インスタンスへの参照を持っているようなものです)。 +オブジェクトは実際には*連想配列*(別名 _map_、 _dictionary_、 _hash_、 _lookup table_)とみなすことができます。この配列における*キー*はオブジェクトの[プロパティ](/ja/docs/Glossary/Property/JavaScript)の名前です。 -プロパティにアクセスするには、*ドット表記法*と*ブラケット表記法*の 2 通りがあります。 +プロパティにアクセスするには、*ドット記法*と*ブラケット記法*の 2 通りがあります。 -### ドット表記法 +### ドット記法 -`object.property` の構文では、 `property` は有効な JavaScript の [識別子](/ja/docs/Glossary/Identifier)でなければなりません。 (ECMAScript 標準では、プロパティの名前は技術的には "IdentifierNames" であり、 "Identifiers" ではないので、予約語を使用することができますがお勧めしません)。例えば、 `object.$1` は有効であるのに対し、 `object.1` は有効ではありません。 +`object.propertyName` の構文では、 `propertyName` は有効な JavaScript の [識別子](/ja/docs/Web/JavaScript/Reference/Lexical_grammar#識別子)でなければならず、[予約語](/ja/docs/Web/JavaScript/Reference/Lexical_grammar#キーワード)であっても構いません。例えば、 `object.$1` は有効であるのに対し、 `object.1` は有効ではありません。 ```js -const variable = object.property_name; - -object.property_name = value; +const variable = object.propertyName; +object.propertyName = value; ``` ```js const object = {}; +object.$1 = "foo"; +console.log(object.$1); // 'foo' +``` -object.$1 = 'foo'; -console.log(object.$1); // 'foo' - -object.1 = 'bar'; // SyntaxError -console.log(object.1); // SyntaxError +```js-nolint example-bad +const object = {}; +object.1 = 'bar'; // SyntaxError +console.log(object.1); // SyntaxError ``` ここで、 `createElement` というメソッドを `document` から取得し、呼び出します。 @@ -66,13 +68,15 @@ document.createElement("pre"); // 77.と77.0は同じものとして評価されます ``` -### ブラケット表記法 +さらに、[プライベートプロパティ](/ja/docs/Web/JavaScript/Reference/Classes/Private_properties)は、それを定義するクラス内でドット記法を使用してのみアクセスすることができます。 -`object[property_name]` の構文では、 `property_name` は文字列または[シンボル](/ja/docs/Glossary/Symbol)です。ですから、これは任意の文字列、例えば `'1foo'`、`'!bar!'`、または `' '` (空白) であっても構いません。 +### ブラケット記法 + +`object[expression]` の構文では、`expression` は文字列または[シンボル](/ja/docs/Web/JavaScript/Reference/Global_Objects/Symbol)です。ですから、これは任意の文字列、例えば `'1foo'`、`'!bar!'`、または `' '` (空白) であっても構いません。 ```js -const variable = object[property_name]; -object[property_name] = value; +const variable = object[propertyName]; +object[propertyName] = value; ``` これは前の例とまったく同じです。 @@ -81,18 +85,32 @@ object[property_name] = value; document["createElement"]("pre"); ``` -ブラケット表記法の前には空白を入れることができます。 +ブラケット記法の前には空白を入れることができます。 ```js-nolint document ["createElement"]("pre"); ``` +プロパティ名として評価される式を渡すと、プロパティ名を直に直接渡すのと同じことが行われます。 + +```js +const key = "name"; +const getKey = () => "name"; +const Obj = { name: "Michel" }; + +Obj["name"]; // "Michel" を返す +Obj[key]; // Obj["name"] と解釈され、 "Michel" を返す +Obj[getKey()]; // Obj["name"] と解釈され、 "Michel" を返す +``` + +ただし、外部入力で指定された名前のプロパティにアクセスするために角括弧を使用することには注意が必要です。これにより、コードが[オブジェクトインジェクション攻撃](https://github.com/eslint-community/eslint-plugin-security/blob/main/docs/the-dangers-of-square-bracket-notation.md)を許しやすくなる可能性があります。 + ### プロパティ名 -プロパティ名は文字列または[シンボル](/ja/docs/Glossary/Symbol)です。それ以外の値は、数値を含めて、文字列へ強制変換されます。これは `'value'` を出力します。 `1` が `'1'` に強制変換されるからです。 +プロパティ名は文字列または[シンボル](/ja/docs/Web/JavaScript/Reference/Global_Objects/Symbol)です。それ以外の値は、数値を含めて、文字列へ強制変換されます。これは `'value'` を出力します。 `1` が `'1'` に強制変換されるからです。 ```js -let object = {}; +const object = {}; object["1"] = "value"; console.log(object[1]); ``` @@ -100,35 +118,35 @@ console.log(object[1]); こちらも `'value'` を出力します。`foo` と `bar` は同じ文字列に変換されるからです。 ```js -let foo = { unique_prop: 1 }, - bar = { unique_prop: 2 }, - object = {}; +const foo = { uniqueProp: 1 }; +const bar = { uniqueProp: 2 }; +const object = {}; object[foo] = "value"; console.log(object[bar]); ``` -[SpiderMonkey](/ja/docs/Mozilla/Projects/SpiderMonkey) JavaScript エンジンでは、この文字列は "`[object Object]`" となります。 - ### メソッドのバインド -メソッドは、そのメソッドが所属するオブジェクトにバインドされているわけではありません。特に、 `this` はメソッド内で固定されていません。つまり、 `this` は必ずしもそのメソッドを含んでいるオブジェクトを参照しているとは限りません。 `this` は関数呼び出し時に「渡される」ものです。[メソッドのバインド](/ja/docs/Web/JavaScript/Reference/Operators/this#method_binding)を参照してください。 +オブジェクトのプロパティについて話す場合は、プロパティとメソッドを区別するのが一般的です。しかし、プロパティとメソッドの区別は、単なる慣習にすぎません。メソッドは、呼び出すことができるプロパティです(例えば、{{jsxref("Function")}} インスタンスへの参照を値として保有している場合など)。 + +メソッドは、そのメソッドが所属するオブジェクトにバインドされているわけではありません。特に、 `this` はメソッド内で固定されているわけではなく、必ずしもそのメソッドを含んでいるオブジェクトを参照しているとは限りません。 `this` は関数呼び出し時に「渡される」ものです。[`this` のリファレンス](/ja/docs/Web/JavaScript/Reference/Operators/this)を参照してください。 ## 例 -### ブラケット表記法と `eval` +### ブラケット記法と eval() -JavaScript 初心者はしばしば、代わりにブラケット表記法を使えるところで {{jsxref("eval", "eval()")}} を使用してしまう間違いを犯します。 +JavaScript 初心者はしばしば、代わりにブラケット記法を使えるところで {{jsxref("eval", "eval()")}} を使用してしまう間違いを犯します。 例えば、以下のような構文がたくさんのスクリプトで見られます。 ```js -x = eval("document.forms.form_name.elements." + strFormControl + ".value"); +const x = eval(`document.forms.form_name.elements.${strFormControl}.value`); ``` -`eval()` は低速であり、可能な限り避けるべきです。また、 `strFormControl` は ID を必要としますが、フォームコントロールの名前と `id` は必須ではありません。代わりにブラケット表記法を使った方が良いでしょう。 +`eval()` は低速であり、可能な限り避けるべきです。また、 `strFormControl` は ID を必要としますが、フォームコントロールの名前と `id` は必須ではありません。代わりにブラケット記法を使った方が良いでしょう。 ```js -x = document.forms["form_name"].elements[strFormControl].value; +const x = document.forms.form_name.elements[strFormControl].value; ``` ## 仕様書 @@ -143,4 +161,4 @@ x = document.forms["form_name"].elements[strFormControl].value; - {{jsxref("Object")}} - {{jsxref("Object.defineProperty()")}} -- [オプショナルチェイニング](/ja/docs/Web/JavaScript/Reference/Operators/Optional_chaining) +- [オプショナルチェーン (`?.`)](/ja/docs/Web/JavaScript/Reference/Operators/Optional_chaining) diff --git a/files/ja/web/javascript/reference/operators/this/index.md b/files/ja/web/javascript/reference/operators/this/index.md index e89018284b183a..f139f2cd7b23e4 100644 --- a/files/ja/web/javascript/reference/operators/this/index.md +++ b/files/ja/web/javascript/reference/operators/this/index.md @@ -1,115 +1,230 @@ --- title: this slug: Web/JavaScript/Reference/Operators/this +l10n: + sourceCommit: 8cb0caef8175e1772f13ef7bc761f9616e2c5a4b --- {{jsSidebar("Operators")}} -**関数の `this` キーワード** は、JavaScript ではほかの言語と少々異なる動作をします。また、[strict モード](/ja/docs/Web/JavaScript/Reference/Strict_mode)であるかどうかでも違いがあります。 +**`this`** キーワードは、関数本体などのコードを実行するコンテキストを指します。最も一般的な用途はオブジェクトメソッドで、この場合、`this` はメソッドが関連付けられているオブジェクトを指し、これにより、同じメソッドをさまざまなオブジェクトで再利用することができます。 -ほとんどの場合、`this` の値はどのように関数が呼ばれたかによって決定されます (実行時結合)。これは実行時に代入によって設定することはできず、関数が呼び出されるたびに異なる可能性があります。ES5 では {{jsxref("Function.prototype.bind()", "bind()")}} メソッドが導入され、関数が{{jsxref('Operators/this', "どのように呼ばれたかに関係なく `this` の値を設定する", 'The_bind_method', 1)}}することができるようになり、ES2015 では、自身では `this` の結び付けを行わない[アロー関数](/ja/docs/Web/JavaScript/Reference/Functions/Arrow_functions)が導入されました (これは包含する構文上のコンテキストの `this` の値を保持します)。 +JavaScript で `this` の値は、関数がどのように定義されているかではなく、どのように呼び出されるか(実行時の{{glossary("binding", "バインド方法")}})によって決まります。通常の関数がオブジェクトのメソッドとして呼び出された場合 (`obj.method()`)、`this` はそのオブジェクトを指します。単独の関数として呼び出された場合(オブジェクトに関連付けられていない func())、this は通常、[グローバルオブジェクト](/ja/docs/Glossary/Global_object)(厳格モードでない場合)、グローバルオブジェクトまたは `undefined` ([厳格モード](/ja/docs/Web/JavaScript/Reference/Strict_mode)の場合)を指します。 +{{jsxref("Function.prototype.bind()")}} メソッドは、`this` のバインドが変更されない関数を作成できます。また、{{jsxref("Function.prototype.apply()")}} および {{jsxref("Function.prototype.call()")}} メソッドは、特定の呼び出しに対して `this` の値を設定することもできます。 + +[アロー関数](/ja/docs/Web/JavaScript/Reference/Functions/Arrow_functions)では、`this` の扱いが異なります。定義された時点で親スコープから継承します。この動作により、アロー関数はコールバックやコンテキストの保持を行う上で特に便利です。ただし、アロー関数には独自の `this` バインディングがありません。そのため、`bind()`、`apply()`、`call()` メソッドで `this` の値を設定することはできません。また、オブジェクトメソッドで現在のオブジェクトを指すこともできません。 {{EmbedInteractiveExample("pages/js/expressions-this.html")}} ## 構文 -``` +```js-nolint this ``` ### 値 -strict モードでない場合は、実行コンテキスト (グローバル、関数、eval) のプロパティで、常にオブジェクトへの参照です。 strict モードではどのような値でも取り得ます。 +厳格モードでない場合は、`this` は常にオブジェクトを参照します。厳格モードでは、どのような値もどのような値でも取り得ます。値の決定方法に関する詳細情報は、下記を参照してください。 ## 解説 -### グローバルコンテキスト +この値は、それが現れるコンテキスト(関数、クラス、グローバル)によって異なります。 -グローバル実行コンテキスト (すべての関数の外側) では、strict モードであるかどうかにかかわらず、`this` はグローバルオブジェクトを参照します。 +### 関数コンテキスト + +関数内での `this` の値は、関数の呼び出し方によって異なります。 + +下記のコードは [strict モード](/ja/docs/Web/JavaScript/Reference/Strict_mode)ではないため、また呼び出し時に `this` の値が設定されないため、`this` は既定でグローバルオブジェクトとなり、これはブラウザーでは {{domxref("Window", "window")}} です。 ```js -// ウェブブラウザーでは window オブジェクトもグローバルオブジェクトです。 -console.log(this === window); // true +function getThis() { + return this; +} -a = 37; -console.log(window.a); // 37 +const obj1 = { name: "obj1" }; +const obj2 = { name: "obj2" }; -this.b = "MDN"; -console.log(window.b); // "MDN" -console.log(b); // "MDN" +obj1.getThis = getThis; +obj2.getThis = getThis; + +console.log(obj1.getThis()); // { name: 'obj1', getThis: [Function: getThis] } +console.log(obj2.getThis()); // { name: 'obj2', getThis: [Function: getThis] } ``` -> [!NOTE] -> コードが実行されている現在のコンテキストに関係なく、グローバルの {{jsxref("globalThis")}} プロパティを使用していつでも簡単にグローバルオブジェクトを取得できます。 +関数は同じですが、呼び出し方法によって `this` の値が異なることに注目してください。これは、関数への引数がどのように動作するのかと似ています。 -### 関数コンテキスト +`this` の値は、自分自身のプロパティとして機能を持つオブジェクトではなく、その機能を呼び出すために使用されるオブジェクトです。これを証明するために、[プロトタイプチェーン](/ja/docs/Web/JavaScript/Inheritance_and_the_prototype_chain)の上位にあるオブジェクトのメソッドを呼び出してみましょう。 -関数内での `this` の値は、関数の呼び出し方によって異なります。 +```js +const obj3 = { + __proto__: obj1, + name: "obj3", +}; -下記のコードは [strict モード](/ja/docs/Web/JavaScript/Reference/Strict_mode)ではないため、また呼び出し時に `this` の値が設定されないため、`this` は既定でグローバルオブジェクトとなり、これはブラウザーでは {{domxref("Window", "window")}} です。 +console.log(obj3.getThis()); // { name: 'obj3' } +``` + +`this` の値は、関数がオブジェクトに作成時に定義された場合でも、常にその関数がどのように呼び出されたかによって変化します。 + +```js +const obj4 = { + name: "obj4", + getThis() { + return this; + }, +}; + +const obj5 = { name: "obj5" }; + +obj5.getThis = obj4.getThis; +console.log(obj5.getThis()); // { name: 'obj5', getThis: [Function: getThis] } +``` + +メソッドにアクセスする値がプリミティブの場合、`this` はプリミティブ値となります。ただし、関数が厳格モードの場合のみです。 ```js -function f1() { +function getThisStrict() { + "use strict"; // 厳格モードに入る return this; } -// ブラウザー上で -f1() === window; // true +// デモ専用のものです。組み込みのプロトタイプを変更しないでください。 +Number.prototype.getThisStrict = getThisStrict; +console.log(typeof (1).getThisStrict()); // "number" +``` + +何らかの形でアクセスされることなく関数が呼び出された場合、`this` は `undefined` となります。ただし、関数が厳格モードの場合のみです。 -// Node 上で -f1() === global; // true +```js +console.log(typeof getThisStrict()); // "undefined" ``` -ただし strict モードでは、実行コンテキストに入るときに `this` 値が設定されていないと、以下の例のように `undefined` のままになります。 +厳格モードではない場合、[`this` 置換](/ja/docs/Web/JavaScript/Reference/Strict_mode#no_this_substitution)と呼ばれる特別な処理により、この値が常にオブジェクトであることが確実に保持されます。これはつまり、 + +- 関数が `this` を `undefined` または `null` に設定されて呼び出された場合、`this` は {{jsxref("globalThis")}} に置き換えられます。 +- 関数が `this` をプリミティブ値に設定されて呼び出された場合、`this` はそのプリミティブ地のラッパーオブジェクトに置き換えられます。 ```js -function f2() { - "use strict"; // strict モードにする +function getThis() { return this; } -f2() === undefined; // true +// デモ専用のものです。組み込みのプロトタイプを変更しないでください。 +Number.prototype.getThis = getThis; +console.log(typeof (1).getThis()); // "object" +console.log(getThis() === globalThis); // true ``` -> [!NOTE] -> 二番目の例において、`this` が {{jsxref("undefined")}} となるのは `f2` が直接呼び出されており、オブジェクトのメソッドやプロパティ (例えば `window.f2()`) ではないためです。この機能は初めて [strict モード](/ja/docs/Web/JavaScript/Reference/Strict_mode)への対応が始まったとき、一部のブラウザーが実装していませんでした。結果的に、これらのブラウザーは不正確に `window` オブジェクトを返していました。 +一般的な関数呼び出しでは、この値は関数の接頭辞(ドットの前の部分)を通して暗黙的に引数として渡されます。また、`this` の値は {{jsxref("Function.prototype.call()")}}、{{jsxref("Function.prototype.apply()")}}、{{jsxref("Reflect.apply()")}} のメソッドを使用して、明示的に設定することもできます。{{jsxref("Function.prototype.bind()")}} を使用すると、関数の呼び出し方法に関わらず変更されない特定の `this` 値を持つ新しい関数を作成することができます。これらのメソッドを使用する場合、関数が厳格モードでない場合でも、上記の `this` の置換ルールが適用されます。 -関数の呼び出し時に `this` の値を特定の値に設定するには、以下の例のように {{jsxref("Function.prototype.call()", "call()")}} または {{jsxref("Function.prototype.apply()", "apply()")}} を使用します。 +#### コールバック -### クラスコンテキスト +関数がコールバックとして渡される場合、`this` の値はコールバックがどのように呼び出されるかによって決まり、これはAPIの実装者によって決定されます。コールバックは通常、`this` の値が `undefined` で(オブジェクトに関連付けずに直接)呼び出されます。これは、関数が厳格モードでない場合、`this` の値はグローバルオブジェクト ({{jsxref("globalThis")}}) であることを意味します。これは、[反復処理可能な配列メソッド](/ja/docs/Web/JavaScript/Reference/Global_Objects/Array#反復処理メソッド)、[`Promise()`](/ja/docs/Web/JavaScript/Reference/Global_Objects/Promise/Promise) コンストラクターなどにも当てはまります。 -[クラス](/ja/docs/Web/JavaScript/Reference/Classes)は関数の機能であるため、クラスと関数の `this` の動作は似ています。ただし、いくつかの違いと注意点があります。 +```js +function logThis() { + "use strict"; + console.log(this); +} + +[1, 2, 3].forEach(logThis); // undefined, undefined, undefined +``` -クラスのコンストラクター内では、`this` は通常のオブジェクトです。クラス内のすべて静的でないメソッドは `this` のプロトタイプに追加されます。 +API によっては、コールバックの呼び出し時に `this` の値を設定することができます。例えば、すべての反復処理配列メソッドと、{{jsxref("Set.prototype.forEach()")}} のような関連メソッドでは、オプションの `thisArg` 引数を受け入れます。/\ ```js -class Example { - constructor() { - const proto = Object.getPrototypeOf(this); - console.log(Object.getOwnPropertyNames(proto)); - } - first() {} - second() {} - static third() {} +[1, 2, 3].forEach(logThis, { name: "obj" }); +// { name: 'obj' }, { name: 'obj' }, { name: 'obj' } +``` + +時には、`this` 値が `undefined` 以外でコールバックが呼び出されることもあります。例えば、{{jsxref("JSON.parse()")}} の `reviver` 引数と {{jsxref("JSON.stringify()")}} の `replacer` 引数はどちらも、この値が解釈/シリアライズできるプロパティが属するオブジェクトに設定されて呼び出されます。 + +#### アロー関数 + +[アロー関数](/ja/docs/Web/JavaScript/Reference/Functions/Arrow_functions)では、`this` 値は周囲の字句コンテキストの `this` の値を保持します。言い換えれば、アロー関数の本体を評価する際、言語は新しい `this` のバインドを作成しません。 + +例えば、グローバルコードでは、`this` は厳格モードであるかどうかにかかわらず、常に `globalThis` となります。これは、[グローバルコンテキスト](#グローバルコンテキスト)のバインドによるものです。 + +```js +const globalObject = this; +const foo = () => this; +console.log(foo() === globalObject); // true +``` + +アロー関数は、その関数が存在するスコープの `this` 値を囲む[クロージャ](/ja/docs/Web/JavaScript/Closures)を作成します。つまり、アロー関数は「自動バインド」されているかのように動作します。つまり、どのように呼び出されたとしても、`this` は関数が作成された時点での値(例えば、グローバルオブジェクト)にバインドされます。他の関数内で作成されたアロー関数にも同じことが言えます。そのthisは、それを囲む字句コンテキストのままです。[下記の例を参照してください](#アロー関数内の_this)。 + +さらに、`call()`、`bind()`、`apply()` を使用してアロー関数を呼び出す場合、`thisArg` 引数は無視されます。ただし、これらのメソッドを使用しても、他にも引数を渡すことができます。 + +```js +const obj = { name: "obj" }; + +// call を使用して this を設定しようとする +console.log(foo.call(obj) === globalObject); // true + +// bind を使用して this を設定しようとする +const boundFoo = foo.bind(obj); +console.log(boundFoo() === globalObject); // true +``` + +#### コンストラクター + +関数がコンストラクター({{jsxref("Operators/new", "new")}} キーワード付き)として使用される場合、コンストラクター関数がどのオブジェクトにアクセスしているかに関わらず、その `this` は、構築中の新しいオブジェクトにバインドされます。コンストラクターが別のプリミティブ値以外の値を返さない限り、`this` の値は `new` 式の値となります。 + +```js +function C() { + this.a = 37; +} + +let o = new C(); +console.log(o.a); // 37 + +function C2() { + this.a = 37; + return { a: 38 }; } -new Example(); // ['constructor', 'first', 'second'] +o = new C2(); +console.log(o.a); // 38 ``` -> [!NOTE] -> 静的メソッドは `this` のプロパティではありません。クラス自身のプロパティです。 +2 つ目の例 (`C2`) では、構築中にオブジェクトが返されるため、`this` にバインドされていた新しいオブジェクトは破棄されます。(これは本質的に、`this.a = 37;` の文をデッドコードにします。このコードは実行されるため、厳密にはデッドコードではありませんが、外部に影響を与えることなく削除することができます。) + +#### super + +`super.method()` 形式で関数が最初に呼び出された場合、`method` 関数内の `this` は `super.method()` 呼び出しの周辺の `this` 値と同じ値であり、通常 `super` が参照するオブジェクトとは異なります。これは、`super.method` が上記のオブジェクトメンバーにアクセスするようなものではないためです。これは、異なるバインドルールを持つ特別な構文です。例えば、[`super` のリファレンス](/ja/docs/Web/JavaScript/Reference/Operators/super#calling_methods_from_super)を参照してください。 + +### クラスコンテキスト -### 派生クラス +[クラス](/ja/docs/Web/JavaScript/Reference/Classes)は、静的コンテキストとインスタンスコンテキストの 2 つに分けることができます。[コンストラクター](/ja/docs/Web/JavaScript/Reference/Classes/constructor)、メソッド、インスタンスフィールド初期化子([パブリック](/ja/docs/Web/JavaScript/Reference/Classes/Public_class_fields)または[プライベート](/ja/docs/Web/JavaScript/Reference/Classes/Private_properties))はインスタンスコンテキストに属します。[静的](/ja/docs/Web/JavaScript/Reference/Classes/static)メソッド、静的フィールド初期化子、静的初期化ブロックは静的コンテキストに属します。それぞれのコンテキストで、`this` の値が異なります。 -基本クラスのコンストラクターとは異なり、派生コンストラクターには初期の `this` の結び付けがありません。{{jsxref("Operators/super", "super()")}} を呼び出すとコンストラクター内に `this` の結び付けが作成され、基本的に以下のコードを評価する効果があります。ここで、Base は継承されたクラスです。 +クラスのコンストラクターは常に `new` で呼び出されるため、その動作は[関数コンストラクター](#コンストラクター)と同じです。`this` 値は、作成される新しいインスタンスです。 クラスメソッドは、オブジェクトリテラル内のメソッドと同じように動作します。`this` 値は、メソッドがアクセスされたオブジェクトです。 メソッドが他のオブジェクトに転送されない場合、`this` は通常、クラスのインスタンスです。 + +静的メソッドは `this` のプロパティではありません。クラス自体のプロパティです。つまり、それらは一般的にクラスにアクセスされるため、`this` はクラス(またはサブクラス)の値です。静的初期化ブロックも、`this` を現在のクラスに設定して評価します。 + +フィールド初期化子もクラスのコンテキストで評価されます。インスタンスフィールドは、`this` を構築中のインスタンスに設定して評価されます。静的フィールドは、`this` を現在のクラスに設定して評価されます。これが、フィールド初期化子でアロー関数が[インスタンスフィールドの場合はインスタンスに、静的フィールドの場合はクラスにバインドされる](/ja/docs/Web/JavaScript/Reference/Functions/Arrow_functions#メソッドとしては使用不可)理由です。 ```js +class C { + instanceField = this; + static staticField = this; +} + +const c = new C(); +console.log(c.instanceField === c); // true +console.log(C.staticField === C); // true +``` + +#### 派生クラスのコンストラクター + +基本クラスのコンストラクターとは異なり、派生コンストラクターには初期の `this` の結び付けがありません。{{jsxref("Operators/super", "super()")}} を呼び出すとコンストラクター内に `this` のバインドが作成され、基本的に以下のコードを評価する効果があります。ここで、`Base` は継承されたクラスです。 + +```js-nolint this = new Base(); ``` > **警告:** `this` を `super()` の呼び出しの前に参照すると、エラーが発生します。 -派生クラスはでは `super()` を呼び出す前に return をしてはいけません。ただし、 `Object` を返す場合やコンストラクターがない場合を除きます。 +派生クラスはでは `super()` を呼び出す前に return をしてはいけません。ただし、オブジェクトを返す場合やコンストラクターがない場合を除きます。 ```js class Base {} @@ -125,50 +240,98 @@ class Bad extends Base { new Good(); new AlsoGood(); -new Bad(); // 参照エラー +new Bad(); // ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor +``` + +### グローバルコンテキスト + +グローバル実行コンテキスト(関数やクラスの外部、グローバルスコープで定義された[ブロック](/ja/docs/Web/JavaScript/Reference/Statements/block)または[アロー関数](#アロー関数)の内部の場合もあり)では、スクリプトが動作する実行コンテキストによって `this` の値が決まります。 [コールバック](#コールバック)と同様に、`this` の値は実行環境(呼び出し側)によって決定されます。 + +スクリプトの最上位レベルでは、`this` 値は厳格モードであるかどうかに関わらず、`globalThis` を参照します。これは一般的にグローバルオブジェクトと同じです。例えば、ソースが HTML の [`