JS でクロージャが悪用される一般的なシナリオは何ですか? (画像とテキストのチュートリアル)
シナリオ 1: 関数参照を使用した SetTimeout 呼び出し
クロージャーの一般的な使用法は、特定の関数が実行される前に実行される関数にパラメーターを提供することです。たとえば、Web 環境では、関数が setTimeout 関数呼び出しの最初のパラメーターとして使用されるのが非常に一般的なアプリケーションです。
setTimeout は、実行される関数 (または JavaScript コードの一部、ただしこれについては説明しません) を最初のパラメーターとして受け取り、次のパラメーターは実行を遅延する時間です。コードの一部を setTimeout 経由で呼び出したい場合は、最初のパラメータとして関数オブジェクトへの参照を渡す必要があります。 2 番目のパラメーターとして遅延するミリ秒数を指定しますが、この関数オブジェクト参照は遅延されるオブジェクトのパラメーターを提供できません。
ただし、内部関数への呼び出しを返す別の関数を呼び出し、その内部関数オブジェクトへの参照を setTimeout 関数に渡すことは可能です。内部関数の実行時に必要なパラメータは、外部関数の呼び出し時に渡されます。 setTimeout は、内部関数の実行時にパラメーターを渡す必要はありません。内部関数は、外部関数の呼び出し時に提供されたパラメーターに引き続きアクセスできるためです:
function callLater(paramA, paramB, paramC) { /*使用函数表达式创建并放回一个匿名内部函数的引用*/ return (function () { /* 这个内部函数将被setTimeout函数执行; 并且当它被执行时, 它能够访问并操作外部函数传递过来的参数 */ paramA[paramB] = paramC; }); } /* 调用这个函数将在它的执行上下文中创建,并最终返回内部函数对象的引用 传递过来的参数,内部函数在最终被执行时,将使用外部函数的参数 返回的引用被赋予了一个变量 */ var funcRef = callLater(elStyle, "display", "none"); /*调用setTimeout函数,传递内部函数的引用作为第一个参数*/ hideMenu = setTimeout(funcRef, 500);
シナリオ 2: 関数をオブジェクトのインスタンス メソッドに関連付けます
このようなシナリオの多くは、将来のある時点で関数を実行できるように、オブジェクトへの関数 A 参照を割り当てる必要があります。その場合、クロージャは、実行される関数への参照を提供するのに非常に役立ちます。実行するまで関数にアクセスできない可能性があるためです。
1 つの例は、特定の DOM 要素の対話に参加するために JavaScript オブジェクトがカプセル化されることです。 doOnClick、doMouseOver、doMouseOut メソッドがあります。そして、DOM 要素上の対応するイベントがトリガーされたときにこれらのメソッドを実行したいと考えています。ただし、DOM 要素に関連付けられた JavaScript オブジェクトはいくつでも作成できますが、個々のインスタンスは、それらをインスタンス化するコードがそれらのオブジェクトに対して何を行うのかわかりません。オブジェクト インスタンスは、どのグローバル変数 (存在する場合) に参照が割り当てられるかわからないため、自分自身を「グローバルに」参照する方法がわかりません。
つまり、問題は、特定の JavaScript オブジェクト インスタンスに関連付けられたイベント ハンドラー関数を実行し、そのオブジェクトのどのメソッドを呼び出すかを知ることです。
次の例では、要素イベント処理を備えたオブジェクト インスタンスの関連関数に対して単純なクロージャを使用します。イベント ハンドラーには、イベント オブジェクトと関連付けられる要素への参照を渡すことによって呼び出すさまざまなオブジェクト インスタンス メソッドが割り当てられます。
/* 一个给对象实例关联一个事件处理器的普通方法, 返回的内部函数被作为事件的处理器, 对象实例被作为obj参数,对象上将要被调用的方法名称被作为第二个参数 */ function associateObjWithEvent(obj, methodName) { /*返回的内部函数被用来作为一个DOM元素的事件处理器*/ return (function (e) { /* 事件对象在DOM标准的浏览器中将被转换为e参数, 如果没有传递参数给事件处理内部函数,将统一处理成IE的事件对象 */ e = e || window.event; /* 事件处理器调用obj对象上的以methodName字符串标识的方法 并传递两个对象:通用的事件对象,事件处理器被订阅的元素的引用 这里this参数能够使用,因为内部函数已经被执行作为事件处理器所在元素的一个方法 */ return obj[methodName](e, this); }); } /* 这个构造器函数,通过将元素的ID作为字符串参数传递进来, 来创建将自身关联到DOM元素上的对象, 对象实例想在对应的元素触发onclick、onmouseover、onmouseout事件时 对应的方法被调用。 */ function DhtmlObject(elementId) { /* 调用一个方法来获得一个DOM元素的引用 如果没有找到,则为null */ var el = getElementWith(elementId); /* 因为if语句块,el变量的值在内部进行了类型转换,变成了boolean类型 所以当它指向一个对象,结果就为true,如果为null则为false */ if (el) { /* 为了给元素指定一个事件处理函数,调用了associateObjWithEvent函数, 利用它自己(this关键字)作为被调用方法的对象,并且提供方法名称 */ el.onclick = associateObjWithEvent(this, "doOnClick"); el.onmouseover = associateObjWithEvent(this, "doOnMouseOver"); el.onmouseout = associateObjWithEvent(this, "doOnMouseOut"); } } DhtmlObject.prototype.doOnClick = function (event, element) { //doOnClick body } DhtmlObject.prototype.doMouseOver = function (event, element) { //doMouseOver body } DhtmlObject.prototype.doMouseOut = function (event, element) { //doMouseOut body }
DhtmlObject のインスタンスは、関心のある DOM 要素に関連付けることができます。これらの要素が他のコードによってどのように処理され、グローバル名前空間や他の DhtmlObject の競合によって「汚染」されるかを心配する必要はありません。
シナリオ 3: 関連する関数セットのカプセル化
クロージャーは追加のスコープを作成でき、これを使用して関連コードまたは依存コードを結合できます。このようにして、コード干渉の危険を最小限に抑えることができます。関数を使用して文字列を作成し、繰り返しの連結操作 (一連の中間文字列の作成など) を回避するとします。 1 つのアイデアは、配列を使用して文字列の一部を順番に格納し、Array.prototype.join メソッドを使用して結果を出力することです (空の文字列を引数として使用します)。配列は出力バッファの役割を果たしますが、ローカルに定義すると、関数が実行されるたびに配列が再度作成されます。この配列がすべての関数呼び出しに唯一の変数として割り当てられるだけであれば、これは少しやりすぎになります。
1 つの解決策は、配列をグローバル変数に昇格させて、再度作成しなくても再度使用できるようにすることです。しかし、結果は思ったほど単純ではありません。さらに、グローバル変数がバッファ配列を使用する関数に関連付けられている場合、2 番目のグローバル属性 (関数自体もウィンドウ オブジェクトの属性です) が関連付けられます。配列を使用すると、コードの制御性が失われます。他の場所で使用される場合だからです。このコードの作成者は、配列の定義ロジックだけでなく、組み込まれている関数の定義も覚えておく必要がありました。また、関数名がグローバル名前空間内で一意であるかどうかを判断するだけでなく、関数に関連付けられた配列の名前がグローバル名前空間内で一意であるかどうかを判断する必要があるため、コードを他のコードと統合するのが難しくなります。グローバル名前空間。
クロージャーを使用すると、バッファー配列は依存する関数を関連付け (クリーンに含めること)、同時に名前の競合のリスクを回避しながら、バッファー配列のプロパティ名をグローバル空間に割り当てられているかのように維持できます。コード相互作用の干渉。
ここでの 1 つのトリックは、インライン関数式を実行して追加の実行コンテキストを作成し、その関数式が外部コードで使用されるインライン関数を返すようにすることです。バッファ配列は、インラインで実行される関数式のローカル変数として定義されます。これは 1 回だけ呼び出されるため、配列は 1 回だけ作成されます。ただし、配列は、それに依存する関数から常にアクセスでき、再利用できます。
次のコードは、一部変更されていない HTML 文字列を返す関数を作成しますが、これらの変更されていない文字列には、パラメーターとして渡される変数を散在させる必要があります。
一个内联执行的函数表达式返回了内部函数对象的一个引用。并且分配了一个全局变量,让它可以被作为一个全局函数来调用。而缓冲数组作为一个局部变量被定义在外部函数表达式中。它没有被扩展到全局命名空间中,并且无论函数什么时候使用它都不需要被再次创建。
/* 定义一个全局变量:getImgInPositionedDivHtml 被赋予对外部函数表达式一次调用返回的一个内部函数表达式 内部函数返回了一个HTML字符串,代表一个绝对定位的DIV 包裹这一个IMG元素,而所有的变量值都被作为函数调用的参数 */ var getImgInPositionedDivHtml = (function () { /* buffAr 数组被定义在外部函数表达式中,作为一个局部变量 它只被创建一次。数组的唯一实例对内部函数是可见的, 所以它可以被用于每一次的内部函数执行 空字符串仅仅被用来作为一个占位符,它将被内部函数的参数代替 */ var buffAr = [ '<div id="', '', //index 1, DIV ID attribute '" style="position:absolute;top:', '', //index 3, DIV top position 'px;left:', '', //index 5, DIV left position 'px;width:', '', //index 7, DIV width 'px;height:', '', //index 9, DIV height 'px;overflow:hidden;\"><img src=\"', '', //index 11, IMG URL '\" width=\"', '', //index 13, IMG width '\" height=\"', '', //index 15, IMG height '\" alt=\"', '', //index 17, IMG alt text '\"><\/div>' ]; /* 返回一个内部函数对象,他是函数表达式执行返回的结果 */ return (function (url, id, width, height, top, left, altText) { /* 分配各种参数给对应的数组元素 */ buffAr[1] = id; buffAr[3] = top; buffAr[5] = left; buffAr[13] = (buffAr[7] = width); buffAr[15] = (buffAr[9] = height); buffAr[11] = url; buffAr[17] = altText; /* 返回连接每个元素后创建的字符串 */ return buffAr.join(''); }); })();
如果一个函数依赖另一个或几个函数,但那些其他的函数并不期望与任何其他的代码产生交互。那么这个简单的技巧(使用一个对外公开的函数来扩展那些函数)就可以被用来组织那些函数。
上面是我整理给大家的,希望今后会对大家有帮助。
相关文章:
以上がJS でクロージャが悪用される一般的なシナリオは何ですか? (画像とテキストのチュートリアル)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック











昨日の面接で、ロングテール関連の質問をしたかと聞かれたので、簡単にまとめてみようと思いました。自動運転のロングテール問題とは、自動運転車におけるエッジケース、つまり発生確率が低い考えられるシナリオを指します。認識されているロングテール問題は、現在、単一車両のインテリジェント自動運転車の運用設計領域を制限している主な理由の 1 つです。自動運転の基礎となるアーキテクチャとほとんどの技術的問題は解決されており、残りの 5% のロングテール問題が徐々に自動運転の開発を制限する鍵となってきています。これらの問題には、さまざまな断片的なシナリオ、極端な状況、予測不可能な人間の行動が含まれます。自動運転におけるエッジ シナリオの「ロング テール」とは、自動運転車 (AV) におけるエッジ ケースを指します。エッジ ケースは、発生確率が低い可能性のあるシナリオです。これらの珍しい出来事

WebSocket と JavaScript を使用してオンライン音声認識システムを実装する方法 はじめに: 技術の継続的な発展により、音声認識技術は人工知能の分野の重要な部分になりました。 WebSocket と JavaScript をベースとしたオンライン音声認識システムは、低遅延、リアルタイム、クロスプラットフォームという特徴があり、広く使用されるソリューションとなっています。この記事では、WebSocket と JavaScript を使用してオンライン音声認識システムを実装する方法を紹介します。

WebSocketとJavaScript:リアルタイム監視システムを実現するためのキーテクノロジー はじめに: インターネット技術の急速な発展に伴い、リアルタイム監視システムは様々な分野で広く利用されています。リアルタイム監視を実現するための重要なテクノロジーの 1 つは、WebSocket と JavaScript の組み合わせです。この記事では、リアルタイム監視システムにおける WebSocket と JavaScript のアプリケーションを紹介し、コード例を示し、その実装原理を詳しく説明します。 1.WebSocketテクノロジー

WebSocket と JavaScript を使用してオンライン予約システムを実装する方法 今日のデジタル時代では、ますます多くの企業やサービスがオンライン予約機能を提供する必要があります。効率的かつリアルタイムのオンライン予約システムを実装することが重要です。この記事では、WebSocket と JavaScript を使用してオンライン予約システムを実装する方法と、具体的なコード例を紹介します。 1. WebSocket とは何ですか? WebSocket は、単一の TCP 接続における全二重方式です。

JavaScript と WebSocket を使用してリアルタイム オンライン注文システムを実装する方法の紹介: インターネットの普及とテクノロジーの進歩に伴い、ますます多くのレストランがオンライン注文サービスを提供し始めています。リアルタイムのオンライン注文システムを実装するには、JavaScript と WebSocket テクノロジを使用できます。 WebSocket は、TCP プロトコルをベースとした全二重通信プロトコルで、クライアントとサーバー間のリアルタイム双方向通信を実現します。リアルタイムオンラインオーダーシステムにおいて、ユーザーが料理を選択して注文するとき

JavaScript と WebSocket: 効率的なリアルタイム天気予報システムの構築 はじめに: 今日、天気予報の精度は日常生活と意思決定にとって非常に重要です。テクノロジーの発展に伴い、リアルタイムで気象データを取得することで、より正確で信頼性の高い天気予報を提供できるようになりました。この記事では、JavaScript と WebSocket テクノロジを使用して効率的なリアルタイム天気予報システムを構築する方法を学びます。この記事では、具体的なコード例を通じて実装プロセスを説明します。私たちは

JavaScript チュートリアル: HTTP ステータス コードを取得する方法、特定のコード例が必要です 序文: Web 開発では、サーバーとのデータ対話が頻繁に発生します。サーバーと通信するとき、多くの場合、返された HTTP ステータス コードを取得して操作が成功したかどうかを判断し、さまざまなステータス コードに基づいて対応する処理を実行する必要があります。この記事では、JavaScript を使用して HTTP ステータス コードを取得する方法を説明し、いくつかの実用的なコード例を示します。 XMLHttpRequestの使用

JavaScript で HTTP ステータス コードを取得する方法の紹介: フロントエンド開発では、バックエンド インターフェイスとの対話を処理する必要があることが多く、HTTP ステータス コードはその非常に重要な部分です。 HTTP ステータス コードを理解して取得すると、インターフェイスから返されたデータをより適切に処理できるようになります。この記事では、JavaScript を使用して HTTP ステータス コードを取得する方法と、具体的なコード例を紹介します。 1. HTTP ステータス コードとは何ですか? HTTP ステータス コードとは、ブラウザがサーバーへのリクエストを開始したときに、サービスが
