ホームページ >ウェブフロントエンド >jsチュートリアル >JavaScriptクロージャ_JavaScriptスキルの詳しい説明
インターネット上でクロージャに関する概念や記事を読んだ後、この問題を自分自身で整理してみたいと思います。
Q: クロージャとは何ですか?
回答: クロージャとは、JavaScript において、外部関数が返された後 (サポート終了) であっても、内部関数がその内部関数が配置されている外部関数で宣言されたパラメーターと変数に常にアクセスできることを意味します。
クロージャーの問題に遭遇したのはこれが初めてです
<!DOCTYPE HTML> <html> <head> <meta charset="utf-8"/> <title>闭包循环问题</title> <style type="text/css"> p {background:#ccc; width: 300px; height: 100px;} </style> </head> <body> <p id="p0">段落0</p> <p id="p1">段落1</p> <p id="p2">段落2</p> <p id="p3">段落3</p> <p id="p4">段落4</p> <script type="text/javascript"> for( var i=0; i<5; i++ ) { document.getElementById("p"+i).onclick=function() { alert(i); //访问了父函数的变量i, 闭包 }; }; </script> </body> </html>
これまでに使用したことがない場合は、段落をクリックすると、この段落に対応する番号 0、1、2、3、4 がポップアップ表示されると考えるかもしれません。しかし実際には、それらはすべて 5 つ現れます。
この問題についてオンラインで議論しているブログは数多くあり、対応する番号をポップアップ表示するためのさまざまな方法が提供されています。
解決策 1: 変数 i を対応する段落の属性に保存します
var pAry = document.getElementsByTagName("p"); for( var i=0; i< 5; i++ ) { pAry[i].no = i; pAry[i].onclick = function() { alert(this.no); } };
解決策 2: クロージャーの層を追加し、関数パラメーターの形式で i を内部関数に渡します
var pAry = document.getElementsByTagName("p"); for( var i=0; i< 5; i++ ) { pAry[i].no = i; pAry[i].onclick = function() { alert(this.no); } };
これによって引き起こされるクロージャの問題について、インターネット上では「変数 i はポインタまたは変数アドレスとして関数に格納される」と言われていますが、これはすべてポインタに関係しています。 。 。 。次に、さらに探索します。
Explore 1、戻り値は
ではなく 10 です
(function test() { var temp =10; for(var i=0; i< 5; i++ ){ document.getElementById("p"+i).onclick=function() { alert(temp); //访问了父函数的变量temp, 闭包 } }; temp=20; })();
2 を探索し、10 を一度返し、その後 20 を返します
(function test() { var temp =10; for( var i=0; i< 5; i++ ) { document.getElementById("p"+i).onclick=function() { alert(temp); //访问了父函数的变量i, 闭包 } if(i===1){ alert(temp); } }; temp=20; })();
1 と 2 の検討から、関数と同じレベルの変数が関数内でアクセスされる場合、その変数はメモリ内に常駐すると結論付けることができます。この変数にアクセスすると、基本的に変数
のアドレスにアクセスします。その後、「JS クロージャー内のこのオブジェクト」に関する別の記事を読みました。この問題について引き続き議論しましょう。
// js闭包this对象1 var name = 'The Window'; var object = { name : 'My Object', getNameFunc1 : function(){ // return this.name; console.log(this);//object return function(){//闭包,访问的便是全局变量的了,this指windows console.log(this);//windows return this.name; //The Window } }, getNameFunc2 : function(){ return this.name;//访问的是object }, aa:function(){ alert(22); } }; alert(object.getNameFunc1()());//弹出“The Window”
質問: では、なぜ匿名関数はそのスコープを含む this オブジェクトを取得しないのでしょうか?
回答: すべての関数は、呼び出されるときに、this と引数という 2 つの特別な変数を自動的に取得します。 これら 2 つの変数を検索する場合、内部関数はアクティブなオブジェクトに検索を指示するため、外部関数でこれら 2 つの変数に直接アクセスすることはできません。
ただし、これは次のコードで実行できます (外部関数の変数に直接アクセスします):
// js闭包this对象2 var name = 'The Window'; var object = { name : 'My Object', getNameFunc : function(){ var that = this; console.log(this);//输出的是object return function(){ console.log(this);//输出的仍然是Windows return that.name; }; } }; alert(object.getNameFunc()());//弹出“My Object”
違いは、関数が戻った後でも this オブジェクトが that 変数に割り当てられるため、オブジェクトが返されることです。
クロージャについてたくさん書いてきたので、クロージャの有用性について触れておきます。そうしないと、クロージャをいじり続けるのは悪い人になります。
この典型的なクロージャの例を見てください:
function A(){ var a=1; function B(){ return a; }; return B; }; var C=A();//C取得A的子作用域B的访问接口 console.log(C());//1 C能访问到B的父级作用域中的变量a
他のスコープが子スコープのアクセス インターフェイスを取得できる限り、他のスコープは子スコープの親スコープの変数にアクセスする方法を持ちます。この場合、将来特定の関数の値にアクセスする必要がある場合に非常に役立ちます。
上記のコードの多くは実際にオンラインで見つけたもので、私が理解した内容と読んだプロセスを要約したものです。