関数の定義: a. 関数宣言 functionName (name, age) {}————関数宣言のプロモーション
b. 関数式 var functionName=function (name, age) {};
変数のスコープは 2 つだけです: グローバル変数とローカル変数です。 JavaScript 言語の特別な点は、グローバル変数を関数内で直接読み取ることができることです。 ローカル変数を外部から読み取るにはどうすればよいですか? それは、関数の中に別の関数を定義することです。内部関数を戻り値として使用することで、その内部変数を外部から読み取ることができます。 クロージャは、他の関数の内部変数を読み取ることができる関数です。 JavaScript言語ではローカル変数を読み込めるのは関数内のサブ関数のみなので、クロージャは単純に「関数内で定義された関数」と理解できます。 つまり、本質的に、クロージャは関数の内部と関数の外部を接続する橋です。 これには 2 つの大きな用途があります。1 つは前述したように関数内の変数を読み取ること、もう 1 つはこれらの変数の値をメモリに保持することです。 クロージャの使用に関する注意事項1) クロージャは関数内の変数をメモリに格納し、大量のメモリを消費するため、クロージャを悪用することはできません。悪用しないと、Web ページでパフォーマンスの問題が発生します。 IEでメモリリークが発生する可能性があります。解決策は、関数を終了する前に、未使用のローカル変数をすべて削除することです。 2) クロージャは、親関数内の変数の値を親関数の外に変更します。したがって、親関数をオブジェクトとして使用し、クロージャをそのパブリック メソッドとして使用し、内部変数をプライベート値として使用する場合は、親関数内の変数の値を自由に変更しないように注意する必要があります。 クロージャは、特に JS 初心者にとっては非常に曖昧な概念であり、私にとっても同様です しかし、JS の機能を向上させる上で避けては通れないものでもあります。最初のステップは、ほぼすべての面接で聞かれなければならない質問です。なぜなら、これに答えると、答えの深さ、用語の理解、JS の内部インタープリターの動作の説明によって、実際のレベルが明らかになるからです。 js. たとえ正解できなかったとしても、試験官にあなたのレベルを評価してもらうことができます。そこで、まず js におけるクロージャについて話しましょう。クロージャは、js の多くの言語に備わっている機能です。パッケージには主に、スコープ チェーン、ガベージ (メモリ) リサイクル メカニズム、関数のネストなど、JS の他のいくつかの機能が含まれます。 クロージャーを理解する前に、まずスコープ チェーンの意味を理解するのが最善です。簡単に言うと、スコープ チェーンです。関数が定義されるときに、使用される変数の値を検索するために作成されるインデックスです。その内部規則は、関数自身のローカル変数を先頭に配置し、親関数の変数を 2 番目に配置します。上位レベルの関数はさらに後ろに配置され、グローバル オブジェクトが関数内で変数の値を照会する必要がある場合、JS インタープリターは先頭のローカル変数から開始してドメイン チェーンを検索するアクションを実行します。対応する変数が見つからない場合は、変数が見つかっても続行しないでください。変数が最後に見つからない場合、インタープリタは戻ります。 unknown.スコープチェーンを理解した後、js のメモリリサイクルメカニズムを見てみましょう。一般的に、関数の実行が開始されると、関数内で定義された変数はメモリ空間に分割されて保存されます。後続のステートメントが完了すると、これらの変数は使用されないとみなされ、次回この関数が実行されると、すべての変数が元の値に戻ります。この関数内に関数がネストされており、この関数が外部から呼び出される可能性があります。また、この内部関数は外部関数の一部の変数を使用します。内部関数が外部関数の直後に呼び出される場合、リサイクル メカニズムに問題が発生します。が返されると、内部関数は必要な外部関数の変数の値を読み取ることができなくなります。そのため、JS インタープリターは時間に達すると関数定義に遭遇し、関数は変数とともに自動的に保存されます。 (ローカル変数と親および祖先関数の変数 (自由変数) を含む) を使用する可能性があります。つまり、クロージャが構築され、これらの変数はメモリ コレクターによって使用されなくなります。内部関数を呼び出すことができない場合にのみ破棄され (たとえば、関数が削除されたり、ポインターがない場合)、次回のメモリのリサイクルが開始されるときに、クロージャによって参照される変数は破棄されません。クロージャを使用すると、ネストされた関数構造が動作します。これは私たちの期待と一致しています。クロージャにはいくつかの機能がありますが、多くの場合、プログラマにとっては理解しにくいです。var result=[];function foo(){ var i= 0; for (;i<3;i=i+1){ result[i]=function(){ alert(i) } } }; foo(); result[0](); // 3 result[1](); // 3 result[2](); // 3
。
这段代码中,程序员希望foo函数中的变量i被内部循环的函数使用,并且能分别获得他们的索引,而实际上,只能获得该变量最后保留的值,也就是说.闭包中所记录的自由变量,只是对这个变量的一个引用,而非变量的值,当这个变量被改变了,闭包里获取到的变量值,也会被改变.
解决的方法之一,是让内部函数在循环创建的时候立即执行,并且捕捉当前的索引值,然后记录在自己的一个本地变量里.然后利用返回函数的方法,重写内部函数,让下一次调用的时候,返回本地变量的值,改进后的代码
var result=[];function foo(){ var i= 0; for (;i<3;i=i+1){ result[i]=(function(j){ return function(){ alert(j); }; })(i); } }; foo(); result[0](); // 0 result[1](); // 1 result[2](); // 2
在这里我再解释一下.这里用到了另外2个技术,立即调用的匿名函数和返回函数.也是初学者比较难以理解的部分.
私有变量
任何在函数中定义的变量,都可以是私有变量。
把有权访问私有变量和私有函数的方法称为特权方法,a)在构造函数中定义特权方法
b)在私有作用域中定义变量或函数,私有变量和函数由实例共享
模块模式——为单例创建私有变量和特权方法。单例,指只有一个实例的对象
使用一个返回对象的匿名函数,函数内部首先定义私有变量和函数,将一个对象字面量作为函数的值返回,返回的 对象字面量只包含公开的属性和方法。