2018年3月19日 星期一

閉包用法的陷阱

閉包用法的陷阱

前言

  最近有個關於閉包的bug,找了相當的久才找到,這裡做個紀錄。


內容

  首先先看以下程式碼
var obj={
  name:"MyObj",
  data:[1,2,3,4,5]
};
function printObjectData(data){
  return function(){
    console.log(data);
  };
}
//
var printFun = printObjectData(obj.data);
printFun();
obj.data = [];
console.log("Clear data!");
printFun();

最後console的結果如下
[1, 2, 3, 4, 5]
Clear data!
[1, 2, 3, 4, 5]

可以看到最後一次的printFun()竟然沒有清除資料!本以為可能是javascript的array是pass by value造成的,但實際試驗了一下javascript會發現array是pass by reference,那這到底是什麼問題呢?實際上是這樣的,printFun在從 printObjectData()取得function時,確實是得到obj.data,但問題是接下來的clear,也就是"obj.data = []",這個array的清除有問題,這裡確實清除了obj.data,但閉包裡的data還是舊的array,所以會發現第二次的printFun()依舊是原本的array,問題是說"obj.data = []"的意思其實不是clear一個array,而是將obj.data指向一個空array。如果要修正問題改成以下

var obj={
  name:"MyObj",
  data:[1,2,3,4,5]
};
function printObjectData(obj){
  return function(){
    console.log(obj.data);
  };
}
//
var printFun = printObjectData(obj);
printFun();
obj.data=[];
console.log("Clear data!");
printFun();

沒有留言:

張貼留言