2012-01-05 106 views
10

我對JavaScript或Chrome控制檯的行爲深感困惑。有人能幫助我理解嗎?JavaScript控制檯在分配變量之前打印分配的變量值?

基本上我有以下的JavaScript代碼,而不是嵌套任何函數或其他範圍內:

var initial_array = []; 

function initialiseArray() { 
    initial_array = [2, 9, 8, 6, 0, 2, 1]; 
} 

function copyToNewArray() { 
    var copied_array = []; 

    console.log("COPIED 1", copied_array); 

    for (var i = 0; i < initial_array.length; i++) { 
     var copy = initial_array[i]; 
     copied_array.push(copy); 
    } 

    console.log("COPIED 2", copied_array); 
} 

initialiseArray(); 
copyToNewArray(); 

我希望COPIED 1打印[] - 作爲變量尚未分配的 - 而是它打印[2, 9, 8, 6, 0, 2, 1] - 即分配後的值。

爲什麼?順便提一下,如果用initial_array = copied_array替換第8-11行,那麼RESULTS 1確實打印爲[]。這與使用.push有關嗎?

+0

有趣。這似乎是解決同一個問題嗎? [鏈接](http://zef.me/2843/javascript-the-scope-pitfall) – j08691 2012-01-05 18:15:30

+4

類似的問題:http://stackoverflow.com/questions/4057440/is-chromes-javascript-console-lazy-about-評估數組 – diEcho 2012-01-05 18:16:32

回答

8

嘗試在Chrome瀏覽器的腳本調試調試你的問題之前,陣列複製。把一個斷點放在線上:

for (var i = 0; i < initial_array.length; i++) { 

你會看到你所期望的行爲。

您遇到的問題是您做出錯誤的假設,即Chrome調試器會立即「打印」該值,而事實上它是異步執行console.log。由於數組是通過後端的引用傳遞的,因此當它實際上打印值時,它現在就是您所看到的值。

+0

好的Chrome腳本調試器建議,我在嘗試使用Webstorm調試器,但沒有取得太大的成功。 – Osy 2013-03-13 18:59:06

+0

很好的答案... LAME記錄器:( – Nicole 2013-10-01 00:36:57

0
var initial_array = []; 
function initialiseArray() { 
    initial_array = [2, 9, 8, 6, 0, 2, 1]; 
} 
function copyToNewArray() { 
    var copied_array = []; 
    console.log("COPIED 1", copied_array); 
    alert(copied_array.length); 
    for (var i = 0; i < initial_array.length; i++) { 
     var copy = initial_array[i]; 
     copied_array.push(copy); 
    } 
    console.log("COPIED 2", copied_array); 
} 
initialiseArray(); 
copyToNewArray(); 

添加行alert(copied_array.length);將顯示正確的結果。

會發生什麼情況是日誌不與JavaScript執行同步。當日志打印時,值已經改變。

1

這是數組顯示在Chrome控制檯中的方式,這是通過引用。如果你想準確的結果,轉換爲字符串:

var initial_array = []; 

function initialiseArray() { 
    initial_array = [2, 9, 8, 6, 0, 2, 1]; 
} 

function copyToNewArray() { 
    var copied_array = []; 

    console.log("COPIED 1", copied_array.toString()); 

    for (var i = 0; i < initial_array.length; i++) { 
     var copy = initial_array[i]; 
     copied_array.push(copy); 
    } 

    console.log("COPIED 2", copied_array.toString()); 
} 

initialiseArray(); 
copyToNewArray(); 

你可以很容易地測試了這一點:

var x = []; 
console.log(x), x.push(5), x; // outputs [5] and [5] 
+0

儘管如此,你會認爲它會在適當的位置渲染/字符串化/解析數組引用,否則'console.log'ging數組幾乎不會工作。 Firefox也會屈服於此,還是更加智能? – 2012-01-05 18:17:53

+0

@LightnessRacesinOrbit:不是更聰明,而是將所有東西都轉換爲字符串,所以是的,它應該可以工作。 (另一方面,FireBug ......我不確定。) – Ryan 2012-01-05 18:19:27

+0

我認爲這是「更智能」,因爲在這種情況下保持參考約束如此之晚顯然違反了POLS。 (FWIW,我的意思是說Firebug) – 2012-01-05 18:23:42

1

控制檯實際上是異步的。因爲你正在記錄一個對象的引用,所以當對象被記錄時它已經改變了。

您可以在記錄之前克隆該數組,以確保它在記錄之前不會被更改。

3

由於數組是通過引用傳遞的,所以每次對它進行的更改都會改變控制檯中輸出的內容。部分是Chrome的控制檯,部分是JavaScript的行爲。

如果您想在撥打console.log時打印結果,可以使用JSON.stringify作爲字符串輸出。

console.log("COPIED 1", JSON.stringify(copied_array)); 

重要編輯

看來我主要是錯誤的。由於diEcho在問題的評論中指出,similar question有一個better answer。這似乎只是Chrome的行爲。

+0

我也在firefox的Web開發者控制檯(股票瀏覽器,而不是螢火蟲)找到這種行爲。所以也許這不僅僅是Chrome的行爲。 – 2013-01-24 19:30:12

0

這是因爲copied_array是一個引用,並且console.log是異步執行的,所以在第一個日誌打印之前修改了該數組的內容。

你可以打印

console.log([].concat(copied_array)); 
0

如果你想保持控制檯的功能,如在一個陣列擴展的對象,我建議使用.slice,登錄時,其使不改變數組的副本:

console.log("COPIED 1", copied_array.slice()); 
+0

不錯,但JSON.stringify(copied_array)方法似乎更好,我認爲。 – 2013-01-24 19:32:48