閉包(Closure)的細節:共用與非共用變數

閉包(Closure)的細節,共用與非共用變數:

一般函式在執行完畢時,內部的區域變數會被釋放掉,但如果在執行時產生了閉包。那閉包會保留其所在巢狀函式內的變數。讓他不至於被系統釋放掉。現在有一個問題是,閉包保留下來的變數,會與其他閉包共用嗎?這其實取決於閉包產生的位置與時間點。

如果在函式同一個呼叫期間建立了多個閉包,那這些閉包是共享該作用域變數的。若是不同的呼叫期間建立閉包,那閉包其實是處在不同的作用域,其變數自然就是不共用的。

同一個呼叫期間內的閉包共享變數:

<script type="text/javascript">
function closuretest(){
x=10;
function changex(cx){
x=cx;
}
function showx(){
alert(x);
}
f1= changex;
f2= showx;
}
closuretest();
f2();//顯示10
f1(5)
f2();//顯示5
</script>

不同呼叫期間的閉包各自擁有變數:

<script type="text/javascript">
function closuretest(ox){
var x=ox;
return function(){
alert(x);
}
}
var f1=closuretest(5);
var f2=closuretest(10);
f1();//顯示5
f2();//顯示10
</script>

閉包的共用與非共用變數:

Closure variable

詭異的陷阱:

來自MDN的一個範例:

<p id="help">Helpful notes will appear here</p>
<p>E-mail: <input type="text" id="email" name="email"></p>
<p>Name: <input type="text" id="name" name="name"></p>
<p>Age: <input type="text" id="age" name="age"></p>
 
 
 
 
function showHelp(help) {
  document.getElementById('help').innerHTML = help;
}

function setupHelp() {
  var helpText = [
      {'id': 'email', 'help': 'Your e-mail address'},
      {'id': 'name', 'help': 'Your full name'},
      {'id': 'age', 'help': 'Your age (you must be over 16)'}
    ];

  for (var i = 0; i < helpText.length; i++) {
    var item = helpText[i];
    document.getElementById(item.id).onfocus = function() {
      showHelp(item.help);
    }
  }
}

setupHelp();

這程式可用來捕捉<input>標籤的focus事件,讓<input>標籤取得焦點時能夠在<p id="help">中顯示相關的說明,不過奇怪的是,不論焦點落在哪,說明總是會顯示"Your age (you must be over 16)"。為什麼會這樣?

其實就是閉包共享變數的原因,在函式內迴圈跑完時,變數item被設定為helpText[2],而閉包的函式主體:

function() {
showHelp(item.help)};

其中的item是共享變數,已經被設定成為了helpText[2],因此不論焦點落在哪個<input>標籤,說明總是會顯示"Your age (you must be over 16)"。

解決這問題方法是使用更多的閉包。這裡就不在列出,請參考:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures

其他:

如果你想更了解其他閉包觀念,可以參考看看下面這篇文章:閉包(Closure)的基本概念

我把許多閉包的觀念與用法都收集在這篇文章內。

 
 

  按個讚!~支持本站!~

FB推薦載入中  

你可能會有興趣的文章