Javascript 是Chrome';如何评估数组?

Javascript 是Chrome';如何评估数组?,javascript,arrays,logging,google-chrome,console,Javascript,Arrays,Logging,Google Chrome,Console,我将从代码开始: var s = ["hi"]; console.log(s); s[0] = "bye"; console.log(s); 很简单,对吧?对此,Firebug表示: ["hi"] ["bye"] 很好,但是Chrome的JavaScript控制台(7.0.517.41测试版)说: 我是否做错了什么,或者Chrome的JavaScript控制台在评估我的数组时异常懒惰 谢谢你的评论,tec。我能够找到一个现有的未经确认的Webkit bug来解释这个问题:(编辑:现已修复!)

我将从代码开始:

var s = ["hi"];
console.log(s);
s[0] = "bye";
console.log(s);
很简单,对吧?对此,Firebug表示:

["hi"]
["bye"]
很好,但是Chrome的JavaScript控制台(7.0.517.41测试版)说:

我是否做错了什么,或者Chrome的JavaScript控制台在评估我的数组时异常懒惰


谢谢你的评论,tec。我能够找到一个现有的未经确认的Webkit bug来解释这个问题:(编辑:现已修复!)

关于它到底有多大程度的缺陷以及是否可以修复,似乎存在一些争论。在我看来,这确实是一种不好的行为。这对我来说尤其麻烦,因为至少在Chrome中,当代码驻留在脚本中并立即执行时(在加载页面之前),甚至当控制台打开时,每当页面刷新时,都会发生这种情况。当控制台尚未激活时调用console.log只会导致对正在排队的对象的引用,而不是控制台将包含的输出。因此,在控制台准备就绪之前,不会对数组(或任何对象)求值。这确实是一个懒惰评估的例子

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

var s = ["hi"];
console.log(s.toString());
s[0] = "bye";
console.log(s.toString());
通过调用toString,您可以在内存中创建一个表示,该表示不会被以下语句更改,控制台将在准备就绪时读取这些语句。控制台输出与直接传递对象略有不同,但似乎可以接受:

hi
bye

谢谢你的评论,tec。我能够找到一个现有的未经确认的Webkit bug来解释这个问题:(编辑:现已修复!)

关于它到底有多大程度的缺陷以及是否可以修复,似乎存在一些争论。在我看来,这确实是一种不好的行为。这对我来说尤其麻烦,因为至少在Chrome中,当代码驻留在脚本中并立即执行时(在加载页面之前),甚至当控制台打开时,每当页面刷新时,都会发生这种情况。当控制台尚未激活时调用console.log只会导致对正在排队的对象的引用,而不是控制台将包含的输出。因此,在控制台准备就绪之前,不会对数组(或任何对象)求值。这确实是一个懒惰评估的例子

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

var s = ["hi"];
console.log(s.toString());
s[0] = "bye";
console.log(s.toString());
通过调用toString,您可以在内存中创建一个表示,该表示不会被以下语句更改,控制台将在准备就绪时读取这些语句。控制台输出与直接传递对象略有不同,但似乎可以接受:

hi
bye

看起来Chrome正在“预编译”阶段用指向实际数组的指针替换任何“s”实例

一种方法是克隆阵列,改为记录新副本:

var s = ["hi"];
console.log(CloneArray(s));
s[0] = "bye";
console.log(CloneArray(s));

function CloneArray(array)
{
    var clone = new Array();
    for (var i = 0; i < array.length; i++)
        clone[clone.length] = array[i];
    return clone;
}
var s=[“hi”];
控制台日志(CloneArray);
s[0]=“再见”;
控制台日志(CloneArray);
函数CloneArray(数组)
{
var clone=新数组();
对于(var i=0;i
看起来Chrome正在“预编译”阶段用指向实际数组的指针替换任何“s”实例

一种方法是克隆阵列,改为记录新副本:

var s = ["hi"];
console.log(CloneArray(s));
s[0] = "bye";
console.log(CloneArray(s));

function CloneArray(array)
{
    var clone = new Array();
    for (var i = 0; i < array.length; i++)
        clone[clone.length] = array[i];
    return clone;
}
var s=[“hi”];
控制台日志(CloneArray);
s[0]=“再见”;
控制台日志(CloneArray);
函数CloneArray(数组)
{
var clone=新数组();
对于(var i=0;i
您可以使用
数组#切片克隆数组

console.log(s); // ["bye"], i.e. incorrect
console.log(s.slice()); // ["hi"], i.e. correct
您可以使用以下函数来代替没有此问题的
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);
};
不幸的是,对于对象,最好的方法似乎是首先使用非WebKit浏览器进行调试,或者编写复杂的克隆函数。如果您仅处理简单对象,其中键的顺序无关紧要,并且没有函数,则始终可以执行以下操作:

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

    return console.log.apply(console, sanitizedArgs);
};

所有这些方法显然都非常慢,因此比普通的
控制台.log更慢,您必须在调试完成后将其剥离。

您可以使用
array#slice
克隆阵列:

console.log(s); // ["bye"], i.e. incorrect
console.log(s.slice()); // ["hi"], i.e. correct
您可以使用以下函数来代替没有此问题的
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);
};
不幸的是,对于对象,最好的方法似乎是首先使用非WebKit浏览器进行调试,或者编写复杂的克隆函数。如果您仅处理简单对象,其中键的顺序无关紧要,并且没有函数,则始终可以执行以下操作:

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

    return console.log.apply(console, sanitizedArgs);
};

所有这些方法显然都非常慢,因此比普通的
console.log更慢,调试完成后必须将它们去掉。

根据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

根据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

这已经得到了回答,但我还是放弃我的答案。我实现了一个简单的控制台包装器,它不会受到这个问题的影响。需要jQuery

它只实现了
log
warn
error
方法,您必须添加更多的方法才能与常规
控制台互换

var固定控制台;
(函数($){
var\u freezeOne=函数(arg){
if(typeof arg==='object'){
返回$.extend(true,{},arg);
}否则{
返回arg;
}
};
var\u freezeAll=函数(args){
var冻结=[];

对于(var i=0;i这已经得到了回答,但无论如何我都会放弃我的答案。我实现了一个简单的控制台包装器,它不会遇到这个问题。需要jQuery