閉包用法的陷阱
前言
最近有個關於閉包的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();