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
-
+ + + + + + + + + + +
前回今回実際の遅延
``` ```js @@ -222,10 +231,9 @@ let last = 0; let iterations = 10; function timeout() { - // log the time of this call + // この呼び出しの時刻をログ出力 logline(new Date().getMilliseconds()); - - // if we are not finished, schedule the next call + // まだ終わっていない場合は、次の呼び出しをスケジュール if (iterations-- > 0) { setTimeout(timeout, 0); } @@ -238,36 +246,47 @@ function run() { log.removeChild(log.lastElementChild); } - // initialize iteration count and the starting timestamp + // 反復処理の回数と開始タイムスタンプを初期化 iterations = 10; last = new Date().getMilliseconds(); - // start timer setTimeout(timeout, 0); } -function pad(number) { - return number.toString().padStart(3, "0"); -} - function logline(now) { - // log the last timestamp, the new timestamp, and the difference - const newLine = document.createElement("pre"); - newLine.textContent = `${pad(last)} ${pad(now)} ${ - now - last - }`; - document.getElementById("log").appendChild(newLine); + // 最後のタイムスタンプ、新しいタイムスタンプ、および差分をログ出力 + const tableBody = document.getElementById("log"); + const logRow = tableBody.insertRow(); + logRow.insertCell().textContent = last; + logRow.insertCell().textContent = now; + logRow.insertCell().textContent = now - last; last = now; } document.querySelector("#run").addEventListener("click", run); ``` +```css hidden +* { + font-family: monospace; +} +th, +td { + padding: 0 10px 0 10px; + text-align: center; + border: 1px solid; +} +table { + border-collapse: collapse; + margin-top: 10px; +} +``` + {{EmbedLiveSample("Nested_timeouts", 100, 420)}} #### アクティブでないタブのタイムアウト -バックグラウンドのタブによる負荷(および関連するバッテリーの使用量)を軽減するために、ブラウザはアクティブでないタブの最小タイムアウト時間を強制します。また、ページがウェブオーディオ API の {{domxref("AudioContext")}} を使用して音声を再生している場合、このタイムアウトが免除されることもあります。 +バックグラウンドのタブによる負荷(および関連するバッテリーの使用量)を軽減するために、ブラウザーはアクティブでないタブの最小タイムアウト時間を強制します。また、ページがウェブオーディオ API の {{domxref("AudioContext")}} を使用して音声を再生している場合、このタイムアウトが免除されることもあります。 この仕様はブラウザーに依存します。 @@ -284,7 +303,8 @@ Firefox は、トラッキングスクリプトとして認識されたスクリ #### タイムアウトの遅延 -ページ(または OS やブラウザー)が他のタスクでビジー状態場合、タイムアウトが予想より遅れて発生することがあります。注意すべき重要なケースとして、 `setTimeout()` を呼び出したスレッドが終了するまで、関数やコードスニペットを実行することができないことがあります。例えば、 +ページ(または OS やブラウザー)が他のタスクでビジー状態場合、タイムアウトが予想より遅れて発生することがあります。 +注意すべき重要なケースとして、 `setTimeout()` を呼び出したスレッドが終了するまで、関数やコードスニペットを実行することができないことがあります。例えば、 ```js function foo() { @@ -296,7 +316,7 @@ console.log("After setTimeout"); このコードは、コンソールへ以下のように出力します。 -``` +```plain After setTimeout foo has been called ``` @@ -313,7 +333,22 @@ Firefox は現在のタブがロードされている間、 `setTimeout()` タ ### 最大の遅延時間 -Internet Explorer、Chrome、Safari、Firefox を含むブラウザーは、内部で遅延時間を 32 ビット符号付き整数値で保存します。このため 2,147,483,647 ms (約 24.8 日) より大きな遅延時間を使用すると整数値がオーバーフローして、その結果直ちに実行されるタイムアウトになります。 +ブラウザーは遅延時間を内部的に 32 ビット符号付き整数として格納するため、 +2,147,483,647 ミリ秒(約 24.8 日)を超える遅延時間を使用すると、整数オーバーフローが発生します。例えば、次のコードでは、 + +```js +setTimeout(() => console.log("hi!"), 2 ** 32 - 5000); +``` + +…タイムアウトが即座に実行される結果となります(`2**32 - 5000` が負の数にオーバーフローするため)。一方、次のコードのようにすると、 + +```js +setTimeout(() => console.log("hi!"), 2 ** 32 + 5000); +``` + +…タイムアウトは約5秒後に実行されます。 + +**メモ**: これは、Node.js の `setTimeout` の動作と一致しません。Node.js では、2,147,483,647 ミリ秒を超えるタイムアウトは即座に実行されます。 ## 例 diff --git a/files/ja/web/api/url_api/index.md b/files/ja/web/api/url_api/index.md index ac1e74fdce329b..a906e9c866f0d8 100644 --- a/files/ja/web/api/url_api/index.md +++ b/files/ja/web/api/url_api/index.md @@ -1,19 +1,21 @@ --- title: URL API slug: Web/API/URL_API +l10n: + sourceCommit: d71da812ee94c20658cb1916a123a42254ea545c --- -{{DefaultAPISidebar("URL API")}} +{{DefaultAPISidebar("URL API")}} {{AvailableInWorkers}} -URL API は URL 標準のコンポーネントであり、有効な {{Glossary("URL", "Uniform Resource Locator")}} の構成要素と URL にアクセスして操作する API を定義します。 URL 標準は、ドメイン、ホスト、IP アドレスなどの概念も定義し、Web フォームのコンテンツをキー/値のペアのセットとして送信するために使用される従来の `application/x-www-form-urlencoded` {{Glossary("MIME type","MIME タイプ")}}を標準的な方法で記述しようとします。 +URL API は URL 標準のコンポーネントであり、有効な {{Glossary("URL", "Uniform Resource Locator")}} の構成要素と URL にアクセスして操作する API を定義します。 URL 標準は、ドメイン、ホスト、IP アドレスなどの概念も定義し、ウェブフォームのコンテンツをキー/値のペアのセットとして送信するために使用される従来の `application/x-www-form-urlencoded` {{Glossary("MIME type","MIME タイプ")}}を標準的な方法で記述しようとします。 -## URL の概念と使用方法 +## 概念と使用方法 -URL 標準の大部分は、[URL の定義](/ja/docs/Learn/Common_questions/What_is_a_URL)と、それがどのように構造化および解析されるかによって構成されます。 また、ネットワーク上のコンピューターのアドレス指定に関連するさまざまな用語の定義も取り上げており、IP アドレスと DOM アドレスを解析するアルゴリズムが指定されています。 ほとんどの開発者にとってより興味深いのは、API 自体です。 +URL 標準の大部分は、[URL の定義](/ja/docs/Learn/Common_questions/Web_mechanics/What_is_a_URL)と、それがどのように構造化および解析されるかによって構成されます。 また、ネットワーク上のコンピューターのアドレス指定に関連するさまざまな用語の定義も取り上げており、IP アドレスと DOM アドレスを解析するアルゴリズムが指定されています。 ほとんどの開発者にとってより興味深いのは、API 自体です。 -### URL コンポーネントへのアクセス +### URL のコンポーネントへのアクセス -所与の URL の {{domxref("URL")}} オブジェクトを作成すると、URL が解析され、そのプロパティを介して構成部分にすばやくアクセスできます。 +所与の URL の {{domxref("URL")}} オブジェクトを作成すると、URL が構文解析され、そのプロパティを介して構成部分にすばやくアクセスできます。 ```js let addr = new URL("https://developer.mozilla.org/ja/docs/Web/API/URL_API"); @@ -21,7 +23,7 @@ let host = addr.host; let path = addr.pathname; ``` -上記のスニペットは、今読んでいる記事の英語版の `URL` オブジェクトを作成し、{{domxref("URL.host", "host")}} プロパティと {{domxref("URL.pathname", "pathname")}} プロパティを取得します。 この場合、これらの文字列はそれぞれ `developer.mozilla.org` と `/ja/docs/Web/API/URL_API` です。 +上記のスニペットは、今読んでいる記事の `URL` オブジェクトを作成し、{{domxref("URL.host", "host")}} プロパティと {{domxref("URL.pathname", "pathname")}} プロパティを取得します。 この場合、これらの文字列はそれぞれ `developer.mozilla.org` と `/ja/docs/Web/API/URL_API` です。 ### URL の変更 @@ -29,18 +31,18 @@ let path = addr.pathname; ```js let myUsername = "someguy"; -let addr = new URL("https://mysite.com/login"); +let addr = new URL("https://example.com/login"); addr.username = myUsername; ``` -{{domxref("URL.username", "username")}} の値を設定すると、そのプロパティの値が設定されるだけでなく、URL 全体が更新されます。 上記のコードスニペットを実行した後、{{domxref("URL.href", "addr.href")}} によって返される値は `https://someguy@mysite.com/login` です。 これは、書き込み可能なプロパティのいずれにも当てはまります。 +{{domxref("URL.username", "username")}} の値を設定すると、そのプロパティの値が設定されるだけでなく、URL 全体が更新されます。 上記のコードスニペットを実行した後、{{domxref("URL.href", "href")}} によって返される値は `https://someguy@example.com/login` です。 これは、書き込み可能なプロパティのいずれにも当てはまります。 ### クエリー -`URL` の {{domxref("URL.search", "search")}} プロパティには、URL のクエリー文字列部分が含まれます。 例えば、URL が `https://mysite.com/login?user=someguy&page=news` の場合、`search` プロパティの値は `?user=someguy&page=news` です。 {{domxref("URLSearchParams")}} オブジェクトの {{domxref("URLSearchParams.get", "get()")}} メソッドを使用して、個々のパラメーターの値を検索することもできます。 +`URL` の {{domxref("URL.search", "search")}} プロパティには、URL のクエリー文字列部分が含まれます。 例えば、URL が `https://example.com/login?user=someguy&page=news` の場合、`search` プロパティの値は `?user=someguy&page=news` です。 {{domxref("URLSearchParams")}} オブジェクトの {{domxref("URLSearchParams.get", "get()")}} メソッドを使用して、個々の引数の値を検索することもできます。 ```js -let addr = new URL("https://mysite.com/login?user=someguy&page=news"); +let addr = new URL("https://example.com/login?user=someguy&page=news"); try { loginUser(addr.searchParams.get("user")); gotoPage(addr.searchParams.get("page")); @@ -51,44 +53,44 @@ try { 例えば、上記のスニペットでは、ユーザー名と対象のページをクエリーから取得し、サイトのコードで使用される適切な関数に渡してログインし、サイト内の目的の宛先にユーザーを案内します。 -`URLSearchParams` 内の他の関数を使用すると、キーに属する値を変更したり、キーとその値を追加および削除したり、パラメーターのリストをソートしたりすることができます。 +`URLSearchParams` 内の他の関数を使用すると、キーに属する値を変更したり、キーとその値を追加および削除したり、引数のリストをソートしたりすることができます。 -## URL API インターフェイス +## インターフェイス URL API は単純な API で、それに対するインターフェイスは次の 2 つだけです。 -- [`URL`](/ja/docs/Web/API/URL) -- [`URLSearchParams`](/ja/docs/Web/API/URLSearchParams) - -仕様の古いバージョンには {{domxref("URLUtilsReadOnly")}} と呼ばれるインターフェイスが含まれていましたが、これはその後 {{domxref("WorkerLocation")}} インターフェイスに統合されました。 +- {{domxref("URL")}} + - : {{glossary("URL", "URL")}} の解釈、構築、正規化、エンコードに使用することができます。 +- {{domxref("URLSearchParams")}} + - : URL のクエリー文字列で作業するユーティリティメソッドを定義します。 ## 例 -URL に含まれるパラメーターを処理する場合は、手動で実行できますが、`URL` オブジェクトを作成してそれを行う方がはるかに簡単です。 以下の `fillTableWithParameters()` 関数は、{{HTMLElement("table")}} を表す {{domxref("HTMLTableElement")}} オブジェクトを入力として受け取ります。 パラメーターで見つかった各キーに対応する行が表に追加され、最初の列にはキーの名前が含まれ、2 番目の列には値が含まれます。 +URL に含まれる引数の処理は手動でもきますが、`URL` オブジェクトを作成してそれを行う方がはるかに簡単です。 以下の `fillTableWithParameters()` 関数は、{{HTMLElement("table")}} を表す {{domxref("HTMLTableElement")}} オブジェクトを入力として受け取ります。 引数で見つかった各キーに対応する行が表に追加され、最初の列にはキーの名前が含まれ、2 番目の列には値が含まれます。 -表を生成する前に {{domxref("URLSearchParams.sort()")}} を呼び出してパラメーターリストをソートしていることに注意してください。 +表を生成する前に {{domxref("URLSearchParams.sort()")}} を呼び出して引数リストをソートしていることに注意してください。 ```js function fillTableWithParameters(tbl) { - let url = new URL(document.location.href); + const url = new URL(document.location.href); url.searchParams.sort(); - let keys = url.searchParams.keys(); - - for (let key of keys) { - let val = url.searchParams.get(key); - let row = document.createElement("tr"); - let cell = document.createElement("td"); - cell.innerText = key; - row.appendChild(cell); - cell = document.createElement("td"); - cell.innerText = val; - row.appendChild(cell); + const keys = url.searchParams.keys(); + + for (const key of keys) { + const val = url.searchParams.get(key); + const row = document.createElement("tr"); + const cell1 = document.createElement("td"); + cell1.innerText = key; + row.appendChild(cell1); + const cell2 = document.createElement("td"); + cell2.innerText = val; + row.appendChild(cell2); tbl.appendChild(row); } } ``` -この例の働くバージョンは [Glitch にあります](https://url-api.glitch.me)。 ページをロードするときに URL にパラメーターを追加するだけで、表に表示されます。 例えば、[`https://url-api.glitch.me?from=mdn&excitement=high&likelihood=inconceivable`](https://url-api.glitch.me?from=mdn&excitement=high&likelihood=inconceivable) を試してください。 +この例の動作するバージョンは [Glitch にあります](https://url-api.glitch.me)。 ページを読み込むときに URL に引数を追加するだけで、表に表示されます。 例えば、[`https://url-api.glitch.me?from=mdn&excitement=high&likelihood=inconceivable`](https://url-api.glitch.me?from=mdn&excitement=high&likelihood=inconceivable) を試してください。 ## 仕様書 @@ -100,5 +102,7 @@ function fillTableWithParameters(tbl) { ## 関連情報 -- [Fetch API](/ja/docs/Web/API/Fetch_API) -- CSS {{cssxref("<url>")}} 型 +- {{domxref("Fetch API", "フェッチ API", "", "nocode")}} +- CSS {{cssxref("url_value")}} 型 +- {{jsxref("encodeURI", "encodeURI()")}} +- {{jsxref("encodeURIComponent", "encodeURIComponent()")}} diff --git a/files/ja/web/api/queuemicrotask/index.md b/files/ja/web/api/window/queuemicrotask/index.md similarity index 97% rename from files/ja/web/api/queuemicrotask/index.md rename to files/ja/web/api/window/queuemicrotask/index.md index 690663f6410af1..8d46d166db506f 100644 --- a/files/ja/web/api/queuemicrotask/index.md +++ b/files/ja/web/api/window/queuemicrotask/index.md @@ -1,6 +1,7 @@ --- title: queueMicrotask() -slug: Web/API/queueMicrotask +slug: Web/API/Window/queueMicrotask +original_slug: Web/API/queueMicrotask --- {{APIRef("HTML DOM")}} diff --git a/files/ja/web/api/reporterror/index.md b/files/ja/web/api/window/reporterror/index.md similarity index 97% rename from files/ja/web/api/reporterror/index.md rename to files/ja/web/api/window/reporterror/index.md index aa212c6fa89854..102bb4b397f2bd 100644 --- a/files/ja/web/api/reporterror/index.md +++ b/files/ja/web/api/window/reporterror/index.md @@ -1,7 +1,7 @@ --- title: reportError() グローバル関数 -short-title: reportError() -slug: Web/API/reportError +slug: Web/API/Window/reportError +original_slug: Web/API/reportError l10n: sourceCommit: 76717f752447b6eef25bf29c12272e407ee5cb6b --- diff --git a/files/ja/web/api/structuredclone/index.md b/files/ja/web/api/window/structuredclone/index.md similarity index 98% rename from files/ja/web/api/structuredclone/index.md rename to files/ja/web/api/window/structuredclone/index.md index 3f6911cf23eff7..f2dcc6cf0c76c4 100644 --- a/files/ja/web/api/structuredclone/index.md +++ b/files/ja/web/api/window/structuredclone/index.md @@ -1,7 +1,7 @@ --- title: structuredClone() グローバル関数 -short-title: structuredClone() -slug: Web/API/structuredClone +slug: Web/API/Window/structuredClone +original_slug: Web/API/structuredClone l10n: sourceCommit: cb279e20569055b200f93802d1704846c28aa04f --- diff --git a/files/ja/web/css/index.md b/files/ja/web/css/index.md index 6301005324d19c..e9f1471730aee6 100644 --- a/files/ja/web/css/index.md +++ b/files/ja/web/css/index.md @@ -2,14 +2,14 @@ title: "CSS: カスケーディングスタイルシート" slug: Web/CSS l10n: - sourceCommit: b85bf9fcc2c0062a765d104799d7d45d9e9b13bb + sourceCommit: 6197320c2f25a975ee4f7df4b8d5b48bf8d01562 --- {{CSSRef}} -**カスケーディングスタイルシート** (Cascading Style Sheets、**CSS**) は[スタイルシート](/ja/docs/Web/API/StyleSheet)言語であり、[HTML](/ja/docs/Web/HTML) や [XML](/ja/docs/Web/XML/XML_introduction) (方言である [SVG](/ja/docs/Web/SVG)、[MathML](/ja/docs/Web/MathML)、{{Glossary("XHTML")}} などを含む) で記述された文書の体裁や見栄えを表現するために用いられます。 CSS は、要素が画面上で (あるいは紙や音声といった別のメディア上で) どのように表現されるのかを定義します。 +**カスケーディングスタイルシート** (Cascading Style Sheets、**CSS**) は[スタイルシート](/ja/docs/Web/API/StyleSheet)言語であり、[HTML](/ja/docs/Web/HTML) や [XML](/ja/docs/Web/XML/XML_introduction)(派生言語である [SVG](/ja/docs/Web/SVG)、[MathML](/ja/docs/Web/MathML)、{{Glossary("XHTML")}} などを含む)で記述された文書の体裁や見栄えを表現するために用いられます。CSS は、要素が画面上で (あるいは紙や音声といった別のメディア上で) どのように表現されるのかを定義します。 -CSS は**オープンウェブ**の核となる言語に含まれており、[W3C 標準仕様](https://www.w3.org/Style/CSS/#specs)によってウェブブラウザー間で標準化されています。以前は CSS 仕様書の様々な部分が同時に開発されており、最新勧告の版数付けができていました。皆さんも CSS1、CSS2.1、また CSS3 についても聞いたことがあるでしょう。CSS3 や CSS4 にはなりません。すべてバージョン番号のない CSS になりました。 +CSS は**オープンウェブ**の核となる言語に含まれており、[W3C 標準仕様](https://www.w3.org/Style/CSS/#specs)によってウェブブラウザー間で標準化されています。以前は CSS 仕様書の様々な部分が同時に開発されており、最新勧告の版数付けができていました。皆さんも CSS1、CSS2.1、また CSS3 についても聞いたことがあるでしょう。CSS3 や CSS4 にはなりません。すべて単なる "CSS" と、バージョン番号を持つ個々の CSS モジュールとなりました。 CSS 2.1 以降、仕様の範囲が大幅に拡大し、CSS モジュールごとに進捗状況が大きく異なるようになったため、[モジュールごとに勧告を開発して公開する](https://www.w3.org/Style/CSS/current-work)ことがより効果的になりました。W3C では、CSS 仕様のバージョン管理の代わりに、[最新の CSS 仕様の安定した状態](https://www.w3.org/TR/css/)のスナップショットと独立したモジュールの進捗を定期的に取得するようになりました。CSS のモジュールは、[CSS Color Module Level 5](https://drafts.csswg.org/css-color-5/) のように、バージョン番号またはレベルを持つようになりました。 @@ -20,15 +20,7 @@ CSS 2.1 以降、仕様の範囲が大幅に拡大し、CSS モジュールご - CSS チュートリアル - : [CSS 学習領域](/ja/docs/Learn/CSS)は、初心者から中級者になるための、すべての基本事項を網羅した豊富なコンテンツがあります。 - CSS リファレンス - - : CSS のすべてのプロパティや概念について記述された、熟練のウェブ開発者向けの[包括的な CSS リファレンス](/ja/docs/Web/CSS/Reference)です。 - -> [!CALLOUT] -> -> #### フロントエンドのウェブ開発者を目指している方へ -> -> ゴールに向かって頑張るために必要な情報をまとめたコースをご用意しました。 -> -> [**始めましょう**](/ja/docs/Learn/Front-end_web_developer) + - : CSS の個々のプロパティや概念について記述された [CSS リファレンス](/ja/docs/Web/CSS/Reference)です。 ## チュートリアル @@ -43,30 +35,32 @@ CSS 2.1 以降、仕様の範囲が大幅に拡大し、CSS モジュールご ここでの目的は、[テキストの装飾](/ja/docs/Learn/CSS/Styling_text)や[CSS レイアウト](/ja/docs/Learn/CSS/CSS_layout)などのより具体的な分野に進む前に、適切な CSS を書くための手法を知り、すべての重要な理論を理解できるようになることです。 - [CSS テキスト装飾](/ja/docs/Learn/CSS/Styling_text) + - : CSS 言語の基本を習得したら、次に取り組むべき CSS のトピックはテキストの装飾です — これは、CSS で行う最も一般的なことの一つです。ここでは、フォント、太字、イタリック体、ラインと文字の間隔、ドロップシャドウやその他のテキスト機能の設定を含む、テキストの装飾の基本を見ていきます。あなたのページにカスタムフォントを適用し、リストとリンクを装飾するところを見ることによって、このモジュールを締めくくります。 + - [CSS レイアウト](/ja/docs/Learn/CSS/CSS_layout) + - : 現段階で、すでに CSS の基本、テキストの装飾方法、コンテンツを格納するボックスの装飾方法と操作方法を見てきました。今度は、ビューポートからの相対でボックスを適切な場所に配置する方法、および互いの配置方法を検討します。必要な前提知識をカバーしているので、さまざまな表示の設定、フレックスボックス・CSS グリッド・位置指定などの最新のレイアウトツール、そしてまだ知っておきたいと思うかもしれない過去のテクニックのいくつかを見ながら、CSS レイアウトについて深く掘り下げることができます。 + - [CSS を使ってよくある問題を解決する](/ja/docs/Learn/CSS/Howto) - : このモジュールは、ウェブページを作成する際の一般的な問題を解決するための CSS の使用方法を説明するコンテンツの節へのリンクを提供しています。 ## リファレンス -- [CSS リファレンス](/ja/docs/Web/CSS/Reference): CSS のすべてのプロパティや概念について記述された、熟練のウェブ開発者向けの CSS リファレンスです。 -- CSS の主要な概念: - - - [言語の構文と書式](/ja/docs/Web/CSS/Syntax) - - [詳細度](/ja/docs/Web/CSS/Specificity)と[継承](/ja/docs/Web/CSS/Inheritance)と[カスケード](/ja/docs/Web/CSS/Cascade) - - [CSS 単位と値](/ja/docs/Web/CSS/CSS_Values_and_Units)および[関数記法](/ja/docs/Web/CSS/CSS_Functions) - - [ボックスモデル](/ja/docs/Web/CSS/CSS_box_model/Introduction_to_the_CSS_box_model)と[マージンの相殺](/ja/docs/Web/CSS/CSS_box_model/Mastering_margin_collapsing) - - [包含ブロック](/ja/docs/Web/CSS/Containing_block) - - [重ね合わせ](/ja/docs/Web/CSS/CSS_positioned_layout/Understanding_z-index/Stacking_context)と[ブロック整形](/ja/docs/Web/Guide/CSS/Block_formatting_context)コンテキスト - - [初期値](/ja/docs/Web/CSS/initial_value)、[計算値](/ja/docs/Web/CSS/computed_value)、[使用値](/ja/docs/Web/CSS/used_value)、[実効値](/ja/docs/Web/CSS/actual_value) - - [CSS 一括指定プロパティ](/ja/docs/Web/CSS/Shorthand_properties) - - [CSS フレックスボックスレイアウト](/ja/docs/Web/CSS/CSS_flexible_box_layout) - - [CSS グリッドレイアウト](/ja/docs/Web/CSS/CSS_grid_layout) - - [CSS セレクター](/ja/docs/Web/CSS/CSS_selectors) - - [メディアクエリー](/ja/docs/Web/CSS/CSS_media_queries) - - [アニメーション](/ja/docs/Web/CSS/animation) +[CSS リファレンス](/ja/docs/Web/CSS/Reference)は、経験豊富なウェブ開発者向けの包括的なリファレンスであり、CSS のすべてのプロパティと概念を記述しています。 + +- [言語の構文と書式](/ja/docs/Web/CSS/Syntax) +- [詳細度](/ja/docs/Web/CSS/Specificity)と[継承](/ja/docs/Web/CSS/Inheritance)と[カスケード](/ja/docs/Web/CSS/Cascade) +- [CSS セレクター](/ja/docs/Web/CSS/CSS_selectors)、[擬似要素](/ja/docs/Web/CSS/CSS_pseudo-elements)、[入れ子](/ja/docs/Web/CSS/CSS_nesting)、[スコープ化](/ja/docs/Web/CSS/CSS_scoping)、[シャドウパーツ](/ja/docs/Web/CSS/CSS_shadow_parts) +- [CSS アットルール](/ja/docs/Web/CSS/At-rule)([メディア](/ja/docs/Web/CSS/CSS_media_queries)や[コンテナー](/ja/docs/Web/CSS/CSS_containment)クエリーを含む) +- [CSS 単位と値](/ja/docs/Web/CSS/CSS_Values_and_Units)および[関数記法](/ja/docs/Web/CSS/CSS_Functions) +- [ボックスモデル](/ja/docs/Web/CSS/CSS_box_model/Introduction_to_the_CSS_box_model)と[マージンの相殺](/ja/docs/Web/CSS/CSS_box_model/Mastering_margin_collapsing) +- [包含ブロック](/ja/docs/Web/CSS/Containing_block) +- [重ね合わせ](/ja/docs/Web/CSS/CSS_positioned_layout/Understanding_z-index/Stacking_context)と[ブロック整形](/ja/docs/Web/CSS/CSS_display/Block_formatting_context)コンテキスト +- [初期値](/ja/docs/Web/CSS/initial_value)、[計算値](/ja/docs/Web/CSS/computed_value)、[使用値](/ja/docs/Web/CSS/used_value)、[実効値](/ja/docs/Web/CSS/actual_value) +- [CSS 一括指定プロパティ](/ja/docs/Web/CSS/Shorthand_properties) +- [CSS フレックスボックス](/ja/docs/Web/CSS/CSS_flexible_box_layout)、[段組み](/ja/docs/Web/CSS/CSS_multicol_layout)、[グリッド](/ja/docs/Web/CSS/CSS_grid_layout)レイアウト +- [アニメーション](/ja/docs/Web/CSS/animation)、[トランジション](/ja/docs/Web/CSS/CSS_transitions)、[座標変換](/ja/docs/Web/CSS/CSS_transforms) ## 料理帳 @@ -84,6 +78,5 @@ CSS 2.1 以降、仕様の範囲が大幅に拡大し、CSS モジュールご ## 関連情報 -- [CSS のデモ](/ja/docs/Web/Demos#css): 最新の CSS テクノロジーの例を探索して想像力をかきたてましょう。 - CSS がよく適用されるウェブ言語。[HTML](/ja/docs/Web/HTML)、[SVG](/ja/docs/Web/SVG)、[MathML](/ja/docs/Web/MathML)、{{Glossary("XHTML")}}、[XML](/ja/docs/Web/XML/XML_introduction) - [CSS に関する Stack Overflow の質問](https://stackoverflow.com/questions/tagged/css) diff --git a/files/ja/web/javascript/reference/operators/optional_chaining/index.md b/files/ja/web/javascript/reference/operators/optional_chaining/index.md index 89ba1216da569e..ef8ed4de73d5fc 100644 --- a/files/ja/web/javascript/reference/operators/optional_chaining/index.md +++ b/files/ja/web/javascript/reference/operators/optional_chaining/index.md @@ -1,46 +1,44 @@ --- title: オプショナルチェーン (?.) slug: Web/JavaScript/Reference/Operators/Optional_chaining +l10n: + sourceCommit: 8cb0caef8175e1772f13ef7bc761f9616e2c5a4b --- -{{JSSidebar("Operators")}} +{{jsSidebar("Operators")}} -**オプショナルチェーン** (optional chaining) 演算子 (**`?.`**) は、接続されたオブジェクトチェーンの深くに位置するプロパティの値を、チェーン内の各参照が正しいかどうかを明示的に確認せずに読み込むことを可能にします。 +**オプショナルチェーン (`?.`)** (optional chaining) 演算子は、オブジェクトのプロパティにアクセスしたり、関数を呼び出したりします。この演算子を使用してアクセスするオブジェクトまたは呼び出される関数が {{jsxref("undefined")}} または [`null`](/ja/docs/Web/JavaScript/Reference/Operators/null) の場合、エラーが発生することなく、式が途中で終了し、{{jsxref("undefined")}} と評価されます。 -`?.` 演算子の機能は `.` チェーン演算子と似ていますが、参照が [nullish](/ja/docs/Glossary/Nullish) ([`null`](/ja/docs/Web/JavaScript/Reference/Operators/null) または {{JSxRef("undefined")}}) の場合にエラーとなるのではなく、式が短絡され `undefined` が返されるところが異なります。関数呼び出しで使用すると、与えられた関数が存在しない場合、 `undefined` を返します。 - -これは、参照が失われた可能性のある連結されたプロパティにアクセスする時、結果的に短く単純な式になります。また、必要なプロパティの存在が保証されていない場合にオブジェクトのコンテンツを探索するのにも役立ちます。 - -オプショナルチェーンは、宣言されていないルートオブジェクトでは使用できませんが、未定義のルートオブジェクトで使用できます。 - -{{EmbedInteractiveExample("pages/js/expressions-optionalchainingoperator.html", - "taller")}} +{{EmbedInteractiveExample("pages/js/expressions-optionalchainingoperator.html", "taller")}} ## 構文 -```js -obj.val?.prop; -obj.val?.[expr]; -obj.arr?.[index]; -obj.func?.(args); +```js-nolint +obj.val?.prop +obj.val?.[expr] +obj.func?.(args) ``` ## 解説 -オプショナルチェーン演算子は、参照や関数が `undefined` または `null` である可能性がある場合でも、接続されたオブジェクトの値に簡単にアクセスする手段を提供します。 +`?.` 演算子の機能は `.` チェーン演算子と似ていますが、参照が [nullish](/ja/docs/Glossary/Nullish) ([`null`](/ja/docs/Web/JavaScript/Reference/Operators/null) または {{jsxref("undefined")}}) の場合にエラーとなるのではなく、式が短絡され `undefined` が返されるところが異なります。関数呼び出しで使用すると、与えられた関数が存在しない場合、 `undefined` を返します。 + +これは、参照が失われた可能性のある連結されたプロパティにアクセスする時、結果的に短く単純な式になります。また、必要なプロパティの存在が保証されていない場合にオブジェクトのコンテンツを探索するのにも役立ちます。 たとえば、入れ子構造を持つオブジェクト `obj` を考えましょう。オプショナルチェーン演算子なしで深い入れ子になったサブプロパティにアクセスするには、次のように、各プロパティ間の参照を確認する必要があります。 ```js -let nestedProp = obj.first && obj.first.second; +const nestedProp = obj.first && obj.first.second; ``` -`obj.first.second` の値にアクセスする前に、 `obj.first` の値が `null` または `undefined` でないことを確認します。これにより、 `obj.first` をテストせず `obj.first.second` にアクセスしたときに起きるエラーを防ぐことができます。 +`obj.first` の値が `null` ではない(そして `undefined` でもない)ことが確認された後で、`obj.first.second` の値にアクセスします。これにより、`obj.first` をテストせずに直接 `obj.first.second` にアクセスした場合に発生するエラーを防ぐことができます。 -しかし、オプショナルチェーン演算子 (`?.`) を使えば、`obj.first.second` にアクセスしようとする前に `obj.first` の状態を明示的にテストする必要がなくなります。

+これは JavaScript でよく使われるパターンですが、チェーンが長くなると冗長になり、安全ではありません。例えば、`obj.first` が{{Glossary("Falsy", "偽")}}値で、`null` や `undefined` ではない値(例えば `0`)であった場合、それでも短絡となり、`nestedProp` が `0` になります。これは望ましくないかもしれません。 + +しかし、オプショナルチェーン演算子 (`?.`) を使えば、`obj.first.second` にアクセスしようとする前に `obj.first` の状態を明示的にテストする必要がなくなります。 ```js -let nestedProp = obj.first?.second; +const nestedProp = obj.first?.second; ``` `?.` を `.` の代わりに用いることで、 JavaScript が `obj.first.second` にアクセスしようとする前に `obj.first` が `null` または `undefined` でないことを暗黙的に確かめるようになります。`obj.first` が `null` または `undefined` であった場合、式が自動的に短絡され、 `undefined` が返ります。 @@ -48,8 +46,15 @@ let nestedProp = obj.first?.second; これは、一時的な変数が作成されないことを除き、次の式と等価です。 ```js -let temp = obj.first; -let nestedProp = temp === null || temp === undefined ? undefined : temp.second; +const temp = obj.first; +const nestedProp = + temp === null || temp === undefined ? undefined : temp.second; +``` + +オプションチェーンは、宣言されていないルートオブジェクトでは使用できませんが、値が `undefined` のルートオブジェクトでは使用することができます。 + +```js example-bad +undeclaredVar?.prop; // ReferenceError: undeclaredVar is not defined ``` ### 関数呼び出しにおけるオプショナルチェーン演算子 @@ -59,65 +64,107 @@ let nestedProp = temp === null || temp === undefined ? undefined : temp.second; 関数呼び出しでオプショナルチェーン演算子を用いた場合、メソッドが見つからないときは自動的に `undefined` が返り、例外は発生しません。 ```js -let result = someInterface.customMethod?.(); +const result = someInterface.customMethod?.(); ``` +しかし、そのような名前のプロパティが関数でない場合、`?.` を使用しても、{{jsxref("TypeError")}} 例外 "someInterface.customMethod is not a function" が発生します。 + > [!NOTE] -> 関数ではない名前のプロパティがあった場合、 `?.` を使用すると {{JSxRef("TypeError")}} 例外が発生します -> (`someInterface.customMethod is not a function`)。 +> 関数ではない名前のプロパティがあった場合、 `?.` を使用すると {{jsxref("TypeError")}} 例外が発生します ("someInterface is null")。 +> もし `someInterface` 自体が `null` または `undefined` である可能性がある場合は、この位置にも `?.` を使用する必要があります。つまり、`someInterface?.customMethod?.()` のように指定します。 -> **メモ:** `someInterface` 自体が `null` または `undefined` である場合にも、 {{JSxRef("TypeError")}} 例外が発生します (`someInterface is null`)。 `someInterface` 自体が `null` または `undefined` である可能性がある場合は、この位置にも `?.` を使用して `someInterface?.customMethod?.()` のようにする必要があります。 +`eval?.()` は[_間接的 eval_](/ja/docs/Web/JavaScript/Reference/Global_Objects/eval#直接的または間接的な_eval) モードに入るための最短の方法です。 -#### 省略可能なコールバックやイベントハンドラーの扱い +### オプショナルチェーン演算子と式の組み合わせ -

コールバックを使う場合や、オブジェクトからメソッドを分割代入を利用して取り出す場合に、存在しない値がある可能性があり、その存在を検証するまで関数として呼び出せません。その場合 `?.` を利用することで、検証の必要性を回避できます。 +[ブラケット記法](/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 の [`