2014年4月29日 星期二

Javascript 區塊範疇的陷阱

這篇文章要介紹的主要幾個觀念是 :

  • 函式能夠參考在它們外層範疇中定義的變數
  • Closures 捕捉它們外層變數的方式是透過參考 ( by reference ) 而非值 ( by value )

之前介紹過 javascript 跟別的語言不同的是使用 function 建立作用域


上面的範例可以清楚知道使用 var 關鍵字建立變數,
因為作用域的影響外層是無法直接存取至內層宣告的變數.


內層函式可以直接存取外層變數 !


使用 Closures

Closures 會內部儲存對它們外層變數的參考, 並且能夠讀取或更新它們所儲存的變數.


Motorcycle() 是回傳 demo 函式
當 x = Motorcycle('GTR');
x = function demo() { return '品牌 : ' + name; }
所以當執行 console.log(x());
就會印出 品牌 : GTR

區塊範疇的陷阱

如果上面的範例都清楚明瞭了, 就來看今天的重點.


能夠清楚看到宣告了 x 變數把陣列傳進去,
利用陣列的方式指向 function(){return intArray[i];},
在回傳一整個陣列, 結果如下.


這是怎麼一回事呢 ?
有人可能會思考到因為是外面傳進來參數的問題.
那我將程式修改成直接在內部宣告 intArray.


嗯 ..... 要理解這個陷阱就必須談到程式執行時期 ( runtime ) 進入到一個 scope 時,
會為 scope 內的每個變數繫結 ( variable binding ) 都在記憶體配置一個位置 ( slot ).
而內層函式是透過參考去存取外層變數,
這個程式的臭蟲來源是, 在巢狀函式被建立之時, 儲存當時的 i 的值,
但實際上它所儲存的卻是對 i 的一個參考 ( reference ).
既然 i 的值會被建立之後改變, 那些內層函式所見的即是 i 的最終值.
這就是關鍵所在 ... 看以下範例會更了解.



沒有留言: