Chrome的JavaScript控制台是否懒于评估数组?

Eri*_*sen 116 javascript arrays console logging google-chrome

我将从代码开始:

var s = ["hi"];
console.log(s);
s[0] = "bye";
console.log(s);
Run Code Online (Sandbox Code Playgroud)

简单吧?对此,Firebug说:

["hi"]
["bye"]
Run Code Online (Sandbox Code Playgroud)

很棒,但Chrome的JavaScript控制台(7.0.517.41 beta)说:

["bye"]
["bye"]
Run Code Online (Sandbox Code Playgroud)

我做错了什么,或者Chrome的JavaScript控制台在评估我的阵列方面特别懒惰?

在此输入图像描述

Eri*_*sen 59

谢谢你的评论,tec.我能够找到一个现有的未经证实的Webkit错误来解释这个问题:https://bugs.webkit.org/show_bug.cgi? id = 35801(编辑:现在修复了!)

关于它有多少虫子以及它是否可以修复似乎存在争议.这对我来说似乎是不好的行为.这对我来说尤其令人不安,因为至少在Chrome中,当代码驻留在立即执行的脚本中(在页面加载之前),即使控制台处于打开状态,每当刷新页面时,也会发生这种情况.当控制台尚未激活时调用console.log仅导致对正在排队的对象的引用,而不是控制台将包含的输出.因此,在控制台准备好之前,不会评估数组(或任何对象).这确实是一个懒惰的评估案例.

但是,在代码中有一种简单的方法可以避免这种情况:

var s = ["hi"];
console.log(s.toString());
s[0] = "bye";
console.log(s.toString());
Run Code Online (Sandbox Code Playgroud)

通过调用toString,您可以在内存中创建一个表示形式,该表示形式不会被以下语句更改,控制台在准备就绪时将读取这些语句.控制台输出与直接传递对象略有不同,但似乎可以接受:

hi
bye
Run Code Online (Sandbox Code Playgroud)

  • JSON.stringify() (24认同)
  • 实际上,对于关联数组或其他对象,这可能是一个真正的问题,因为 toString 不会产生任何有价值的东西。一般来说,是否有针对对象的简单解决方法? (2认同)
  • 这样做: console.log(JSON.parse(JSON.stringify(s)); (2认同)

nop*_*ole 18

从Eric的解释来看,它是由于console.log()排队,并且它打印了一个稍后的数组(或对象)值.

可以有5种解决方案:

1. arr.toString()   // not well for [1,[2,3]] as it shows 1,2,3
2. arr.join()       // same as above
3. arr.slice(0)     // a new array is created, but if arr is [1, 2, arr2, 3] 
                    //   and arr2 changes, then later value might be shown
4. arr.concat()     // a new array is created, but same issue as slice(0)
5. JSON.stringify(arr)  // works well as it takes a snapshot of the whole array 
                        //   or object, and the format shows the exact structure
Run Code Online (Sandbox Code Playgroud)


yin*_*ted 7

您可以使用以下命令克隆数组Array#slice:

console.log(s); // ["bye"], i.e. incorrect
console.log(s.slice()); // ["hi"], i.e. correct
Run Code Online (Sandbox Code Playgroud)

您可以使用而console.log不是具有此问题的函数如下:

console.logShallowCopy = function () {
    function slicedIfArray(arg) {
        return Array.isArray(arg) ? arg.slice() : arg;
    }

    var argsSnapshot = Array.prototype.map.call(arguments, slicedIfArray);
    return console.log.apply(console, argsSnapshot);
};
Run Code Online (Sandbox Code Playgroud)

遗憾的是,对于对象的情况,最好的方法似乎是首先使用非WebKit浏览器进行调试,或编写复杂的函数进行克隆.如果您只使用简单对象,键的顺序无关紧要且没有函数,您可以随时执行:

console.logSanitizedCopy = function () {
    var args = Array.prototype.slice.call(arguments);
    var sanitizedArgs = JSON.parse(JSON.stringify(args));

    return console.log.apply(console, sanitizedArgs);
};
Run Code Online (Sandbox Code Playgroud)

所有这些方法显然都非常慢,所以甚至比普通console.log的方法还要多,你必须在完成调试后将其剥离.


jus*_*unt 5

这已经在 Webkit 中进行了修补,但是当使用 React 框架时,在某些情况下我会发生这种情况,如果您遇到此类问题,请按照其他人的建议使用:

console.log(JSON.stringify(the_array));
Run Code Online (Sandbox Code Playgroud)

  • 可以确认。当尝试注销 ReactSyntheticEvents 时,这实际上是最糟糕的。即使“JSON.parse(JSON.stringify(event))”也没有获得正确的深度/准确性。调试器语句是我发现的唯一能够获得正确见解的真正解决方案。 (3认同)