JavaScriptのクロージャとは何ですか

青灯夜游
リリース: 2021-11-24 13:40:04
オリジナル
2222 人が閲覧しました

JavaScript では、2 つの関数が相互にネストされている場合、内部関数はクロージャです。クロージャは、別の関数のスコープ内の変数にアクセスできる関数です。クロージャを作成する最も一般的な方法は、関数内に別の関数を作成し、その関数を通じてこの関数のローカル変数にアクセスすることです。

JavaScriptのクロージャとは何ですか

このチュートリアルの動作環境: Windows7 システム、JavaScript バージョン 1.8.5、Dell G3 コンピューター。

1. クロージャとは何ですか?

クロージャは、他の関数の内部変数を読み取ることができる関数です。 JavaScript では、関数内のサブ関数のみがローカル変数を読み取ることができるため、クロージャは「関数内で定義された関数」として理解できます。本質的に、クロージャは関数の内部と関数の外部の間のブリッジです。 (クロージャの最も一般的なアプリケーションは、コールバック関数を実装することです)。

2. JS のクロージャーの長所、短所、および特性

利点:

1 , 関数内の変数のセキュリティを保護する

2. 変数をメモリに保持する (使いすぎると不利になり、メモリを占有する);

3. 論理的連続性、クロージャの場合別の関数呼び出しのパラメーターとして使用すると、現在のロジックとは別に追加のロジックを作成できなくなります。

4. コンテキストの呼び出しを容易にするローカル変数。

5. カプセル化を強化すると、変数を保護できます。

欠点:

1. 常駐メモリによりメモリ使用量が増加し、不適切に使用するとメモリ リークが発生しやすくなります。
2. また、非常に深刻な問題があり、それはメモリの浪費の問題です。このメモリの浪費はメモリ内に常駐するためだけではなく、さらに重要なことに、クロージャの不適切な使用により無効なメモリが生成されることです。

機能:

1. 関数のネストされた関数

2. 内部関数は外部関数の変数にアクセスできます

3. パラメータと変数は再利用されません。

3. 変数スコープ

クロージャを理解するには、上記のクロージャの概念を理解するだけでは十分ではありません。まず、JavaScript の特殊な変数スコープを理解する必要があります。

1. 変数のスコープは 2 つだけです: グローバル変数とローカル変数です。

2. JavaScript 言語の特別な点は、グローバル変数は関数内で直接読み取ることができますが、関数内のローカル変数は関数の外から読み取ることができないことです。

3. 注: 関数内で変数を宣言する場合は、必ず var コマンドを使用してください。これを使用しない場合、実際にはグローバル変数を宣言していることになります。

4. コードでクロージャを解釈する

Javascript でのクロージャの作成プロセスは次のプログラムのようになります。

function a () {
   var i = 0;
   function b () {
      alert (i++);
   }
  return b;
}
var c = a();
c();  //函数调用
ログイン後にコピー

コードの機能

このコードには 2 つの機能があります。

1. 関数 b は関数 a にネストされています。内部。

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

このように、var c = a() を実行すると、変数 c は実際には関数 b を指します。c() を再度実行すると、ウィンドウがポップアップして i の値が表示されます (1 回目は1) 。関数 a の外側の変数 c が関数 a 内の関数 b を参照しているため、このコードは実際にクロージャを作成します。つまり、関数 a 内の関数 b が関数 a の外側の変数によって参照されると、クロージャが作成されます。

関数

要するに、クロージャの機能は、 a が実行されて返された後に Javascript のガベージ コレクションを有効にすることです。 a の内部関数 b の実行は a の変数に依存する必要があるため、a が占有しているリソースを再利用します。

上記の例では、クロージャの存在により、関数 a が戻った後も a の i が常に存在するため、c() が実行されるたびに、i は i の値になります。 1 を追加すると警告が表示されます。

では、別の状況を想像してみましょう。a が関数 b 以外の値を返す場合、状況はまったく異なります。 a が実行された後、b は a の外に戻されるのではなく、a から参照されるだけです。このとき、a は b からのみ参照されます。そのため、関数 a と関数 b は相互に参照しますが、乱されることはありません。 by the external world (外の世界から参照される) 、関数 a と b はリサイクルされます。

アプリケーション シナリオ

1. 関数内の変数を保護します。関数 a では、i には関数 b によってのみアクセスでき、他の手段ではアクセスできないため、i のセキュリティが保護されます。

2. 変数をメモリ内に保持します。クロージャにより、関数 a の i は常にメモリ内に存在するため、c() が実行されるたびに i が 1 ずつインクリメントされます。

五、如何从外部读取函数内部的局部变量?

  出于种种原因,我们有时候需要获取到函数内部的局部变量。但是,上面(三、变量作用域)已经说过了,正常情况下,这是办不到的!只有通过变通的方法才能实现。那就是在函数内部,再定义一个函数。

function demo1 () {
    var n = 6699;
    function demo2 () {
      alert(n); // 6699
    }
  }
ログイン後にコピー

在上面的代码中,函数 demo2 就被包括在函数demo1内部,这时demo1内部的所有局部变量,对demo2都是可见的。但是反过来就不行,demo2内部的局部变量,对demo1就是不可见的。 

这就是Javascript语言特有的”链式作用域”结构(chain scope),子对象会一级一级地向上寻找所有父对象的变量。所以,父对象的所有变量,对子对象都是可见的,反之则不成立。 

既然demo2可以读取demo1中的局部变量,那么只要把demo2作为返回值,我们不就可以在demo1外部读取它的内部变量了吗!

六、闭包的用途

闭包可以用在许多地方。它的最大用处有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中,不会在demo1调用后被自动清除。 

那为什么会这样呢?原因就在于demo1是demo2的父函数,而demo2被赋给了一个全局变量,这导致demo2始终在内存中,而demo2的存在依赖于demo1,因此demo1也始终在内存中,不会在调用结束后,被垃圾回收机制(garbage collection)回收。

七、使用闭包的注意点

1、由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。 

2、闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。

八、总结:

1、闭包是指有权访问另一个函数作用域中的变量的函数,创建闭包的最常见的方式就是在一个函数内创建另一个函数,通过另一个函数访问这个函数的局部变量。闭包的缺点就是常驻内存,会增大内存使用量,使用不当很容易造成内存泄露。 

2、不适合场景:返回闭包的函数是个非常大的函数。 

    闭包的典型框架应该就是jquery了。 

    闭包是javascript语言的一大特点,主要应用闭包场合主要是为了:设计私有的方法和变量。 

    这在做框架的时候体现更明显,有些方法和属性只是运算逻辑过程中的使用的,不想让外部修改这些属性,因此就可以设计一个闭包来只提供方法获取。 

3、 不必纠结到底怎样才算闭包,其实你写的每一个函数都算作闭包,即使是全局函数,你访问函数外部的全局变量时,就是闭包
的体现。

更多编程相关知识,请访问:编程入门!!

以上がJavaScriptのクロージャとは何ですかの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート