不囉唆直接上程式碼
var objText = {
type : 'text',
text : ''
}
var myArray = [] ;
for(var i=0; i < 5; i++)
{
objText.text = i ;
console.log(objText) ;
myArray.push(objText);
}
console.log(myArray);
//首先我預想的結果應該是這樣
{ type: 'text', text: 0 }
{ type: 'text', text: 1 }
{ type: 'text', text: 2 }
{ type: 'text', text: 3 }
{ type: 'text', text: 4 }
[ { type: 'text', text: 0 },
{ type: 'text', text: 1 },
{ type: 'text', text: 2 },
{ type: 'text', text: 3 },
{ type: 'text', text: 4 } ]
//實際上是
{ type: 'text', text: 0 }
{ type: 'text', text: 1 }
{ type: 'text', text: 2 }
{ type: 'text', text: 3 }
{ type: 'text', text: 4 }
[ { type: 'text', text: 4 },
{ type: 'text', text: 4 },
{ type: 'text', text: 4 },
{ type: 'text', text: 4 },
{ type: 'text', text: 4 } ]
目前解決方法是在迴圈裡面進行宣告
for(var i=0; i < 5; i++)
{
let objText = {
type : 'text',
text : ''
}
objText.text = i ;
console.log(objText) ;
myArray.push(objText);
}
但我實在不懂為何會這樣,想了解一下原理
是因為閉包問題嗎??
但我印出來的objText也有確實的每一個迴圈改變
還是因為他是同一個物件,所以我改變了之後,陣列裡所有物件也跟著改變
這樣的話我push進去的是給同一個物件,不是複製進去的意思嗎??
寫這個程式的目的是做Line的bot裡面的訊息格式都是使用json
因此蠻常需要做一個template不斷動態產生訊息,但不斷踩到這個雷
所以上來發問一下~還請各位大佬解答
要說得精確一點:
JS跟python的變數很特別,他們兩個對於變數都有分:
然後這兩個語言遇到這兩類變數,在傳遞時會有不同的行為:
mutable:會用 call by reference
immutable:會用 call by value
像你這樣,在mutable(array)中推送,實際上array中記的值是推送reference,你4次都推同樣的物件,也就是你array裡面其實存的是
[objText的ref, objText的ref, objText的ref, objText的ref]
所以會是objText的最後值。
解法的話,ccutmis提供的是一個解,另外也可以用new,無分好壞,看你物件有沒有需要被重用:
function objText(text) {
this.type = 'text'
this.text = text
}
for(var i=0; i < 5; i++)
{
let _obj = new objText(i)
myArray.push(_obj);
}
然後這個在python被習慣稱做 call by assignment,JS則被稱為 call by sharing。