検索
ホームページウェブフロントエンドjsチュートリアル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 = [  
                 &#39;<div id="&#39;,  
                &#39;&#39;,   //index 1, DIV ID attribute  
                &#39;" style="position:absolute;top:&#39;,  
                &#39;&#39;,   //index 3, DIV top position  
                &#39;px;left:&#39;,  
                &#39;&#39;,   //index 5, DIV left position  
                &#39;px;width:&#39;,  
                &#39;&#39;,   //index 7, DIV width  
                &#39;px;height:&#39;,  
                &#39;&#39;,   //index 9, DIV height  
                &#39;px;overflow:hidden;\"><img src=\"&#39;,  
                &#39;&#39;,   //index 11, IMG URL  
                &#39;\" width=\"&#39;,  
                &#39;&#39;,   //index 13, IMG width  
                &#39;\" height=\"&#39;,  
                &#39;&#39;,   //index 15, IMG height  
                &#39;\" alt=\"&#39;,  
                &#39;&#39;,   //index 17, IMG alt text  
                &#39;\"><\/div>&#39;  
            ];  
            /* 
            返回一个内部函数对象,他是函数表达式执行返回的结果 
            */  
            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(&#39;&#39;);  
            });  
        })();

如果一个函数依赖另一个或几个函数,但那些其他的函数并不期望与任何其他的代码产生交互。那么这个简单的技巧(使用一个对外公开的函数来扩展那些函数)就可以被用来组织那些函数。

上面是我整理给大家的,希望今后会对大家有帮助。

相关文章:

JS取得最小公倍数与最大公约数

JS实现数组去重算法

使用JS实现购物车功能步骤详解

以上がJS でクロージャが悪用される一般的なシナリオは何ですか? (画像とテキストのチュートリアル)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
JavaScriptエンジン:実装の比較JavaScriptエンジン:実装の比較Apr 13, 2025 am 12:05 AM

さまざまなJavaScriptエンジンは、各エンジンの実装原則と最適化戦略が異なるため、JavaScriptコードを解析および実行するときに異なる効果をもたらします。 1。語彙分析:ソースコードを語彙ユニットに変換します。 2。文法分析:抽象的な構文ツリーを生成します。 3。最適化とコンパイル:JITコンパイラを介してマシンコードを生成します。 4。実行:マシンコードを実行します。 V8エンジンはインスタントコンピレーションと非表示クラスを通じて最適化され、Spidermonkeyはタイプ推論システムを使用して、同じコードで異なるパフォーマンスパフォーマンスをもたらします。

ブラウザを超えて:現実世界のJavaScriptブラウザを超えて:現実世界のJavaScriptApr 12, 2025 am 12:06 AM

現実世界におけるJavaScriptのアプリケーションには、サーバー側のプログラミング、モバイルアプリケーション開発、モノのインターネット制御が含まれます。 2。モバイルアプリケーションの開発は、ReactNativeを通じて実行され、クロスプラットフォームの展開をサポートします。 3.ハードウェアの相互作用に適したJohnny-Fiveライブラリを介したIoTデバイス制御に使用されます。

next.jsを使用してマルチテナントSaaSアプリケーションを構築する(バックエンド統合)next.jsを使用してマルチテナントSaaSアプリケーションを構築する(バックエンド統合)Apr 11, 2025 am 08:23 AM

私はあなたの日常的な技術ツールを使用して機能的なマルチテナントSaaSアプリケーション(EDTECHアプリ)を作成しましたが、あなたは同じことをすることができます。 まず、マルチテナントSaaSアプリケーションとは何ですか? マルチテナントSaaSアプリケーションを使用すると、Singの複数の顧客にサービスを提供できます

next.jsを使用してマルチテナントSaaSアプリケーションを構築する方法(フロントエンド統合)next.jsを使用してマルチテナントSaaSアプリケーションを構築する方法(フロントエンド統合)Apr 11, 2025 am 08:22 AM

この記事では、許可によって保護されたバックエンドとのフロントエンド統合を示し、next.jsを使用して機能的なedtech SaaSアプリケーションを構築します。 FrontEndはユーザーのアクセス許可を取得してUIの可視性を制御し、APIリクエストがロールベースに付着することを保証します

JavaScript:Web言語の汎用性の調査JavaScript:Web言語の汎用性の調査Apr 11, 2025 am 12:01 AM

JavaScriptは、現代のWeb開発のコア言語であり、その多様性と柔軟性に広く使用されています。 1)フロントエンド開発:DOM操作と最新のフレームワーク(React、Vue.JS、Angularなど)を通じて、動的なWebページとシングルページアプリケーションを構築します。 2)サーバー側の開発:node.jsは、非ブロッキングI/Oモデルを使用して、高い並行性とリアルタイムアプリケーションを処理します。 3)モバイルおよびデスクトップアプリケーション開発:クロスプラットフォーム開発は、反応および電子を通じて実現され、開発効率を向上させます。

JavaScriptの進化:現在の傾向と将来の見通しJavaScriptの進化:現在の傾向と将来の見通しApr 10, 2025 am 09:33 AM

JavaScriptの最新トレンドには、TypeScriptの台頭、最新のフレームワークとライブラリの人気、WebAssemblyの適用が含まれます。将来の見通しは、より強力なタイプシステム、サーバー側のJavaScriptの開発、人工知能と機械学習の拡大、およびIoTおよびEDGEコンピューティングの可能性をカバーしています。

javascriptの分解:それが何をするのか、なぜそれが重要なのかjavascriptの分解:それが何をするのか、なぜそれが重要なのかApr 09, 2025 am 12:07 AM

JavaScriptは現代のWeb開発の基礎であり、その主な機能には、イベント駆動型のプログラミング、動的コンテンツ生成、非同期プログラミングが含まれます。 1)イベント駆動型プログラミングにより、Webページはユーザー操作に応じて動的に変更できます。 2)動的コンテンツ生成により、条件に応じてページコンテンツを調整できます。 3)非同期プログラミングにより、ユーザーインターフェイスがブロックされないようにします。 JavaScriptは、Webインタラクション、シングルページアプリケーション、サーバー側の開発で広く使用されており、ユーザーエクスペリエンスとクロスプラットフォーム開発の柔軟性を大幅に改善しています。

pythonまたはjavascriptの方がいいですか?pythonまたはjavascriptの方がいいですか?Apr 06, 2025 am 12:14 AM

Pythonはデータサイエンスや機械学習により適していますが、JavaScriptはフロントエンドとフルスタックの開発により適しています。 1. Pythonは、簡潔な構文とリッチライブラリエコシステムで知られており、データ分析とWeb開発に適しています。 2。JavaScriptは、フロントエンド開発の中核です。 node.jsはサーバー側のプログラミングをサポートしており、フルスタック開発に適しています。

See all articles

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

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

ホットツール

VSCode Windows 64 ビットのダウンロード

VSCode Windows 64 ビットのダウンロード

Microsoft によって発売された無料で強力な IDE エディター

SublimeText3 Linux 新バージョン

SublimeText3 Linux 新バージョン

SublimeText3 Linux 最新バージョン

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

強力な PHP 統合開発環境

SublimeText3 英語版

SublimeText3 英語版

推奨: Win バージョン、コードプロンプトをサポート!

AtomエディタMac版ダウンロード

AtomエディタMac版ダウンロード

最も人気のあるオープンソースエディター