2012-01-05 66 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