検索
ホームページウェブフロントエンドjsチュートリアルJavaScript クロージャーの概念についての理解を深めます。

インターネット上で JavaScript クロージャ関連の情報をたくさんチェックしましたが、そのほとんどは非常に学術的で専門的なものでした。初心者にとっては、クロージャを理解することはおろか、テキストの説明すら理解することが困難です。この記事を書く目的は、最も一般的な言葉を使って JavaScript クロージャの本当の姿を明らかにすることです。

1. 閉鎖とは何ですか?

「公式」の説明は次のとおりです: クロージャは、多くの変数とこれらの変数にバインドされた環境を持つ式 (通常は関数) であり、したがって、これらの変数も式の一部です。 あまりにも学術的な記述のため、この文章を直接理解できる人は少ないと思います。実際、この文は平たく言えば、「JavaScript のすべての関数はクロージャである」という意味です。しかし、一般的に言えば、入れ子関数によって生成されたクロージャはより強力であり、ほとんどの場合、これが「クロージャ」と呼ばれるものです。次のコードを見てください:

function a() {
    var i = 0;
    function b() {
        alert(++i);
    }
    return b;
}
var c = a();
c();

このコードには 2 つの特徴があります:

関数 b は関数 a 内にネストされています;

関数 a は関数 b を返します。

このように、var c=a() を実行すると、変数 c は実際には関数 b を指します。変数 i は b で使用されます。c() を実行すると、i の値を表示するウィンドウが表示されます。時間は1)です。このコードは実際にクロージャを作成します。なぜでしょうか。関数 a の外側の変数 c は関数 a 内の関数 b を参照しているため、つまり、関数 a の内部関数 b が関数 a の外側の変数によって参照される場合、いわゆる「クロージャ」が作成されます。

もっと徹底しましょう。いわゆる「クロージャ」とは、コンストラクタ本体内に別の関数を対象オブジェクトのメソッド関数として定義し、そのオブジェクトのメソッド関数が外側の関数本体内の一時変数を参照することです。これにより、ターゲット オブジェクトが存続期間中常にそのメソッドを維持できる限り、元のコンストラクター本体で使用される一時変数の値を間接的に維持できます。最初のコンストラクター呼び出しが終了し、一時変数の名前が消えていますが、変数の値はターゲット オブジェクトのメソッド内で常に参照でき、このメソッドを介してのみ値にアクセスできます。同じコンストラクターが再度呼び出された場合でも、新しいオブジェクトとメソッドのみが生成され、新しい一時変数は最後の呼び出しから独立した新しい値にのみ対応します。

クロージャをより深く理解するために、クロージャの機能と効果を引き続き調べてみましょう。

2. クロージャの機能と効果は何ですか?

つまり、クロージャの機能は、a が実行されて返された後、a の内部関数 b の実行は変数に依存する必要があるため、JavaScript のガベージ コレクション メカニズム GC が a によって占有されているリソースを再利用するのをクロージャが阻止することです。これはクロージャの役割を非常に簡単に説明したもので、専門的でも厳密でもありませんが、必ず理解できます。クロージャを理解するには、段階的なプロセスが必要です。

上記の例では、クロージャの存在により、関数aが戻った後もaのiが常に存在します。このように、c()が実行されるたびに、iは1を加えた後に通知されるiの値になります。 。

次に、a が関数 b 以外の値を返す場合、状況はまったく異なります。 a が実行された後、b は a の外に戻されるのではなく、a によってのみ参照されるため、関数 a と関数 b は相互に参照しますが、干渉されません。外部の世界によって (外部の世界によって参照される)、関数 a と b は GC によってリサイクルされます。

3. クロージャのミクロの世界

クロージャと関数 a と入れ子関数 b の関係をより深く理解したい場合は、関数実行コンテキスト (実行コンテキスト)、アクティブ オブジェクトなどの他の概念を導入する必要があります。 (呼び出し) オブジェクト)、スコープ、スコープ チェーン。これらの概念を説明するために、関数 a の定義から実行までのプロセスを例として取り上げます。

関数 a を定義するとき、js インタープリターは関数 a のスコープ チェーンを、 a がグローバル関数の場合、スコープ チェーン内に存在する「環境」に設定します。

関数 a を実行すると、 a は対応する実行コンテキストに入ります。

実行環境を作成するプロセスでは、最初に a にscope属性が追加されます。これはaのスコープであり、その値はステップ1のスコープチェーンです。つまり、a.scope=a のスコープ チェーンです。

その後、実行環境は呼び出しオブジェクトを作成します。アクティブ オブジェクトもプロパティを持つオブジェクトですが、プロトタイプを持たないため、JavaScript コードから直接アクセスできません。アクティブ オブジェクトを作成した後、そのアクティブ オブジェクトを のスコープ チェーンの先頭に追加します。この時点で、a のスコープ チェーンには、a のアクティブ オブジェクトとウィンドウ オブジェクトの 2 つのオブジェクトが含まれています。

次のステップは、関数 a を呼び出すときに渡されるパラメーターを保持する、アクティブなオブジェクトに argument 属性を追加することです。

最后把所有函数a的形参和内部的函数b的引用也添加到a的活动对象上。在这一步中,完成了函数b的的定义,因此如同第3步,函数b的作用域链被设置为b所被定义的环境,即a的作用域。

到此,整个函数a从定义到执行的步骤就完成了。此时a返回函数b的引用给c,又函数b的作用域链包含了对函数a的活动对象的引用,也就是说b可以访问到a中定义的所有变量和函数。函数b被c引用,函数b又依赖函数a,因此函数a在返回后不会被GC回收。

当函数b执行的时候亦会像以上步骤一样。因此,执行时b的作用域链包含了3个对象:b的活动对象、a的活动对象和window对象

当在函数b中访问一个变量的时候,搜索顺序是:

先搜索自身的活动对象,如果存在则返回,如果不存在将继续搜索函数a的活动对象,依次查找,直到找到为止。

如果函数b存在prototype原型对象,则在查找完自身的活动对象后先查找自身的原型对象,再继续查找。这就是Javascript中的变量查找机制。

如果整个作用域链上都无法找到,则返回undefined。

小结,本段中提到了两个重要的词语:函数的定义与执行。文中提到函数的作用域是在定义函数时候就已经确定,而不是在执行的时候确定(参看步骤1和3)。用一段代码来说明这个问题:

function f(x) {
    var g = function () { return x; }
    return g;
}
var h = f(1);
alert(h());

这段代码中变量h指向了f中的那个匿名函数(由g返回)。

假设函数h的作用域是在执行alert(h())确定的,那么此时h的作用域链是:h的活动对象->alert的活动对象->window对象。

假设函数h的作用域是在定义时确定的,就是说h指向的那个匿名函数在定义的时候就已经确定了作用域。那么在执行的时候,h的作用域链为:h的活动对象->f的活动对象->window对象。

如果第一种假设成立,那输出值就是undefined;如果第二种假设成立,输出值则为1。运行结果证明了第2个假设是正确的,说明函数的作用域确实是在定义这个函数的时候就已经确定了。

4. 闭包的应用场景

保护函数内的变量安全。以最开始的例子为例,函数a中i只有函数b才能访问,而无法通过其他途径访问到,因此保护了i的安全性。

在内存中维持一个变量。依然如前例,由于闭包,函数a中i的一直存在于内存中,因此每次执行c(),都会给i自加1。

function Constructor(...) {
    var that = this;
    var membername = value;
    function membername(...) {...}
}

以上3点是闭包最基本的应用场景,很多经典案例都源于此。

5. JavaScript的垃圾回收机制

在Javascript中,如果一个对象不再被引用,那么这个对象就会被GC回收。如果两个对象互相引用,而不再被第3者所引用,那么这两个互相引用的对象也会被回收。因为函数a被b引用,b又被a外的c引用,这就是为什么函数a执行后不会被回收的原因。

6. 结语

理解JavaScript的闭包是迈向高级JS程序员的必经之路,理解了其解释和运行机制才能写出更为安全和优雅的代码。


声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、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ヘンタイを無料で生成します。

ホットツール

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

このプロジェクトは osdn.net/projects/mingw に移行中です。引き続きそこでフォローしていただけます。 MinGW: GNU Compiler Collection (GCC) のネイティブ Windows ポートであり、ネイティブ Windows アプリケーションを構築するための自由に配布可能なインポート ライブラリとヘッダー ファイルであり、C99 機能をサポートする MSVC ランタイムの拡張機能が含まれています。すべての MinGW ソフトウェアは 64 ビット Windows プラットフォームで実行できます。

MantisBT

MantisBT

Mantis は、製品の欠陥追跡を支援するために設計された、導入が簡単な Web ベースの欠陥追跡ツールです。 PHP、MySQL、Web サーバーが必要です。デモおよびホスティング サービスをチェックしてください。

SublimeText3 Mac版

SublimeText3 Mac版

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

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

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