diff --git a/files/ja/web/api/event/preventdefault/index.md b/files/ja/web/api/event/preventdefault/index.md index 0a456f9300dda6..de87e93e0aec1b 100644 --- a/files/ja/web/api/event/preventdefault/index.md +++ b/files/ja/web/api/event/preventdefault/index.md @@ -3,10 +3,10 @@ title: "Event: preventDefault() メソッド" short-title: preventDefault() slug: Web/API/Event/preventDefault l10n: - sourceCommit: 32b07aa5b6ac4799a88e7b87a4d8333643ab6427 + sourceCommit: 15f0b5552bc9c2ea1f32b0cd5ee840a7d43c887e --- -{{apiref("DOM")}} +{{APIRef("DOM")}}{{AvailableInWorkers}} **`preventDefault()`** は {{domxref("Event")}} インターフェイスのメソッドで、{{Glossary("user agent", "ユーザーエージェント")}}に、このイベントが明示的に処理されない場合に、その既定のアクションを通常どおりに行うべきではないことを伝えます。 @@ -78,7 +78,7 @@ function checkboxClick(event) { #### CSS -ユーザが無効なキーを押したときに描画する警告ボックスには、CSS を少し使用します。 +ユーザーが無効なキーを押したときに描画する警告ボックスには、CSS を少し使用します。 ```css .warning { diff --git a/files/ja/web/api/eventtarget/addeventlistener/index.md b/files/ja/web/api/eventtarget/addeventlistener/index.md index bce731ab8c42f2..10ca0498277c04 100644 --- a/files/ja/web/api/eventtarget/addeventlistener/index.md +++ b/files/ja/web/api/eventtarget/addeventlistener/index.md @@ -1,15 +1,16 @@ --- title: "EventTarget: addEventListener() メソッド" +short-title: addEventListener() slug: Web/API/EventTarget/addEventListener l10n: - sourceCommit: 339595951b78774e951b1a9d215a6db6b856f6b2 + sourceCommit: ded971d7fec855c2b81fde8809172697f2e227c1 --- -{{APIRef("DOM")}} +{{APIRef("DOM")}}{{AvailableInWorkers}} **`addEventListener()`** は {{domxref("EventTarget")}} インターフェイスのメソッドで、ターゲットに特定のイベントが配信されるたびに呼び出される関数を設定します。 -対象としてよくあるものは {{domxref("Element")}}、{{domxref("Document")}}、{{domxref("Window")}} ですが、イベントに対応したあらゆるオブジェクトが対象になることができます ({{domxref("XMLHttpRequest")}} など)。 +対象としてよくあるものは {{domxref("Element")}}、{{domxref("Document")}}、{{domxref("Window")}} ですが、イベントに対応したあらゆるオブジェクトが対象になることができます({{domxref("IDBRequest")}} など)。 > **メモ:** `addEventListener()` メソッドは、イベントリスナーを登録するための*推奨される*方法です。以下のような長所があります。 > @@ -17,7 +18,7 @@ l10n: > - `onXYZ` プロパティを使用するのとは対照的に、リスナーが起動されるときのフェーズ(キャプチャとバブリング)をより細かく制御できます。 > - HTML や SVG の要素だけでなく、あらゆるイベントターゲットで動作します。 -`addEventListener()` は関数または {{domxref("EventTarget.addEventListener", "EventListener")}} を実装したオブジェクトを、呼び出される {{domxref("EventTarget")}} における指定されたイベント種別のイベントリスナーのリストに加えることで動作します。その関数やオブジェクトが既にターゲットのイベントリスナーのリストにあった場合は、その関数やオブジェクトが二重に追加されることはありません。 +`addEventListener()` メソッドは、関数または `handleEvent()` 関数を実装したオブジェクトを、呼び出される {{domxref("EventTarget")}} における指定されたイベント種別のイベントリスナーのリストに加えることで動作します。その関数やオブジェクトが既にターゲットのイベントリスナーのリストにあった場合は、その関数やオブジェクトが二重に追加されることはありません。 > **メモ:** ある無名関数が特定のターゲットでイベントリスナーのリストに登録されており、後のコードで同じ無名関数が `addEventListener` の呼び出しに指定された場合、2 つ目の関数*も*そのターゲットのイベントリスナーのリストに追加されます。 > @@ -41,17 +42,22 @@ addEventListener(type, listener, useCapture) - `type` - : 対象とする[イベントの種類](/ja/docs/Web/Events)を表す文字列です。 - `listener` - - : 指定された種類のイベントが発生するときに通知({{domxref("Event")}} インターフェースを実装しているオブジェクト)を受け取るオブジェクト。これは `null` であるか、`handleEvent()` メソッドのあるオブジェクトか、JavaScript の[関数](/ja/docs/Web/JavaScript/Guide/Functions)の何れかでなければなりません。コールバックについて詳しくは、[イベントリスナーのコールバック](#イベントリスナーのコールバック)を参照してください。 + - : 指定された種類のイベントが発生するときに通知({{domxref("Event")}} インターフェイスを実装しているオブジェクト)を受け取るオブジェクト。これは `null` であるか、`handleEvent()` メソッドのあるオブジェクトか、JavaScript の[関数](/ja/docs/Web/JavaScript/Guide/Functions)のいずれかでなければなりません。コールバックについて詳しくは、[イベントリスナーのコールバック](#イベントリスナーのコールバック)を参照してください。 - `options` {{optional_inline}} - - : 対象のイベントリスナーの特性を指定する、オプションのオブジェクトです。次のオプションが使用できます。 + - : 対象のイベントリスナーの特性を指定する、オプションのオブジェクトです。 + 次のオプションが使用できます。 - `capture` {{optional_inline}} - : 論理値で、この型のイベントが DOM ツリーで下に位置する `EventTarget` に配信 (dispatch) される前に、登録された `listener` に配信されることを示します。指定されていない場合は、既定で `false` になります。 - `once` {{optional_inline}} - : 論理値で、 `listener` の呼び出しを一回のみのとしたいかどうかを値で指定します。 `true` を指定すると、 `listener` は一度実行された時に自動的に削除されます。指定されていない場合は、既定で `false` になります。 - `passive` {{optional_inline}} - - : 論理値で、 `true` ならば、 `listener` で指定された関数が {{domxref("Event.preventDefault", "preventDefault()")}} を呼び出さないことを示します。呼び出されたリスナーが `preventDefault()` を呼び出すと、ユーザーエージェントは何もせず、コンソールに警告を出力します。指定されていない場合、既定で `false` になります。ただし、Safari 以外のブラウザーでは、{{domxref("Element/wheel_event", "wheel")}}、{{domxref("Element/mousewheel_event", "mousewheel")}}、{{domxref("Element/touchstart_event", "touchstart")}}、{{domxref("Element/touchmove_event", "touchmove")}} の各イベントでは `true` になります。詳細は[パッシブリスナーによるスクロールの性能改善](#パッシブリスナーによるスクロールの性能改善)をご覧ください。 + + - : 論理値で、`true` ならば、 `listener` で指定された関数が {{domxref("Event.preventDefault", "preventDefault()")}} を呼び出さないことを示します。呼び出されたリスナーが `preventDefault()` を呼び出すと、ユーザーエージェントは何もせず、コンソールに警告を出力します。 + + このオプションが指定されていない場合、既定で `false` になります。ただし、Safari 以外のブラウザーでは、{{domxref("Element/wheel_event", "wheel")}}、{{domxref("Element/mousewheel_event", "mousewheel")}}、{{domxref("Element/touchstart_event", "touchstart")}}、{{domxref("Element/touchmove_event", "touchmove")}} の各イベントでは `true` になります。詳細は[パッシブリスナーの使用](#パッシブリスナーの使用)をご覧ください。 + - `signal` {{optional_inline}} - : {{domxref("AbortSignal")}} です。指定された `AbortSignal` オブジェクトの {{domxref("AbortController/abort()", "abort()")}} メソッドが呼び出された時に、リスナーが削除されます。指定されていない場合は、`AbortSignal` がリスナーに関連付けられません。 @@ -61,10 +67,10 @@ addEventListener(type, listener, useCapture) 指定されていない場合、 `useCapture` は既定で `false` となります。 > **メモ:** イベントターゲットに登録されたイベントリスナーは、キャプチャフェーズやバブリングフェーズではなく、ターゲットフェーズのイベントになります。 - > キャプチャリングフェーズのイベントリスナーは、キャプチャリングフェーズ以外のイベントリスナーよりも先に呼び出されます。 + > キャプチャフェーズのイベントリスナーは、キャプチャフェーズ以外のイベントリスナーよりも先に呼び出されます。 - `wantsUntrusted` {{optional_inline}} {{non-standard_inline}} - - : `true` の場合、このリスナーはウェブコンテンツによって発行された合成イベント (カスタムイベント) を受け取ります (ブラウザーの{{glossary("chrome", "クローム")}}では既定で `false` ですが、一般のウェブページでは `true` です)。この引数は、主にアドオンやブラウザー自身の役に立つものです。 + - : Firefox (Gecko) 独自の引数です。`true` の場合、このリスナーはウェブコンテンツによって発行された合成イベント (カスタムイベント) を受け取ります (ブラウザーの{{glossary("chrome", "クローム")}}では既定で `false` ですが、一般のウェブページでは `true` です)。この引数は、主にアドオンやブラウザー自身の役に立つものです。 ### 返値 @@ -74,18 +80,18 @@ addEventListener(type, listener, useCapture) ### イベントリスナーのコールバック -イベントリスナーには、コールバック関数または `handleEvent()` メソッドを持つオブジェクトの何れかをコールバック関数として指定することができます。 +イベントリスナーには、コールバック関数または `handleEvent()` メソッドを持つオブジェクトのいずれかをコールバック関数として指定することができます。 コールバック関数自体は、 `handleEvent()` メソッドと同じ引数と返値を持ちます。つまり、コールバック関数は発生したイベントを説明する {{domxref("Event")}} に基づくオブジェクトを唯一の引数として受け付け、何も返しません。 たとえば、次のイベントハンドラーコールバックは、 {{domxref("Element/fullscreenchange_event", "fullscreenchange")}} および {{domxref("Element/fullscreenerror_event", "fullscreenerror")}} の両方を処理するために使用することができます。 ```js -function eventHandler(event) { +function handleEvent(event) { if (event.type === "fullscreenchange") { - /* handle a full screen toggle */ + /* 全画面モードへの切り替えを処理 */ } else { - /* handle a full screen toggle error */ + /* 全画面モードへの切り替えエラーを処理 */ } } ``` @@ -134,9 +140,208 @@ someElement.addEventListener( ここでは、 {{domxref("Element/mouseup_event", "mouseup")}} イベントのリスナーを `someElement` 要素に追加しています。第 3 引数の `passiveSupported` が `true` である場合、 `options` オブジェクトを `passive` を `true` に設定して指定しています。そうでない場合は、論理値を渡す必要があることがわかっているので、 `useCapture` 引数の値として `false` を渡しています。 -ご希望であれば、 [Modernizr](https://modernizr.com/docs) や [Detect It](https://github.com/rafgraph/detect-it) のようなサードパーティ製のライブラリーを使用してこのテストを行うことができます。 +[機能検出の実装](/ja/docs/Learn/Tools_and_testing/Cross_browser_testing/Feature_detection)のドキュメントや [Web Incubator Community Group](https://wicg.github.io/admin/charter.html) の [`EventListenerOptions`](https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md#feature-detection) に関する説明で詳しく学ぶことができます。 + +### ハンドラー内での "this" の値 + +イベントハンドラーが発行された要素を参照することはよくあることで、似たような要素の設定に汎用ハンドラーを使用する場合などに便利です。 + +ハンドラー関数を `addEventListener()` を使用して要素に装着する場合、ハンドラー内の {{jsxref("Operators/this","this")}} の値は要素を参照します。ハンドラーに渡すイベント引数の `currentTarget` プロパティの値と同じになります。 + +```js +my_element.addEventListener("click", function (e) { + console.log(this.className); // my_element の className をログ出力 + console.log(e.currentTarget === this); // `true` をログ出力 +}); +``` + +注意点として、[アロー関数は自分自身で `this` コンテキストを持つことはありません](/ja/docs/Web/JavaScript/Reference/Functions/Arrow_functions#メソッドとしては使用不可)。 + +```js +my_element.addEventListener("click", (e) => { + console.log(this.className); // 警告: `this` は `my_element` ではない + console.log(e.currentTarget === this); // `false` をログ出力 +}); +``` + +イベントハンドラー(例えば、{{domxref("Element.click_event", "onclick")}})が HTML ソースの要素に指定されている場合、属性値の JavaScript コードは実質的にハンドラー関数にラップされ、`addEventListener()` と整合する方法で `this` の値にバインドされます。コード内に `this` が現れた場合は、要素への参照を表します。 + +```html + + + … +
+``` + +属性値内のコードによって呼び出された関数内の `this` の値は、[標準ルール](/ja/docs/Web/JavaScript/Reference/Operators/this) に従って動作することに注意してください。これは次の例で表示されます。 + +```html + + + + … +
+``` + +`logID()` 内の `this` の値はグローバルオブジェクト {{domxref("Window")}} への参照です([厳格モード](/ja/docs/Web/JavaScript/Reference/Strict_mode)の場合は `undefined`)。 + +#### bind() を使用した "this" の設定 + +{{jsxref("Function.prototype.bind()")}} メソッドを使用すると、修正された `this` コンテキストをその後のすべての呼び出しに使用することができます。ただし、リスナーへの参照を保持しておく必要があることに注意してください。 -[Web Incubator Community Group](https://wicg.github.io/admin/charter.html) の [`EventListenerOptions`](https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md#feature-detection) の記事を参考にしてください。 +これは `bind()` を使用した例と使用しない例です。 + +```js +class Something { + name = "Something Good"; + constructor(element) { + // bind によって、修正された `this` コンテキストを `onclick2` に代入される + this.onclick2 = this.onclick2.bind(this); + element.addEventListener("click", this.onclick1, false); + element.addEventListener("click", this.onclick2, false); // Trick + } + onclick1(event) { + console.log(this.name); // undefined(`this` が要素であるため) + } + onclick2(event) { + console.log(this.name); // 'Something Good'(`this` が Something インターフェイスに結び付けられているため) + } +} + +const s = new Something(document.body); +``` + +もう一つの解決策は、`handleEvent()` と呼ばれる特別な関数を使用してイベントを捕捉することです。 + +```js +class Something { + name = "Something Good"; + constructor(element) { + // この場合のリスナーは `this` であり、 this.handleEvent ではないことに注意 + element.addEventListener("click", this, false); + element.addEventListener("dblclick", this, false); + } + handleEvent(event) { + console.log(this.name); // 'Something Good'(新しく作成されたオブジェクトに結び付けられているため) + switch (event.type) { + case "click": + // ここにいくらかのコード… + break; + case "dblclick": + // ここにいくらかのコード… + break; + } + } +} + +const s = new Something(document.body); +``` + +`this` への参照を処理するもう一つの方法は、別個の `this` コンテキストを作成しないアロー関数を使用することです。 + +```js +class SomeClass { + name = "Something Good"; + + register() { + window.addEventListener("keydown", (e) => { + this.someMethod(e); + }); + } + + someMethod(e) { + console.log(this.name); + switch (e.code) { + case "ArrowUp": + // ここにいくらかのコード… + break; + case "ArrowDown": + // ここにいくらかのコード… + break; + } + } +} + +const myObject = new SomeClass(); +myObject.register(); +``` + +### イベントリスナーのデータの出し入れ + +イベントリスナーは {{domxref("Event")}} または `Event` のサブクラスの引数を 1 つだけ取りますが、これは自動的にリスナーに渡され、返値は無視されます。 +したがって、イベントリスナーにデータを取得したり、イベントリスナーからデータを取得したりするには、引数と返値でデータを渡すのではなく、代わりに[クロージャ](/ja/docs/Web/JavaScript/Closures)を作成する必要があります。 + +イベントリスナーとして渡された関数は、その関数を格納する外部スコープで宣言されたすべての変数にアクセスすることができます。 + +```js +const myButton = document.getElementById("my-button-id"); +let someString = "Data"; + +myButton.addEventListener("click", () => { + console.log(someString); + // 最初のクリックでは 'Data' となり、 + // 2 番目のクリックでは 'Data Again' となる + + someString = "Data Again"; +}); + +console.log(someString); // 期待される値: 'Data' ('Data Again' とはならない) +``` + +関数スコープに関する詳細情報は、[関数ガイド](/ja/docs/Web/JavaScript/Guide/Functions#関数のスコープ)をお読みください。 + +### メモリーの問題 + +```js +const elts = document.getElementsByTagName("*"); + +// ケース 1 +for (const elt of elts) { + elt.addEventListener( + "click", + (e) => { + // 何かを行う + }, + false, + ); +} + +// ケース 2 +function processEvent(e) { + // 何かを行う +} + +for (const elt of elts) { + elt.addEventListener("click", processEvent, false); +} +``` + +上記の 1 つ目のケースでは、ループの繰り返しごとに新しい(無名の)ハンドラー関数が作成されます。一方、 2 つ目のケースでは、以前に宣言した同じ関数がイベントハンドラーとして使用され、作成されるハンドラー関数が 1 つであるため、メモリー消費量が少なくなります。さらに、最初のケースでは、無名関数への参照が保持されないため、 {{domxref("EventTarget.removeEventListener", "removeEventListener()")}} を呼び出すことができません(ここでは、ループが生成する可能性がある複数の無名関数への参照が保持されません)。2 番目のケースでは、`processEvent` が関数の参照なので、`myElement.removeEventListener("click", processEvent, false)` を実行することが可能です。 + +実は、メモリー消費に関しては、関数参照を保持しないことが本当の問題ではなく、むしろ、*静的*な関数参照を保持しないことが問題なのです。 + +### パッシブリスナーの使用 + +イベントに既定のアクションがある場合、例えば、既定でコンテナーをスクロールする {{domxref("Element/wheel_event", "wheel")}} イベントの場合、イベントリスナーが {{domxref("Event.preventDefault()")}} を呼び出して既定のアクションをキャンセルするかどうかを事前に知ることができないため、ブラウザーは一般的にイベントリスナーが完了するまで既定のアクションを開始することができません。イベントリスナーの実行に時間がかかりすぎると、既定のアクションが実行されるまでに、{{glossary("jank", "ジャンク")}}と呼ばれる顕著な遅延が発生する可能性があります。 + +`passive` オプションを `true` に設定することで、イベントリスナーは既定のアクションを取り消される可能性がないことを宣言します。リスナーが {{domxref("Event.preventDefault()")}} を呼び出しても、効果はありません。 + +`addEventListener()` の仕様書では、`passive` オプションの既定値は常に `false` であると定義しています。しかし、パッシブリスナーのスクロールパフォーマンスの利点を古いコードで実現するために、最近のブラウザーでは {{domxref("Element/wheel_event", "wheel")}}、{{domxref("Element/mousewheel_event", "mousewheel")}}、{{domxref("Element/touchstart_event", "touchstart")}}、{{domxref("Element/touchmove_event", "touchmove")}} の各イベントの `passive` オプションの既定値が、文書レベルノード {{domxref("Window")}}、{{domxref("Document")}}、{{domxref("Document.body")}} においては `true` に変更されています。これにより、イベントリスナーが[イベントが取り消される可能性](/ja/docs/Web/API/Event/preventDefault)を防ぐことができるので、ユーザーがスクロールしている間にページのレンダリングをブロックすることはありません。 + +そのため、(既定値に頼らずに)その動作を上書きして `passive` オプションを確実に `false` にしたい場合は、明示的にこのオプションを `false` に設定する必要があります。 + +基本的な {{domxref("Element/scroll_event", "scroll")}} イベントについて、`passive` の値を気にする必要はありません。 +取り消される可能性がないため、イベントリスナーがページのレンダリングをブロックすることはありません。 + +パッシブリスナーの効果を示す例については[パッシブリスナーによるスクロールの性能改善](#パッシブリスナーによるスクロールの性能改善)を参照してください。 + +### 古いブラウザーの場合 + +`addEventListener()` の引数 `options` に対応していない古いブラウザーでは、これを使用しようとすると、[機能検出](#オプションの対応の安全な検出)を適切に使用しない限り、引数 `useCapture` が使用できなくなります。 ## 例 @@ -172,7 +377,7 @@ const el = document.getElementById("outside"); el.addEventListener("click", modifyText, false); ``` -このコードの中で、 `modifyText()` が `addEventListener()` を使用して登録された `click` イベントのリスナーです。表の中のどこかをクリックすると、ハンドラーまでバブリングし、 `modifyText()` が実行されます。 +このコードの中で、 `modifyText()` は `click` イベントのリスナーであり、`addEventListener()` を使用して登録されています。表の中のどこかをクリックすると、ハンドラーまでバブリングし、`modifyText()` が実行されます。 #### 結果 @@ -215,7 +420,7 @@ function modifyText() { } ``` -上の例では、2 行目の内容が "three" に変わった後に、 `addEventListener()` に渡した {{domxref("AbortController")}} から `abort()` を呼び出すようにコードを変更しました。その結果、クリックイベントを待ち受けするコードがなくなったので、値は永遠に "three" のままとなります。 +上の例では、2 行目のコンテンツが "three" に変更された後に、 `addEventListener()` の呼び出しに渡した {{domxref("AbortController")}} から `abort()` を呼び出すように、前回のコードを変更しています。その結果、クリックイベントを待ち受けするコードがなくなったので、値は永遠に "three" のままとなります。 #### 結果 @@ -266,7 +471,7 @@ el.addEventListener( ### アロー関数を使用したイベントリスナー -この例はアロー関数表記を使用して実装された、簡単なイベントリスナーを紹介しています。 +この例はアロー関数記法を使用して実装された、簡単なイベントリスナーを紹介しています。 #### HTML @@ -305,7 +510,7 @@ el.addEventListener( {{EmbedLiveSample('Event_listener_with_an_arrow_function')}} -なお、無名関数とアロー関数は似ており、違いは `this` を結び付けるかどうかです。無名関数 (および従来のすべての JavaScript 関数) は固有の `this` を作成するのに対し、アロー関数はそれを含む関数の `this` を継承します。 +なお、無名関数とアロー関数は似ており、違いは `this` を結び付けるかどうかです。無名関数(および従来のすべての JavaScript 関数)は固有の `this` を作成するのに対し、アロー関数はそれを含む関数の `this` を継承します。 つまり、アロー関数を使用したときは、それを含む関数の変数や定数をイベントハンドラーで利用することができます。 @@ -319,13 +524,16 @@ el.addEventListener(
middle, capture & none-capture - inner1, passive & preventDefault(which is not allowed) + inner1, パッシブ & preventDefault(許可されていない) - inner2, none-passive & preventDefault(not open new page) + inner2, パッシブ & preventDefault(新しいページを開かない)
+
+ +
``` #### CSS @@ -358,8 +566,31 @@ el.addEventListener( } ``` +```css hidden +.demo-logs { + width: 530px; + height: 16rem; + background-color: #ddd; + overflow-x: auto; + padding: 1rem; +} +``` + #### JavaScript +```js hidden +const clearBtn = document.querySelector(".clear-button"); +const demoLogs = document.querySelector(".demo-logs"); + +function log(msg) { + demoLogs.innerText += `${msg}\n`; +} + +clearBtn.addEventListener("click", () => { + demoLogs.innerText = ""; +}); +``` + ```js const outer = document.querySelector(".outer"); const middle = document.querySelector(".middle"); @@ -393,27 +624,27 @@ inner1.addEventListener("click", passiveHandler, passive); inner2.addEventListener("click", nonePassiveHandler, nonePassive); function onceHandler(event) { - alert("outer, once"); + log("outer、once"); } function noneOnceHandler(event) { - alert("outer, none-once, default"); + log("outer、非 once、既定値\n"); } function captureHandler(event) { //event.stopImmediatePropagation(); - alert("middle, capture"); + log("middle、capture"); } function noneCaptureHandler(event) { - alert("middle, none-capture, default"); + log("middle、非 capture、既定値"); } function passiveHandler(event) { - // Unable to preventDefault inside passive event listener invocation. + // パッシブイベントリスナーの呼び出しの中では preventDefault は実行できない event.preventDefault(); - alert("inner1, passive, open new page"); + log("inner1、passive、新しいページを開く"); } function nonePassiveHandler(event) { event.preventDefault(); //event.stopPropagation(); - alert("inner2, none-passive, default, not open new page"); + log("inner2、非 passive、既定値、新しいページを開かない"); } ``` @@ -421,7 +652,7 @@ function nonePassiveHandler(event) { 外側、中央、内側のコンテナーをそれぞれクリックして、オプションがどのように動作するかを確認してください。 -{{ EmbedLiveSample('Example_of_options_usage', 600, 310, '') }} +{{ EmbedLiveSample('options_の使い方の例', 600, 630) }} `options` オブジェクトで特定の値を使用する前に、ユーザーのブラウザーがその値に対応していることを確認するのが良いでしょう。これらは歴史的にすべてのブラウザーがサポートしてきたわけではない追加要素であるからです。詳細は[オプションの対応の安全な検出](#オプションの対応の安全な検出)を参照してください。 @@ -481,292 +712,96 @@ addListener(); {{EmbedLiveSample('Event_listener_with_multiple_options')}} -## その他の注意事項 - -### ハンドラー内での "this" の値 - -一連の類似した要素に対して一般的なハンドラーを使いたい場合のように、イベントハンドラーが実行される要素を参照したいということがたびたびあります。 - -ハンドラー関数を `addEventListener()` を使って要素に装着したとき、ハンドラーの中の {{jsxref("Operators/this","this")}} の値は要素への参照となります。これはハンドラーに渡された event 引数の `currentTarget` プロパティの値と同じです。 - -```js -my_element.addEventListener("click", function (e) { - console.log(this.className); // logs the className of my_element - console.log(e.currentTarget === this); // logs `true` -}); -``` - -[アロー関数は独自の `this` コンテキストを持たない](/ja/docs/Web/JavaScript/Reference/Functions/Arrow_functions#メソッドとして使われるアロー関数)ことをお忘れなく。 - -```js -my_element.addEventListener("click", (e) => { - console.log(this.className); // WARNING: `this` is not `my_element` - console.log(e.currentTarget === this); // logs `false` -}); -``` - -イベントハンドラー(例えば {{domxref("Element.click_event", "onclick")}})が HTML ソース内の要素に指定されていた場合、属性値の JavaScript コードは、 `addEventListener()` を使用するような方法で `this` の値を結び付けたハンドラー関数に置き換えられます。コード内に `this` が現れた場合には、要素への参照を表します。 +### パッシブリスナーによるスクロールの性能改善 -```html - - - … -
-``` +次の例は `passive` を設定した効果を示しています。テキストとチェックボックスを含む {{htmlelement("div")}} があります。 -`this` の値は、属性値の中のコード*によって呼び出される*関数内では、[標準的な規則](/ja/docs/Web/JavaScript/Reference/Operators/this)に従って動作することに注意してください。これは次の例で示されています。 +#### HTML ```html - - - - … -
-``` - -`this` は `logID()` 内においては、グローバルオブジェクト {{domxref("Window")}} (または[厳格モード](/ja/docs/Web/JavaScript/Reference/Strict_mode)の場合は `undefined` になります。 - -#### bind() を使用した this の指定 - -{{jsxref("Function.prototype.bind()")}} メソッドで、その関数のすべての呼び出しにおいて `this` として使用される値を指定できます。これを使えば、関数がどこから呼び出されるかによって `this` の値が変わってしまうというややこしい問題を簡単に回避できます。ただし、リスナーを後で削除できるように、そのリスナーへの参照を残しておく必要があります。 - -以下は `bind()` を使った場合と使わない場合の例です。 - -```js -const Something = function (element) { - // |this| is a newly created object - this.name = "Something Good"; - this.onclick1 = function (event) { - console.log(this.name); // this は element なので undefined になります - }; - - this.onclick2 = function (event) { - console.log(this.name); // this は新しく生成されたオブジェクトに結び付けられているので、 'Something Good' と出力されます - }; - - // bind によって、固定の `this` コンテキストを onclick2 に割り当てる - this.onclick2 = this.onclick2.bind(this); - - element.addEventListener("click", this.onclick1, false); - element.addEventListener("click", this.onclick2, false); // これが仕掛けです -}; -const s = new Something(document.body); -``` - -もうひとつの解決策は、あらゆるイベントを捕捉する `handleEvent()` という特別な関数を使用することです。 - -```js -const Something = function (element) { - // |this| is a newly created object - this.name = "Something Good"; - this.handleEvent = function (event) { - console.log(this.name); // this は新しく生成されたオブジェクトに結び付けられているので、 'Something Good' と出力されます - switch (event.type) { - case "click": - // 処理 - break; - case "dblclick": - // 処理 - break; - } - }; - - // この場合のリスナーは this であって this.handleEvent でないことに注意してください - element.addEventListener("click", this, false); - element.addEventListener("dblclick", this, false); +
+

+ But down there it would be dark now, and not the lovely lighted aquarium she + imagined it to be during the daylight hours, eddying with schools of tiny, + delicate animals floating and dancing slowly to their own serene currents + and creating the look of a living painting. That was wrong, in any case. The + ocean was different from an aquarium, which was an artificial environment. + The ocean was a world. And a world is not art. Dorothy thought about the + living things that moved in that world: large, ruthless and hungry. Like us + up here. +

+
- // リスナーは適切に削除できます - element.removeEventListener("click", this, false); - element.removeEventListener("dblclick", this, false); -}; -const s = new Something(document.body); +
+ + +
``` -_this_ の参照を扱うためのもう一つの方法は、 `EventListener` にアクセスする必要のあるフィールドを含むオブジェクトのメソッドを呼び出す関数を渡すことです。 - -```js -class SomeClass { - constructor() { - this.name = "Something Good"; - } - - register() { - const that = this; - window.addEventListener("keydown", (e) => { - that.someMethod(e); - }); - } - - someMethod(e) { - console.log(this.name); - switch (e.keyCode) { - case 5: - // ここにいくらかのコード... - break; - case 6: - // ここにいくらかのコード... - break; - } - } +```css hidden +#container { + width: 150px; + height: 200px; + overflow: scroll; + margin: 2rem 0; + padding: 0.4rem; + border: 1px solid black; } - -const myObject = new SomeClass(); -myObject.register(); ``` -### イベントリスナーのデータの出し入れ - -イベントリスナーは離島のようなもので、データを渡すのも、ましてや実行後にデータを取り戻すのも至難の業だと思われるかもしれません。 -イベントリスナーは引数を、[イベントオブジェクト](/ja/docs/Learn/JavaScript/Building_blocks/Events#event_objects) 1 つしかとらず、これは自動的にリスナーに渡され、返値は無視されます。 -では、どのようにデータを取り込んだり、戻したりすればよいのでしょうか。これには良い方法がいくつかあります。 - -#### "this" を使用したイベントリスナーへのデータの入力 - -[前述](#bind_を使用した_this_の指定)の通り、 `Function.prototype.bind()` を使用すると `this` 参照変数を通じてイベントリスナーに値を渡すことができます。 - -```js -const myButton = document.getElementById("my-button-id"); -const someString = "Data"; - -myButton.addEventListener( - "click", - function () { - console.log(this); // 期待される値: 'Data' - }.bind(someString), -); -``` - -この方法は、イベントリスナーの中からプログラムでイベントリスナーがどの HTML 要素で発生したかを知る必要がない場合に適しています。これを行う主な利点は、実際に引数リストにデータを渡す場合とほぼ同じ方法でイベントリスナーがデータを受け取ることです。 - -#### 外部スコープのプロパティを使用したイベントリスナーへのデータの入力 +#### JavaScript -外部スコープに(`const`, `let` を付けた)変数宣言が含まれている場合、そのスコープで宣言されたすべての内部関数はその変数にアクセスすることができます(外部関数/内部関数については[こちら](/ja/docs/Glossary/Function#different_types_of_functions)を、変数スコープについては[こちら](/ja/docs/Web/JavaScript/Reference/Statements/var#暗黙のグローバル変数と関数スコープの外部)を参照してください)。したがって、イベントリスナーの外部からデータにアクセスする最も簡単な方法の 1 つは、イベントリスナーが宣言されているスコープにアクセスできるようにすることです。 +このコードは、コンテナーの {{domxref("Element/wheel_event", "wheel")}} イベントにリスナーを追加するもので、既定ではコンテナーをスクロールします。リスナーは長時間実行する処理を実行します。初期状態では、リスナーは `passive` オプションで追加され、チェックボックスがトグル切り替えされるたびに、コードは `passive` オプションをトグル切り替えします。 ```js -const myButton = document.getElementById("my-button-id"); -let someString = "Data"; - -myButton.addEventListener("click", () => { - console.log(someString); // 期待される値: 'Data' - - someString = "Data Again"; +const passive = document.querySelector("#passive"); +passive.addEventListener("change", (event) => { + container.removeEventListener("wheel", wheelHandler); + container.addEventListener("wheel", wheelHandler, { + passive: passive.checked, + once: true, + }); }); -console.log(someString); // 期待される値: 'Data' (will never output 'Data Again') -``` - -> **メモ:** 内側のスコープは外側のスコープにある `const`, `let` 変数にアクセスすることができますが、イベントリスナーの定義後に、同じ外側のスコープ内でこれらの変数にアクセスできるようになることは期待できません。なぜでしょうか?単純に、イベントリスナーが実行される頃には、イベントリスナーが定義されたスコープは既に実行を終了しているからです。 - -#### オブジェクトを用いたイベントリスナーのデータの出し入れ - -JavaScript のほとんどの関数とは異なり、オブジェクトはそのオブジェクトを参照する変数がメモリー内に存在する限り、メモリー内に保持されます。それに加えて、オブジェクトはプロパティを持つことができ、参照によって渡すことができることから、スコープ間でデータを共有するための有力な候補となります。これについて調べてみましょう。 - -> **メモ:** JavaScript の関数は厳密にはオブジェクトです。 (そのため、プロパティを持つことができ、メモリー内に永続的に存在する変数に代入されていれば、実行終了後もメモリー内に保持されます。) - -オブジェクトを参照する変数がメモリーに存在する限り、オブジェクトのプロパティを使用してメモリーにデータを格納することができるので、実際にそれらを使用して、イベントリスナーにデータを渡し、イベントハンドラーが実行された後でデータに変更があった場合には、それを戻すことができます。この例を考えてみましょう。 - -```js -const myButton = document.getElementById("my-button-id"); -const someObject = { aProperty: "Data" }; - -myButton.addEventListener("click", () => { - console.log(someObject.aProperty); // 期待される値: 'Data' - - someObject.aProperty = "Data Again"; // 値を変更 +const container = document.querySelector("#container"); +container.addEventListener("wheel", wheelHandler, { + passive: true, + once: true, }); -setInterval(() => { - if (someObject.aProperty === "Data Again") { - console.log("Data Again: True"); - someObject.aProperty = "Data"; // 次のイベントの実行を待つために値を初期化 +function wheelHandler() { + function isPrime(n) { + for (let c = 2; c <= Math.sqrt(n); ++c) { + if (n % c === 0) { + return false; + } + } + return true; } -}, 5000); -``` - -この例では、イベントリスナーとインターバル関数の両方が定義されているスコープは、 `someObject.aProperty` の元の値が変更される前に実行を終了していたとしても、イベントリスナーとインターバル関数の両方で `someObject` がメモリー内に (*参照*によって) 持続するため、両方とも同じデータにアクセスできます (つまり、一方がデータを変更したときに、もう一方がその変更に対応できます)。 - -> **メモ:** オブジェクトは参照で変数に格納されます。つまり、実際のデータのメモリーの場所だけが変数に格納されます。とりわけ、これはオブジェクトを「格納」する変数が、実際に同じオブジェクト参照が代入 (「格納」) されている他の変数に影響を与えることができるということです。 2 つの変数が同じオブジェクトを参照している場合 (例えば、 `let a = b = {aProperty: 'Yeah'};`)、どちらかから変数のデータを変更すると、もう一方の変数に影響を与えます。 - -> **メモ:** オブジェクトは参照によって変数に格納されているので、関数の実行を停止した後も、関数からオブジェクトを返す (データを失わないようにメモリーに保存しておく) ことができます。 - -### メモリーの問題 - -```js -const elts = document.getElementsByTagName("*"); -// ケース 1 -for (const elt of elts) { - elt.addEventListener( - "click", - (e) => { - // 何かを行う - }, - false, - ); -} + const quota = 1000000; + const primes = []; + const maximum = 1000000; -// ケース 2 -function processEvent(e) { - // 何かを行う -} + while (primes.length < quota) { + const candidate = Math.floor(Math.random() * (maximum + 1)); + if (isPrime(candidate)) { + primes.push(candidate); + } + } -for (const elt of elts) { - elt.addEventListener("click", processEvent, false); + console.log(primes); } ``` -上記の 1 つ目のケースでは、ループの繰り返しごとに新しい(無名の)ハンドラー関数が作成されます。一方、 2 つ目のケースでは、以前に宣言した同じ関数がイベントハンドラーとして使用され、作成されるハンドラー関数が 1 つであるため、メモリー消費量が少なくなります。さらに、最初のケースでは、無名関数への参照が保持されないため、 {{domxref("EventTarget.removeEventListener", "removeEventListener()")}} を呼び出すことができません(ここでは、ループが生成する可能性がある複数の無名関数への参照が保持されません)。2 番目のケースでは、`processEvent` が関数の参照なので、`myElement.removeEventListener("click", processEvent, false)` を実行することが可能です。 - -実は、メモリー消費に関しては、関数参照を保持しないことが本当の問題ではなく、むしろ、*静的*な関数参照を保持しないことが問題なのです。 - -### パッシブリスナーによるスクロールの性能改善 - -以下の例にあるように、`passive` の値を `true` に設定すると、パフォーマンスを最適化し、アプリケーションのパフォーマンスが劇的に向上する可能性があります。 - -```js -/* 機能検出 */ -let passiveIfSupported = false; - -try { - window.addEventListener( - "test", - null, - Object.defineProperty({}, "passive", { - get() { - passiveIfSupported = { passive: true }; - }, - }), - ); -} catch (err) {} - -window.addEventListener( - "scroll", - (event) => { - /* 何かを行う */ - // event.preventDefault(); は使用できない - }, - passiveIfSupported, -); -``` - -`addEventListener()` の仕様では、`passive` オプションの既定値は常に `false` です。しかし、これはタッチイベントやホイールイベントを扱うイベントリスナーがスクロールを処理しようとしている間にブラウザーのメインスレッドをブロックする可能性をもたらすため、スクロール処理中の性能が大幅に低下する結果になる可能性があります。 - -この問題を防ぐため、Safari 以外のブラウザーでは、文書レベルのノードである {{domxref("Window")}}、{{domxref("Document")}}、{{domxref("Document.body")}} のに対する {{domxref("Element/wheel_event", "wheel")}}、{{domxref("Element/mousewheel_event", "mousewheel")}}、{{domxref("Element/touchstart_event", "touchstart")}}、{{domxref("Element/touchmove_event", "touchmove")}} イベントの `passive` オプションの既定値が `true` に変更されました。これにより、イベントリスナーが[イベントをキャンセルする](/ja/docs/Web/API/Event/preventDefault)ことができなくなるため、ユーザーがスクロールしている間、ページレンダリングをブロックすることがなくなります。 - -> **メモ:** この変更された動作を実装しているブラウザー(およびそれらのブラウザーのバージョン)を知りたい場合は、下記の互換性一覧表を参照してください。 - -そのため、その動作を上書きして、すべてのブラウザーで `passive` オプションが `false` になるようにしたい場合は、(既定値に頼らず)明示的にオプションを `false` に設定する必要があります。 +#### 結果 -基本的な {{domxref("Element/scroll_event", "scroll")}} イベントの `passive` の値を気にする必要はありません。 -もともとキャンセル不可であるため、イベントリスナーはいずれにせよページのレンダリングをブロックすることはありません。 +効果は次の通りです。 -### 古いブラウザー +- 初期状態では、リスナーはパッシブであるため、ホイールでコンテナーをスクロールしようとするとすぐにスクロールします。 +- 「パッシブ」のチェックを外して、ホイールを使用してコンテナーをスクロールしようとすると、コンテナーがスクロールするまでに顕著な遅延があります。 -`addEventListener()` の `options` 引数に対応していない古いブラウザーでは、正しく[機能検出](#オプションの対応の安全な検出)をせずに使おうとすると、 `useCapture` 引数が使用できないことがあります。 +{{EmbedLiveSample("Improving scroll performance using passive listeners", 100, 300)}} ## 仕様書 diff --git a/files/ja/web/api/eventtarget/dispatchevent/index.md b/files/ja/web/api/eventtarget/dispatchevent/index.md index d104e41b3e4d63..83b1af6c98a056 100644 --- a/files/ja/web/api/eventtarget/dispatchevent/index.md +++ b/files/ja/web/api/eventtarget/dispatchevent/index.md @@ -1,19 +1,20 @@ --- title: "EventTarget: dispatchEvent() メソッド" +short-title: dispatchEvent() slug: Web/API/EventTarget/dispatchEvent l10n: - sourceCommit: 339595951b78774e951b1a9d215a6db6b856f6b2 + sourceCommit: 8ac73df2fbe2c88d8649fcb006dcde098616c723 --- -{{APIRef("DOM")}} +{{APIRef("DOM")}}{{AvailableInWorkers}} -**`dispatchEvent()`** は {{domxref("EventTarget")}} のメソッドで、 {{domxref("Event")}} をそのオブジェクトへ送り、関連する[イベントリスナー](/ja/docs/Web/API/EventTarget/addEventListener)を(同期的に)適切に起動させます。通常のイベント処理ルール(キャプチャとオプションのバブリングフェーズを含む)は `dispatchEvent()` で手動で配信されたイベントにも適用されます。 +**`dispatchEvent()`** は {{domxref("EventTarget")}} のメソッドで、 {{domxref("Event")}} をそのオブジェクトへ送り、関連するイベントリスナーを(同期的に)適切に起動させます。通常のイベント処理ルール(キャプチャとオプションのバブリングフェーズを含む)は `dispatchEvent()` で手動で配信されたイベントにも適用されます。 `dispatchEvent()` の呼び出しは、イベントを発行させるための最後のステップです。イベントは既に {{domxref("Event/Event", "Event()")}} コンストラクターを使って作成され、初期化されているはずです。 > **メモ:** このメソッドを呼び出すとき、 {{domxref("Event.target")}} プロパティは現在の `EventTarget` に初期化されます。 -「ネイティブ」イベントがブラウザーによって発生し、[イベントループ](/ja/docs/Web/JavaScript/Event_loop)を介して非同期にイベントハンドラーを呼び出すのとは異なり、 `dispatchEvent()` はイベントハンドラーを*同期的に*呼び出します。適用可能なすべてのイベントハンドラが呼び出され、 `dispatchEvent()` から戻る前に返されます。 +「ネイティブ」イベントがブラウザーによって発生し、[イベントループ](/ja/docs/Web/JavaScript/Event_loop)を介して非同期にイベントハンドラーを呼び出すのとは異なり、 `dispatchEvent()` はイベントハンドラーを*同期的に*呼び出します。適用可能なすべてのイベントハンドラーが呼び出され、 `dispatchEvent()` から戻る前に返されます。 ## 構文 diff --git a/files/ja/web/api/eventtarget/eventtarget/index.md b/files/ja/web/api/eventtarget/eventtarget/index.md index b5c6cd724177b0..19db53f3e038b7 100644 --- a/files/ja/web/api/eventtarget/eventtarget/index.md +++ b/files/ja/web/api/eventtarget/eventtarget/index.md @@ -1,11 +1,12 @@ --- title: "EventTarget: EventTarget() コンストラクター" +short-title: EventTarget() slug: Web/API/EventTarget/EventTarget l10n: - sourceCommit: 339595951b78774e951b1a9d215a6db6b856f6b2 + sourceCommit: 15f0b5552bc9c2ea1f32b0cd5ee840a7d43c887e --- -{{APIRef("DOM")}} +{{APIRef("DOM")}}{{AvailableInWorkers}} **`EventTarget()`** コンストラクターは、新しい {{domxref("EventTarget")}} オブジェクトのインスタンスを作成します。 @@ -27,29 +28,63 @@ new EventTarget() ## 例 +### カウンターの実装 + +この例では、 `increment()` メソッドと `decrement()` メソッドを持つ `Counter` クラスを実装します。これらのメソッドが呼び出されると、カスタムイベント `"valuechange"` が発生します。 + +#### HTML + +```html + +0 + +``` + +#### JavaScript + ```js -class MyEventTarget extends EventTarget { - constructor(mySecret) { +class Counter extends EventTarget { + constructor(initialValue = 0) { super(); - this._secret = mySecret; + this.value = initialValue; + } + + #emitChangeEvent() { + this.dispatchEvent(new CustomEvent("valuechange", { detail: this.value })); } - get secret() { - return this._secret; + increment() { + this.value++; + this.#emitChangeEvent(); + } + + decrement() { + this.value--; + this.#emitChangeEvent(); } } -let myEventTarget = new MyEventTarget(5); -let value = myEventTarget.secret; // === 5 -myEventTarget.addEventListener("foo", (e) => { - myEventTarget._secret = e.detail; +const initialValue = 0; +const counter = new Counter(initialValue); +document.querySelector("#currentValue").innerText = initialValue; + +counter.addEventListener("valuechange", (event) => { + document.querySelector("#currentValue").innerText = event.detail; +}); + +document.querySelector("#inc").addEventListener("click", () => { + counter.increment(); }); -let event = new CustomEvent("foo", { detail: 7 }); -myEventTarget.dispatchEvent(event); -let newValue = myEventTarget.secret; // === 7 +document.querySelector("#dec").addEventListener("click", () => { + counter.decrement(); +}); ``` +#### 結果 + +{{EmbedLiveSample("Implementing a counter")}} + ## 仕様書 {{Specifications}} diff --git a/files/ja/web/api/eventtarget/index.md b/files/ja/web/api/eventtarget/index.md index 0a47d008e7c2d5..e2ed2bb930c450 100644 --- a/files/ja/web/api/eventtarget/index.md +++ b/files/ja/web/api/eventtarget/index.md @@ -2,15 +2,15 @@ title: EventTarget slug: Web/API/EventTarget l10n: - sourceCommit: 049632675ccb83fe2e257c43071d366d3f80ee2b + sourceCommit: 15f0b5552bc9c2ea1f32b0cd5ee840a7d43c887e --- -{{ApiRef("DOM")}} +{{APIRef("DOM")}}{{AvailableInWorkers}} **`EventTarget`** インターフェイスは、イベントを受け取ることや、リスナーを持つことができるオブジェクトが実装します。 言い換えると、イベントのターゲットはすべて、このインターフェイスに関する 3 つのメソッドを実装しています。 -{{domxref("Element")}} とその子、{{domxref("Document")}}、{{domxref("Window")}} は、最も一般的なイベントターゲットですが、他のオブジェクトも、例えば {{domxref("XMLHttpRequest")}}、{{domxref("AudioNode")}}、{{domxref("AudioContext")}} などもイベントターゲットになります。 +{{domxref("Element")}} とその子、{{domxref("Document")}}、{{domxref("Window")}} は、最も一般的なイベントターゲットですが、他のオブジェクト、例えば {{domxref("IDBRequest")}}、{{domxref("AudioNode")}}、{{domxref("AudioContext")}} などもイベントターゲットになります。 多くのイベントターゲット (要素、文書、ウィンドウを含む) は、[イベントハンドラー](/ja/docs/Web/Events/Event_handlers)を設定するのに `onイベント名` プロパティや属性を使用することもできます。 diff --git a/files/ja/web/api/eventtarget/removeeventlistener/index.md b/files/ja/web/api/eventtarget/removeeventlistener/index.md index 0e0006df4e1d66..50afc4360dd00a 100644 --- a/files/ja/web/api/eventtarget/removeeventlistener/index.md +++ b/files/ja/web/api/eventtarget/removeeventlistener/index.md @@ -1,11 +1,12 @@ --- title: "EventTarget: removeEventListener() メソッド" +short-title: removeEventListener() slug: Web/API/EventTarget/removeEventListener l10n: - sourceCommit: 339595951b78774e951b1a9d215a6db6b856f6b2 + sourceCommit: 15f0b5552bc9c2ea1f32b0cd5ee840a7d43c887e --- -{{APIRef("DOM")}} +{{APIRef("DOM")}}{{AvailableInWorkers}} **`removeEventListener()`** は {{domxref("EventTarget")}} インターフェイスのメソッドで、以前に {{domxref("EventTarget.addEventListener()")}} で登録されたイベントリスナーを取り外します。 取り外されるイベントリスナーはイベントの型、イベントリスナー関数そのもの、照合プロセスに影響を与えるさまざまな任意のオプションを使用して識別します。 @@ -90,7 +91,7 @@ element.removeEventListener("mousedown", handleMouseDown, false); // 成功 element.removeEventListener("mousedown", handleMouseDown, true); // 失敗 ``` -この点については、いくつかのブラウザのリリースで一貫性がないことに注意してください。特に理由がない限り、`addEventListener()` の呼び出しで使用したのと同じ値を `removeEventListener()` の呼び出しでも使用することが賢明でしょう。 +この点については、いくつかのブラウザーのリリースで一貫性がないことに注意してください。特に理由がない限り、`addEventListener()` の呼び出しで使用したのと同じ値を `removeEventListener()` の呼び出しでも使用することが賢明でしょう。 ## 例 diff --git a/files/ko/web/javascript/reference/global_objects/math/e/index.md b/files/ko/web/javascript/reference/global_objects/math/e/index.md index 79280d323ed466..f328a096161021 100644 --- a/files/ko/web/javascript/reference/global_objects/math/e/index.md +++ b/files/ko/web/javascript/reference/global_objects/math/e/index.md @@ -1,19 +1,29 @@ --- title: Math.E slug: Web/JavaScript/Reference/Global_Objects/Math/E +l10n: + sourceCommit: 761b9047d78876cbd153be811efb1aa77b419877 --- {{JSRef}} -**`Math.E`** 속성은 자연로그의 밑 값 e를 나타내며 약 2.718의 값을 가집니다. +**`Math.E`** 정적 데이터 속성은 오일러 수를 의미하며, 자연로그의 밑 값 e를 나타내며 약 2.718의 값을 가집니다. -Math.E=e2.718\mathtt{\mi{Math.E}} = e \approx 2.718 +{{EmbedInteractiveExample("pages/js/math-e.html")}} -{{EmbedInteractiveExample("pages/js/math-e.html")}}{{js_property_attributes(0, 0, 0)}} +## 값 + + + + 𝙼𝚊𝚝𝚑.𝙴=e2.718\mathtt{Math.E} = e \approx 2.718 + + + +{{js_property_attributes(0, 0, 0)}} ## 설명 -`E`는 `Math`의 정적 속성이므로, 사용자가 생성한 `Math` 객체의 속성으로 접근할 수 없고 항상 `Math.E`를 사용해야 합니다. (`Math`는 생성자가 아닙니다) +`E`는 `Math`의 정적 속성이므로, 생성한 `Math` 객체(`Math`는 생성자가 아닙니다)의 속성 대신 항상 `Math.E`를 사용해야 합니다. ## 예제 @@ -29,7 +39,7 @@ function getNapier() { getNapier(); // 2.718281828459045 ``` -## 명세 +## 명세서 {{Specifications}} diff --git a/files/ko/web/javascript/reference/global_objects/regexp/n/index.md b/files/ko/web/javascript/reference/global_objects/regexp/n/index.md new file mode 100644 index 00000000000000..62d84e51e4d596 --- /dev/null +++ b/files/ko/web/javascript/reference/global_objects/regexp/n/index.md @@ -0,0 +1,52 @@ +--- +title: RegExp.$1, …, RegExp.$9 +slug: Web/JavaScript/Reference/Global_Objects/RegExp/n +l10n: + sourceCommit: fb85334ffa4a2c88d209b1074909bee0e0abd57a +--- + +{{JSRef}} {{Deprecated_Header}} + +> **참고:** 마지막 일치 상태를 전역적으로 노출하는 모든 `RegExp` 정적 속성은 더 이상 사용되지 않습니다. 자세한 내용은 [더 이상 사용되지 않는 RegExp 기능](/ko/docs/Web/JavaScript/Reference/Deprecated_and_obsolete_features#regexp)을 참고하세요. + +**`RegExp.$1, …, RegExp.$9`** 정적 접근자 속성은 괄호 안의 하위 문자열 일치 항목을 반환합니다. + +## 설명 + +`$1`–`$9`는 {{jsxref("RegExp")}}의 정적 속성이기 때문에, 생성한 `RegExp` 객체의 속성으로 사용하는 것보다는 항상`RegExp.$1`, `RegExp.$2` 등으로 사용해야 합니다. + +`$1, …, $9`의 값은 `RegExp`(`RegExp` 하위 클래스 제외) 인스턴스가 일치에 성공할 때마다 갱신됩니다. 일치하는 항목이 없거나 마지막 일치가 대응되는 캡쳐 그룹이 없으면 각각의 속성은 빈 문자열입니다. 각각의 속성의 설정 접근자는 `undefined`이므로 이 속성을 직접 변경할 수 없습니다. + +괄호로 묶을 수 있는 하위 문자열의 개수는 제한이 없지만 `RegExp` 객체는 처음 9개만 보유할 수 있습니다. 반환된 배열의 인덱스를 통해 괄호로 묶인 모든 하위 문자열에 접근할 수 있습니다. + +`$1, …, $9`는 {{jsxref("String.prototype.replace()")}}의 대체 문자열에도 사용할 수 있지만, 이는 `RegExp.$n` 레거시 속성과는 관련이 없습니다. + +## 예제 + +### RegExp.prototype.test()와 함께 $n 사용하기 + +아래 스크립트는 일반적인 문자열 내에서 숫자를 잡아내기 위해 {{jsxref("RegExp.prototype.test()")}} 메서드를 사용합니다. + +```js +const str = "Test 24"; +const number = /(\d+)/.test(str) ? RegExp.$1 : "0"; +number; // "24" +``` + +`re.test(str)` 호출과 `RegExp.$n` 속성 사이에 다른 정규식을 사용하는 작업은 부작용이 있을 수 있습니다. 이러한 특수 속성 접근은 즉시 수행해야 하며, 그렇지 않으면 예상치 못한 결과가 발생할 수 있다는 점을 주의하시기 바랍니다. + +## 명세서 + +{{Specifications}} + +## 브라우저 호환성 + +{{Compat}} + +## 같이 보기 + +- {{jsxref("RegExp/input", "RegExp.input ($_)")}} +- {{jsxref("RegExp/lastMatch", "RegExp.lastMatch ($&)")}} +- {{jsxref("RegExp/lastParen", "RegExp.lastParen ($+)")}} +- {{jsxref("RegExp/leftContext", "RegExp.leftContext ($`)")}} +- {{jsxref("RegExp/rightContext", "RegExp.rightContext ($')")}} diff --git a/files/ru/_redirects.txt b/files/ru/_redirects.txt index f79bee37978aba..cec8e2612ff39f 100644 --- a/files/ru/_redirects.txt +++ b/files/ru/_redirects.txt @@ -755,10 +755,8 @@ /ru/docs/Web/JavaScript/Reference/Classes/Приватные_поля_класса /ru/docs/Web/JavaScript/Reference/Classes/Private_properties /ru/docs/Web/JavaScript/Reference/Errors/Bad_return_or_yield /ru/docs/Web/JavaScript/Reference/Errors/Bad_return /ru/docs/Web/JavaScript/Reference/Errors/Deprecated_octal /ru/docs/Web/JavaScript/Reference/Errors/Deprecated_octal_literal -/ru/docs/Web/JavaScript/Reference/Errors/Equal_as_assign /ru/docs/orphaned/Web/JavaScript/Reference/Errors/Equal_as_assign /ru/docs/Web/JavaScript/Reference/Errors/Missing_semicolon_before_statement /ru/docs/Web/JavaScript/Reference/Errors/Unexpected_token /ru/docs/Web/JavaScript/Reference/Errors/Not_a_codepoint /ru/docs/Web/JavaScript/Reference/Errors/Not_a_valid_code_point -/ru/docs/Web/JavaScript/Reference/Errors/Undefined_prop /ru/docs/orphaned/Web/JavaScript/Reference/Errors/Undefined_prop /ru/docs/Web/JavaScript/Reference/Errors/Unterminated_string_literal /ru/docs/Web/JavaScript/Reference/Errors/String_literal_EOL /ru/docs/Web/JavaScript/Reference/Functions/Определиние_методов /ru/docs/Web/JavaScript/Reference/Functions/Method_definitions /ru/docs/Web/JavaScript/Reference/Global_Objects/Array/@@iterator /ru/docs/Web/JavaScript/Reference/Global_Objects/Array/Symbol.iterator diff --git a/files/ru/_wikihistory.json b/files/ru/_wikihistory.json index ef512df6837696..7123c7e879f0e1 100644 --- a/files/ru/_wikihistory.json +++ b/files/ru/_wikihistory.json @@ -15961,13 +15961,5 @@ "conflicting/Web/SVG/Attribute": { "modified": "2020-10-15T22:34:58.576Z", "contributors": ["osipov_s"] - }, - "orphaned/Web/JavaScript/Reference/Errors/Equal_as_assign": { - "modified": "2020-03-12T19:48:37.445Z", - "contributors": ["MakarovDs777"] - }, - "orphaned/Web/JavaScript/Reference/Errors/Undefined_prop": { - "modified": "2020-03-12T19:47:58.221Z", - "contributors": ["KTatyana"] } } diff --git a/files/ru/orphaned/web/javascript/reference/errors/equal_as_assign/index.md b/files/ru/orphaned/web/javascript/reference/errors/equal_as_assign/index.md deleted file mode 100644 index af44799a3859d3..00000000000000 --- a/files/ru/orphaned/web/javascript/reference/errors/equal_as_assign/index.md +++ /dev/null @@ -1,54 +0,0 @@ ---- -title: "SyntaxError: test for equality (==) mistyped as assignment (=)?(тест на равенство (==) опечатка как присваивание (=)?)" -slug: orphaned/Web/JavaScript/Reference/Errors/Equal_as_assign -original_slug: Web/JavaScript/Reference/Errors/Equal_as_assign ---- - -{{jsSidebar("Errors")}} - -## Сообщения - -``` -Warning: SyntaxError: тест на равенство (==) опечатка как присваивание (=)? -``` - -## Тип ошибки - -(Только в Firefox) {{jsxref("SyntaxError")}} предупреждение, в котором сообщается, только если `javascript.options.strict` предпочтение установлено в `true`. - -## Что пошло не так? - -Было присвоение ( = ), когда вы обычно ожидали тест на присвоение (==). Чтобы помочь отладке, JavaScript (с включёнными строгими предупреждениями) предупреждает об этом шаблоне. - -## Примеры - -### Задание в условных выражениях - -Рекомендуется не использовать простые назначения в условном выражении (например, if...else), поскольку при просмотре кода назначение можно спутать с равенством. Например, не используйте следующий код: - -```js-nolint example-bad -if (x = y) { - // делать правильные вещи -} -``` - -Если необходимо использовать присваивание в условном выражении, то обычно вокруг него ставят дополнительные скобки. Например: - -```js -if ((x = y)) { - // делать правильные вещи -} -``` - -В противном случае вы, вероятно, хотели использовать оператор сравнения (например, = = или ===): - -```js -if (x == y) { - // делать правильные вещи -} -``` - -## Смотрите также - -- [`if...else`](/ru/docs/Web/JavaScript/Reference/Statements/if...else) -- [Comparison operators](/ru/docs/Web/JavaScript/Reference/Operators/Comparison_Operators) diff --git a/files/ru/orphaned/web/javascript/reference/errors/undefined_prop/index.md b/files/ru/orphaned/web/javascript/reference/errors/undefined_prop/index.md deleted file mode 100644 index 1caf390ca8157d..00000000000000 --- a/files/ru/orphaned/web/javascript/reference/errors/undefined_prop/index.md +++ /dev/null @@ -1,55 +0,0 @@ ---- -title: 'ReferenceError: reference to undefined property "x"' -slug: orphaned/Web/JavaScript/Reference/Errors/Undefined_prop -original_slug: Web/JavaScript/Reference/Errors/Undefined_prop ---- - -{{jsSidebar("Errors")}} - -## Сообщение - -``` -ReferenceError: reference to undefined property "x" (Firefox) -``` - -## Тип ошибки - -(только в Firefox) Предупреждение {{jsxref("ReferenceError")}}, возникает, только если значение настройки `javascript.options.strict` равно `true`. - -## Что пошло не так? - -Совершена попытка обращения к свойству объекта, которое не определено. Существует два способа обращения к свойствам: обратитесь к странице справочника {{jsxref("Operators/Property_Accessors", "property accessors", 0, 1)}} для более подробной информации. - -## Примеры - -### Случаи возникновения ошибки - -В данном примере свойство `bar` не определено, поэтому возникнет ошибка `ReferenceError`. - -```js example-bad -var foo = {}; -foo.bar; // ReferenceError: reference to undefined property "bar" -``` - -### Правильный код - -Чтобы избежать ошибки, потребуется либо задать для объекта свойство `bar`, либо проверить существование данного свойства, прежде чем обращаться к нему. Одним из способов это сделать является использование метода {{jsxref("Object.prototype.hasOwnProperty()")}}: - -```js example-good -var foo = {}; - -// Задать свойство bar - -foo.bar = "moon"; -console.log(foo.bar); // "moon" - -// Убедиться, что свойство bar существует, прежде чем обращаться к нему - -if (foo.hasOwnProperty("bar")) { - console.log(foo.bar); -} -``` - -## Смотрите также - -- {{jsxref("Operators/Property_Accessors", "property accessors", 0, 1)}} diff --git a/files/zh-cn/glossary/typescript/index.md b/files/zh-cn/glossary/typescript/index.md new file mode 100644 index 00000000000000..8b0750c331547e --- /dev/null +++ b/files/zh-cn/glossary/typescript/index.md @@ -0,0 +1,41 @@ +--- +title: TypeScript +slug: Glossary/TypeScript +l10n: + sourceCommit: 8005d92738cb5678d9b1e434f02ddebaa15c1eaa +--- + +{{GlossarySidebar}} + +TypeScript 是一个为 JavaScript 添加{{glossary("static_typing", "静态类型检查")}}的编程语言。 + +TypeScript 是 JavaScript 的超集,这意味着 JavaScript 中所具有的一切也都可以在 TypeScript 中使用,而且每个 JavaScript 程序都是语法合法的 TypeScript 程序。此外,TypeScript 和 JavaScript 的运行时行为是相同的。 + +然而,TypeScript 添加了编译时类型检查,实现了关于不同类型如何使用和组合的规则。这可以捕获在 JavaScript 中只有在运行时才会遇到的各种编程错误。 + +一些类型规则是从 JavaScript 中推断出来的。例如,在下面的代码中,TypeScript 推断 `myVariable` 是一个字符串,因此不允许将其重新赋值为不同的类型: + +```ts +let myVariable = "Hello World"; +myVariable = 1; +// 错误: +// Type 'number' is not assignable to type 'string'. +``` + +TypeScript 还允许程序员对其代码进行注释,以指示例如函数的参数类型或对象的属性: + +```ts +function add(left: number, right: number): number { + return left + right; +} + +add("hello", "world"); +// 错误: +// Argument of type 'string' is not assignable to parameter of type 'number'. +``` + +编译后,类型注释会被移除,使得编译输出只是 JavaScript,这意味着它可以在任何 JavaScript 运行时中执行。 + +## 参见 + +- [TypeScript 官网](https://www.typescriptlang.org/) diff --git a/files/zh-cn/glossary/uri/index.md b/files/zh-cn/glossary/uri/index.md index e37ffa7adc622b..39b0ee175356ef 100644 --- a/files/zh-cn/glossary/uri/index.md +++ b/files/zh-cn/glossary/uri/index.md @@ -1,13 +1,17 @@ --- title: URI slug: Glossary/URI +l10n: + sourceCommit: ada5fa5ef15eadd44b549ecf906423b4a2092f34 --- {{GlossarySidebar}} -**URI**(统一资源标识符)是一个指向资源的字符串。最通常用在 {{Glossary("URL")}} 上来指定 Web 上资源文件的具体位置。相比之下,{{Glossary("URN")}} 是在给定的命名空间用名字指向具体的资源,如:书本的 ISBN。 +**URI**(统一资源标识符)是一个指向资源的字符串。 + +最通常用在 {{Glossary("URL")}} 上来指定 Web 上资源文件的具体位置。相比之下,{{Glossary("URN")}} 是在给定的命名空间用名字指向具体的资源,如书本的 ISBN。 ## 参见 - 在维基百科上的 [URI](https://zh.wikipedia.org/wiki/URI) -- [RFC 3986 on URI](https://tools.ietf.org/html/rfc3986) +- [关于 URI 的 RFC 3986](https://tools.ietf.org/html/rfc3986) diff --git a/files/zh-cn/glossary/url/index.md b/files/zh-cn/glossary/url/index.md index 6a3d6cd304bbb7..957e526970453b 100644 --- a/files/zh-cn/glossary/url/index.md +++ b/files/zh-cn/glossary/url/index.md @@ -1,15 +1,17 @@ --- title: URL slug: Glossary/URL +l10n: + sourceCommit: 731e5ba6630a220c24b22288b58af70495063555 --- {{GlossarySidebar}} -统一资源定位器(**URL**)是指定在 Internet 上可以找到资源的位置的文本字符串。 +**统一资源定位符**(**URL**)是指定在互联网上可以找到资源的位置的文本字符串。 -在 {{Glossary("HTTP")}} 的上下文中,URL 被叫做”网络地址“或“链接”。你的浏览器在其地址栏显示 URL,例如 `https://developer.mozilla.org` +在 {{Glossary("HTTP")}} 的上下文中,URL 被叫做”网络地址“或“链接”。{{glossary("browser", "浏览器")}}在其地址栏显示 URL,例如 `https://developer.mozilla.org`。一些浏览器仅显示 URL 中在“//”之后的部分(即{{Glossary("Domain name", "域名")}})。 -URL 也可用于文件传输({{Glossary("FTP")}}) ,电子邮件({{Glossary("SMTP")}})和其他应用。 +URL 也可用于文件传输({{Glossary("FTP")}})、电子邮件({{Glossary("SMTP")}})和其他应用。 ## 参见 diff --git a/files/zh-cn/glossary/viewport/index.md b/files/zh-cn/glossary/viewport/index.md index fcfd130fcb45d0..93d6e003a841d5 100644 --- a/files/zh-cn/glossary/viewport/index.md +++ b/files/zh-cn/glossary/viewport/index.md @@ -1,14 +1,21 @@ --- -title: Viewport +title: 视口 slug: Glossary/Viewport +l10n: + sourceCommit: 50e5e8a9b8a6b7d0dd9877610c9639d8b90f329f --- {{GlossarySidebar}} 在电脑图形学里面,视口代表了一个可看见的多边形区域(通常来说是矩形)。在浏览器范畴里,它代表的是浏览器中网站可见内容的部分。视口外的内容在被滚动进来前都是不可见的。 -视口当前可见的部分叫做**可视视口**(visual viewport)。可视视口可能会比**布局视口**(layout viewport)更小,因为当用户缩小浏览器缩放比例时,布局视口不变,而可视视口变小了。 +视口当前可见的部分叫做[**可视视口**](/zh-CN/docs/Glossary/Visual_viewport)。可视视口可能会比[**布局视口**](/zh-CN/docs/Glossary/Layout_viewport)更小,因为当用户缩小浏览器缩放比例时,布局视口不变,而可视视口变小了。 ## 参见 +- [可视视口 API](/zh-CN/docs/Web/API/Visual_Viewport_API) - 维基百科上的[视口](https://zh.wikipedia.org/wiki/视口) +- [两个视口的故事](https://www.quirksmode.org/mobile/viewports.html)(Quirksmode) +- 相关术语: + - {{Glossary("Visual viewport", "可视视口")}} + - {{Glossary("Layout viewport", "布局视口")}} diff --git a/files/zh-cn/glossary/wcag/index.md b/files/zh-cn/glossary/wcag/index.md new file mode 100644 index 00000000000000..494d6cdf5241c8 --- /dev/null +++ b/files/zh-cn/glossary/wcag/index.md @@ -0,0 +1,28 @@ +--- +title: WCAG +slug: Glossary/WCAG +l10n: + sourceCommit: 3163ae00b0d8ac11dc752ea9f7d956bd00551a3e +--- + +{{GlossarySidebar}} + +_Web 内容无障碍指南_(**WCAG**)是由 {{Glossary("W3C")}} {{Glossary("WAI","Web 无障碍倡议")}}组发布的一些建议。它们概述了一组主要面向残障人士的内容无障碍指南,但也适用于移动电话等资源有限的设备。 + +WCAG 2.0 于 2008 年 12 月 11 日发布,取代了 WCAG 1.0。它由 12 条指南组成,分为 4 个原则(可感知、可操作、可理解和健壮性),每个指南都有可测试的成功标准。 + +WCAG 使用三个一致性水平: + +- 优先级 1:Web 开发人员**必须**满足这些要求,否则将无法让一个或多个群体访问 Web 内容。符合此级别的描述为 A。 +- 优先级 2:Web 开发人员**应该**满足这些要求,否则一些群体将发现访问 Web 内容变得困难。符合此级别的描述为 AA 或双 A。 +- 优先级 3:Web 开发人员**可以**满足这些要求,以便让一些群体更容易访问 Web 内容。符合此级别的描述为 AAA 或三 A。 + +[WCAG 2.2](https://www.w3.org/TR/WCAG22/) 和 [WCAG 3.0](https://www.w3.org/TR/wcag-3.0/) 的工作正在进行中。 + +## 参见 + +- 维基百科上的 [WCAG](https://zh.wikipedia.org/wiki/Web内容无障碍指南) +- [MDN 上的无障碍信息](/zh-CN/docs/Web/Accessibility/Information_for_Web_authors) +- [W3C 上的 WCAG 2.0 推荐标准](https://www.w3.org/Translations/WCAG20-zh/) +- [Web 内容无障碍指南(WCAG)2.2:候选推荐标准](https://www.w3.org/TR/WCAG22/) +- [W3C 内容无障碍指南(WCAG)3.0:工作草案](https://www.w3.org/TR/wcag-3.0/) diff --git a/files/zh-cn/glossary/webvtt/index.md b/files/zh-cn/glossary/webvtt/index.md new file mode 100644 index 00000000000000..ade2f03db742d6 --- /dev/null +++ b/files/zh-cn/glossary/webvtt/index.md @@ -0,0 +1,18 @@ +--- +title: WebVTT +slug: Glossary/WebVTT +l10n: + sourceCommit: ada5fa5ef15eadd44b549ecf906423b4a2092f34 +--- + +{{GlossarySidebar}} + +WebVTT(Web 视频文本轨道)是一种 {{Glossary("W3C")}} 规范的用于和 HTML 的 {{HTMLElement("track")}} 元素一起标记文本轨道资源的文件格式。 + +WebVTT 文件提供了与音频或视频内容同步的元数据,如视频内容的字幕或标题、视频描述的文本、内容导航的章节等。 + +## 参见 + +- 维基百科上的 [WebVTT](https://zh.wikipedia.org/wiki/WebVTT) +- MDN 上的 [WebVTT](/zh-CN/docs/Web/API/WebVTT_API) +- [规范](https://www.w3.org/TR/webvtt1/) diff --git a/files/zh-cn/glossary/windowproxy/index.md b/files/zh-cn/glossary/windowproxy/index.md new file mode 100644 index 00000000000000..54ecec0c59bd8e --- /dev/null +++ b/files/zh-cn/glossary/windowproxy/index.md @@ -0,0 +1,15 @@ +--- +title: WindowProxy +slug: Glossary/WindowProxy +l10n: + sourceCommit: ada5fa5ef15eadd44b549ecf906423b4a2092f34 +--- + +{{GlossarySidebar}} + +**`WindowProxy`** 对象是 [`Window`](/zh-CN/docs/Web/API/Window) 对象的包装器。`WindowProxy` 对象存在于每个[浏览上下文](/zh-CN/docs/Glossary/Browsing_context)中。对 `WindowProxy` 对象执行的所有操作也将应用于它当前包装的底层 `Window` 对象。因此,和 `WindowProxy` 对象直接交互几乎与直接和 `Window` 对象交互相同。当浏览上下文被导航时,其 `WindowProxy` 包装的 `Window` 对象会发生变化。 + +## 参见 + +- HTML 规范:[WindowProxy 小节](https://html.spec.whatwg.org/multipage/window-object.html#the-windowproxy-exotic-object) +- Stack Overflow 问题:[WindowProxy 与 Window 对象?](https://stackoverflow.com/questions/16092835/windowproxy-and-window-objects) diff --git a/files/zh-cn/glossary/wrapper/index.md b/files/zh-cn/glossary/wrapper/index.md new file mode 100644 index 00000000000000..6475454b2d5a09 --- /dev/null +++ b/files/zh-cn/glossary/wrapper/index.md @@ -0,0 +1,21 @@ +--- +title: 包装器 +slug: Glossary/Wrapper +l10n: + sourceCommit: 50e5e8a9b8a6b7d0dd9877610c9639d8b90f329f +--- + +{{GlossarySidebar}} + +在诸如 JavaScript 之类的编程语言中,包装器是一种函数,旨在调用一个或多个其他函数,有时纯粹是为了方便,有时是为了在此过程中使它们执行略有不同的任务。 + +例如,AWS 的 SDK 库就是包装器的例子。 + +## 参见 + +- 维基百科上的[包装函数](https://zh.wikipedia.org/wiki/包裝函式) +- 相关术语: + + - {{Glossary("API")}} + - {{Glossary("Class", "类")}} + - {{Glossary("Function", "函数")}} diff --git a/files/zh-cn/web/api/canvasrenderingcontext2d/beziercurveto/index.md b/files/zh-cn/web/api/canvasrenderingcontext2d/beziercurveto/index.md index 03c0cb03745a9d..698605fe6c911b 100644 --- a/files/zh-cn/web/api/canvasrenderingcontext2d/beziercurveto/index.md +++ b/files/zh-cn/web/api/canvasrenderingcontext2d/beziercurveto/index.md @@ -1,16 +1,18 @@ --- -title: CanvasRenderingContext2D.bezierCurveTo() +title: CanvasRenderingContext2D:bezierCurveTo() 方法 slug: Web/API/CanvasRenderingContext2D/bezierCurveTo +l10n: + sourceCommit: 1f216a70d94c3901c5767e6108a29daa48edc070 --- {{APIRef}} -**`CanvasRenderingContext2D.bezierCurveTo()`** 是 Canvas 2D API 绘制三次贝赛尔曲线路径的方法。该方法需要三个点。第一、第二个点是控制点,第三个点是结束点。起始点是当前路径的最后一个点,绘制贝赛尔曲线前,可以通过调用 `moveTo()` 进行修改。 +Canvas 2D API 的 **`CanvasRenderingContext2D.bezierCurveTo()`** 方法用于将三次[贝赛尔曲线](/zh-CN/docs/Glossary/Bezier_curve)添加到当前子路径中。该方法需要三个点:前两个点是控制点,第三个点是结束点。起始点是当前路径的最后一个点,绘制贝赛尔曲线前,可以通过调用 {{domxref("CanvasRenderingContext2D.moveTo", "moveTo()")}} 进行修改。 ## 语法 -``` -void ctx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y); +```js-nolint +bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y) ``` ### 参数 @@ -28,11 +30,15 @@ void ctx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y); - `y` - : 结束点的 y 轴坐标。 +### 返回值 + +无({{jsxref("undefined")}})。 + ## 示例 -### 使用 `bezierCurveTo` 方法 +### 如何使用 bezierCurveTo 方法 -这是一段绘制贝赛尔曲线的简单的代码片段。控制点是红色的,开始和结束点是蓝色的。 +此示例展示了如何绘制三次贝塞尔曲线。 #### HTML @@ -43,75 +49,72 @@ void ctx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y); #### JavaScript ```js -var canvas = document.getElementById("canvas"); -var ctx = canvas.getContext("2d"); +// 定义画布和上下文 +const canvas = document.getElementById("canvas"); +const ctx = canvas.getContext("2d"); +// 定义点的坐标 {x, y} +let start = { x: 50, y: 20 }; +let cp1 = { x: 230, y: 30 }; +let cp2 = { x: 150, y: 80 }; +let end = { x: 250, y: 100 }; + +// 三次贝塞尔曲线 ctx.beginPath(); -ctx.moveTo(50, 20); -ctx.bezierCurveTo(230, 30, 150, 60, 50, 100); +ctx.moveTo(start.x, start.y); +ctx.bezierCurveTo(cp1.x, cp1.y, cp2.x, cp2.y, end.x, end.y); ctx.stroke(); +// 起点和终点 ctx.fillStyle = "blue"; -// start point -ctx.fillRect(50, 20, 10, 10); -// end point -ctx.fillRect(50, 100, 10, 10); +ctx.beginPath(); +ctx.arc(start.x, start.y, 5, 0, 2 * Math.PI); // 起点 +ctx.arc(end.x, end.y, 5, 0, 2 * Math.PI); // 终点 +ctx.fill(); +// 控制点 ctx.fillStyle = "red"; -// control point one -ctx.fillRect(230, 30, 10, 10); -// control point two -ctx.fillRect(150, 70, 10, 10); +ctx.beginPath(); +ctx.arc(cp1.x, cp1.y, 5, 0, 2 * Math.PI); // 控制点一 +ctx.arc(cp2.x, cp2.y, 5, 0, 2 * Math.PI); // 控制点二 +ctx.fill(); ``` -{{ EmbedLiveSample('使用_bezierCurveTo_方法', 315, 165) }} +#### 结果 -### 尝试 `bezierCurveTo` 参数 +在这个例子中,控制点是红色的,起点和终点是蓝色的。 -修改下面的代码并在线查看 canvas 的变化: +{{ EmbedLiveSample('如何使用_bezierCurveTo_方法', 315, 165) }} -```html hidden - -
- - -
- +### 简单的贝塞尔曲线 + +此示例使用 `bezierCurveTo()` 绘制了一条简单的贝塞尔曲线。 + +#### HTML + +```html + ``` -```js hidden -var canvas = document.getElementById("canvas"); -var ctx = canvas.getContext("2d"); -var textarea = document.getElementById("code"); -var reset = document.getElementById("reset"); -var edit = document.getElementById("edit"); -var code = textarea.value; - -function drawCanvas() { - ctx.clearRect(0, 0, canvas.width, canvas.height); - eval(textarea.value); -} - -reset.addEventListener("click", function () { - textarea.value = code; - drawCanvas(); -}); - -edit.addEventListener("click", function () { - textarea.focus(); -}); - -textarea.addEventListener("input", drawCanvas); -window.addEventListener("load", drawCanvas); +#### JavaScript + +曲线从指定的起点开始,使用 `moveTo()` 方法:(30, 30)。第一个控制点位于 (120, 160),第二个控制点位于 (180, 10)。曲线在 (220, 140) 结束。 + +```js +const canvas = document.getElementById("canvas"); +const ctx = canvas.getContext("2d"); + +ctx.beginPath(); +ctx.moveTo(30, 30); +ctx.bezierCurveTo(120, 160, 180, 10, 220, 140); +ctx.stroke(); ``` -{{ EmbedLiveSample('尝试_bezierCurveTo_参数', 700, 360) }} +#### 结果 + +{{ EmbedLiveSample('简单的贝塞尔曲线', 700, 180) }} -## 规范描述 +## 规范 {{Specifications}} @@ -121,5 +124,5 @@ window.addEventListener("load", drawCanvas); ## 参见 -- 接口定义, {{domxref("CanvasRenderingContext2D")}} -- [维基百科关于贝赛尔曲线](http://en.wikipedia.org/wiki/B%C3%A9zier_curve)。 +- 定义此方法的接口:{{domxref("CanvasRenderingContext2D")}} +- [贝赛尔曲线](/zh-CN/docs/Glossary/Bezier_curve) diff --git a/files/zh-cn/web/api/canvasrenderingcontext2d/fontvariantcaps/index.md b/files/zh-cn/web/api/canvasrenderingcontext2d/fontvariantcaps/index.md new file mode 100644 index 00000000000000..cb203e091f1e16 --- /dev/null +++ b/files/zh-cn/web/api/canvasrenderingcontext2d/fontvariantcaps/index.md @@ -0,0 +1,92 @@ +--- +title: CanvasRenderingContext2D:fontVariantCaps 属性 +slug: Web/API/CanvasRenderingContext2D/fontVariantCaps +l10n: + sourceCommit: 44cf523714745d626317192bfbe849b47144f3ab +--- + +{{APIRef}} + +[Canvas API](/zh-CN/docs/Web/API/Canvas_API) 的 `CanvasRenderingContext2D.fontVariantCaps` 属性用于指定渲染文本的替代大写形式。 + +该属性对应于 CSS 中的 [`font-variant-caps`](/zh-CN/docs/Web/CSS/font-variant-caps) 属性。 + +## 值 + +字体的替代大写形式值,可以是以下之一: + +- `normal`(默认) + - : 停用替代字形。 +- `small-caps` + - : 启用小型大写字母(small capital)的显示(OpenType 特性:`smcp`)。小型大写字形通常使用大写字母的形式,但大小与小写字母相同。 +- `all-small-caps` + - : 同时为大写和小写字母启用小型大写字母(small capital)的显示(OpenType 特性:`c2sc`、`smcp`)。 +- `petite-caps` + - : 启用小型大写字母(petite capital)的显示(OpenType 特性:`pcap`)。 +- `all-petite-caps` + - : 同时为大写和小写字母启用小型大写字母(petite capital)的显示(OpenType 特性:`c2pc`、`pcap`)。 +- `unicase` + - : 启用将大写字母显示为小型大写字母(small capital),同时正常显示小写字母的混合显示(OpenType 特性:`unic`)。 +- `titling-caps` + - : 启用标题大写字母的显示(OpenType 特性:`titl`)。大写字母字形通常设计用于与小写字母配合使用。在全大写的标题序列中使用时,它们可能显得过于强烈。标题大写字母是专为这种情况而设计的。 + +该属性可以用于获取或设置字体的大写值。 + +请注意,某些内容可能会引发无障碍问题,具体内容请参阅相应的 [`font-variant-caps`](/zh-CN/docs/Web/CSS/font-variant-caps#无障碍访问风险) 主题。 + +## 示例 + +以下示例演示了使用 `fontVariantCaps` 属性支持的每种值来显示文本“Hello World”。每种情况还通过读取属性来显示其值。 + +### HTML + +```html + +``` + +### JavaScript + +```js +const canvas = document.getElementById("canvas"); +const ctx = canvas.getContext("2d"); +ctx.font = "20px serif"; + +// 默认值(normal) +ctx.fillText(`Hello world(默认:${ctx.fontVariantCaps})`, 5, 20); + +// 大写形式:small-caps +ctx.fontVariantCaps = "small-caps"; +ctx.fillText(`Hello world(${ctx.fontVariantCaps})`, 5, 50); + +// 大写形式:all-small-caps +ctx.fontVariantCaps = "all-small-caps"; +ctx.fillText(`Hello world(${ctx.fontVariantCaps})`, 5, 80); + +// 大写形式:petite-caps +ctx.fontVariantCaps = "petite-caps"; +ctx.fillText(`Hello world(${ctx.fontVariantCaps})`, 5, 110); + +// 大写形式:all-petite-caps +ctx.fontVariantCaps = "all-petite-caps"; +ctx.fillText(`Hello world(${ctx.fontVariantCaps})`, 5, 140); + +// 大写形式:unicase +ctx.fontVariantCaps = "unicase"; +ctx.fillText(`Hello world(${ctx.fontVariantCaps})`, 5, 170); + +// 大写形式:titling-caps +ctx.fontVariantCaps = "titling-caps"; +ctx.fillText(`Hello world(${ctx.fontVariantCaps})`, 5, 200); +``` + +### 结果 + +{{ EmbedLiveSample('示例', 700, 230) }} + +## 规范 + +{{Specifications}} + +## 浏览器兼容性 + +{{Compat}}