関数
関数形式
関数getPrototyNames(o、/*optional*/ a){a = a || []; for(o in o){a.push(p);} return a;}発信者
func.callerは関数発信者を返します
function callfunc(){if(callfunc.caller){alert(callfunc.caller.tostring());} elsert( "no function call");}} function handlecaller(){callfunc();} handlecaller();/return handlerfunc();カリー
匿名の方法再帰コール
alert((function(x){if(x <=)return; return x * arguments.callee(x-);}()); //範囲
誰もがその範囲に精通しています。今日は閉鎖の問題について話し、閉鎖の問題を徹底的に理解します。
<script> var global = "global scope"; //これはグローバルスコープ関数scope(){var scope = "local scope"; //ローカルスコープリターンスコープ; //返されたスコープはローカル変数} </script>1。:定義されたグローバル変数には、関数内でもアクセスできます。定義されたローカル変数とグローバル変数名が同じ場合、ローカル変数はグローバル変数を非表示にし、グローバル変数の値を破壊しません。
var scope = "global scope"; function f(){var scope = "local scope"; return scope;} alert(f()); // local scopealert(scope); // global scope;上記は確かに理解しやすいですよね?
2。グローバル変数はvarなしで宣言できますが、局所変数はvarで宣言する必要があります。ローカル変数がVAR宣言を使用しない場合、コンパイラはこれをグローバル変数としてデフォルトにします。
<span style = "line-height:。; font-family:verdana、arial、helvetica、sans-serif; font-size:px; background-color:rgb(、> span> scope =" global scope "; function f(){){scope =" local scope "; return scope;} alert(scope();}ただし、グローバル変数はVAR宣言を使用せず、非厳格なモードでのみ使用できます。厳密なモードを使用すると、エラーが報告されます。
<Script> "Strict"; Scope = "Global Scope"; function f(){scope = "local scope"; return scope;} alert(f()); // local scopealert(scope); // local scope </scrip> scrip>したがって、不必要なトラブルを回避できるため、変数を宣言するときはVARを省略しないことをお勧めします。
3。事前に宣言しても大丈夫です。前もって何があるのか。
<Script>「Strict "を使用します; scope; console.log(scope); var scope =" global scope "; console.log(scope); </script>
これは、未定義で最初に印刷したものと見なされる場合があります。はい、まだ値が割り当てられていません。次の割り当てでは、グローバルな範囲を決定できます。
これは間違っていませんが、なぜこれが起こっているのですか?変数を使用する前に定義する必要はありませんか?
ここでは、スコープチェーンについてお話しします。 JavaScriptは語彙スコープ言語です。
1.スコープチェーンはオブジェクトまたはリンクリストです。このコードセットは、このコードの変数「範囲」を定義します。 JavaScriptが可変スコープを見つける必要がある場合、チェーン内の最初のオブジェクトから開発および検索します。最初のオブジェクトがスコープの場合、このオブジェクトの値は直接返されます。存在しない場合、見つかるまで2番目のオブジェクトを検索し続けます。スコープチェーンに変数が見つからない場合、エラーがスローされます。
この機能チェーンを次のように表現できます。スコープ - >ウィンドウ(グローバルオブジェクト)を見つけると、スコープが定義されます。ただし、割り当て操作は実行されず、割り当て操作は後で実行されたため、現時点では値は未定義です。
4.これはより混乱しています。印刷された値は何ですか?
<Script> "Strict"; var scope = "global scope"; function f(){console.log(scope); var scope = "local scope"; console.log(scope);} f(); </script>;} f(); </script>このコードを参照してください:不注意な場合は、間違った答えを書くことができます。
1。ゴールスコープ
2。ローカルスコープ
分析:グローバル変数を宣言します。関数本文では、最初のものがグローバル変数を表すため、グローバルが印刷され、2番目のものがグローバルスコープをカバーするローカル変数を定義するため、ローカルスコープが印刷されます。
このような分析は、C#Javaで完全に正しいです。しかし、ここでの分析は確かに間違っています。
これは、この問題の前に、最初に質問を見てみましょう。
この文は非常に重要です。グローバル変数は常にプログラムで定義されています。ローカル変数は、それを宣言する関数とそれがネストする関数の本体内で常に定義されます。
高レベルの言語で作業している場合、そのスコープ定義には少し不適切にJavaScriptにさらされています。私も同じです。例を見てみましょう:
<script> var g = "global scope"; function f(){for(var i =; i <; i ++){for(var j =; j <; j ++){;} console.log(j);} console.log(i);} console.log(g); f(); </script>印刷の結果は何ですか?
{}はステートメントブロックを表し、ステートメントブロックが同じブロックの範囲内にあることがわかります。したがって、JとIの値がメモリ内でリリースされたと推測される可能性があるため、結果は未定義でなければなりません。
本当の結果はあなたを失望させるかもしれません。
なぜこれが起こったのですか?私の表現はあなたのように始まりました。
私があなたに今覚えておくように頼んだ文をチェックしてください。 。 。グローバル変数は常にプログラムで定義されています。ローカル変数は、それを宣言する関数とそれがネストする関数の本体内で常に定義されます。
正確には、関数のパラメーターはローカル変数のカテゴリにも属します。この文も非常に重要です! ! !
その文は、関数内で定義されている変数が関数全体で有効である限り、ほぼ意味します。したがって、結果を理解するのは難しくありません。私たちの質問を振り返ってみると、わかりますか?
行動のチェーンには、次の定義もあります。
1.アクションチェーンは、グローバルオブジェクトで構成されています。
2。ネストを含まない関数本体には、アクションチェーンに2つのオブジェクトがあります。最初のオブジェクトは関数パラメーターとローカル変数を定義し、2番目はグローバルオブジェクトです。
3。ネストされた関数本文では、アクションチェーンに少なくとも3つのオブジェクトがあります。
関数が定義されると、スコープチェーンが保存されます。
この関数が呼び出されると、ローカル変数を保存する新しいオブジェクトを作成し、このオブジェクトを保存されたアクションチェーンに追加します。同時に、関数呼び出しを表す新しい長い関数チェーンを作成します。
ネストされた関数の場合、外部関数が呼び出されると、内部関数が再び再定義されます。外部関数が呼び出されるたびに、アクションチェーンが異なるためです。内部関数には、定義されるたびに微妙な違いがあります。外部関数が呼び出されるたびに、内部関数のコードは同じであり、関連するコードの範囲も異なります。
閉鎖
長い間それをした後、私はついにそれについて話すようになりましたが、以前にスコープを分析しましょう。
<script> var nameg = "global" var g = function f(){console.log(name); function demo(){console.log( "demo =" + name);} var name = ""; function demo(){var name = ""; console.log( "demo =" + name);} function demo( nameg);} demo(); demo(); demo();}; g(); </script>アクションチェーンに従って分析します。
demo0、demo0() - > not not not exped-> f()、returnを呼び出します
demo1、demo1() - > name、find、returnを呼び出します
demo2、demo2() - > nokeg、not not noted-> f()を見つけてnamegを見つけます。
この例を見てください:
<script> function f(){var count =; return {counter:function(){return count ++;}、reset:function(){return count =;}}} var d = f(); var c = f(); console.log( "d first call:"+ d.counter()); "+ C.Counter()); // </script>この例でわかるように、私はカウントとゼロの操作を行いました。
Fの2つのオブジェクトインスタンスが作成され、それぞれ独自のスコープチェーンがあるため、その値は互いに影響を与えません。 Cが2度目に呼ばれる場合、Cオブジェクトが破壊されないため、カウント値が保存されます。この例を理解した後にのみ、次の例は理解しやすくなります。
誰もがこのプロセスについて非常に明確にする必要があります。それでは、閉鎖の問題を見てみましょう。 4つのボタンを設定し、各ボタンをクリックして応答の名前を返します。
<body> <script> function btninit(){for(var i =; i <; i ++){var btn = document.getElementbyid( "btn" + i); btn.addeventlistener( "click"、function(){alert( "btn" + i);} id = "btn"> btn </button> <button id = "btn"> btn </button> <button id = "btn"> btn </button> <button id = "btn"> btn </button> </div> </body>クリックして実行しますが、結果はすべてBTN5です。
私たちはちょうど今分析に座っていました。まず、匿名関数を呼び出す必要があります - >私は見つかりません - > btninit()を見つけて、forループでiを見つけます。現れる。関数呼び出しのみがリリースされ、i forが常に表示されるため、最後のI値は保持されます。だからそれを解決する方法。
Iの値が関数に常に表示されるとは限らないという問題を解決するには、関数のネストを使用してIのI値を渡す必要があります。
function btninit(){for(var i =; i <; i ++){(function(data_i){var btn = document.getElementbyid( "btn" + data_i); btn.addeventlistener( "click"、function(){alert( "btn" + data_i);};}(i);};}変更されたコードを見ると、最初に最初のコードを実行してオブジェクトを作成します。最初に匿名関数 - > data_iを実行しますが、> function-> function(data_i)を実行し、再度実行してオブジェクトを作成します。閉鎖規則は、それらがお互いに影響を与えないと言っています。したがって、正しい結果を取得できます。
上記は、編集者が紹介するJavaScript必見の必見(9)関数です。閉鎖の問題に関する関連する知識について言えば、それがあなたに役立つことを願っています。ご質問がある場合は、メッセージを残してください。編集者は時間内に返信します。 wulin.comのウェブサイトへのご支援ありがとうございます!