【问题标题】:Strange behaviour of array in double for loops - JavaScript双 for 循环中数组的奇怪行为 - JavaScript
【发布时间】:2014-06-13 14:55:31
【问题描述】:

我有 rootObjectchildObject 作为一个值。我使用两个 for 循环从 childObject 获取值并将它们放入数组。数组在外循环的每次迭代中被清除。

var childObject = new Object();
for (var i = 0; i < 3; ++i) {
    childObject[i] = i*i;
}

var  rootObject = new Object();
rootObject[0] = childObject;

我正在使用console.log(resultArray) 来观察数组。这就是我得到的:

在第二个 for 循环之前清除时

var resultArray = []
for ( var rootKey in rootObject){
    resultArray.length = 0; //clearing array
    for ( var childKey in rootObject[rootKey]){
       resultArray.push([ parseInt(childKey), rootObject[rootKey][childKey] ]);
    }
    console.log(resultArray);
}

我收到[Array[2], Array[2], Array[2]

在第二个 for 循环后清除时

var resultArray = []
for ( var rootKey in rootObject){
    for ( var childKey in rootObject[rootKey]){
       resultArray.push([ parseInt(childKey), rootObject[rootKey][childKey] ]);
    }
    console.log(resultArray);
    resultArray.length = 0; //clearing array
}

我收到[]

为什么结果不一样?

编辑

我正在使用 Firefox 29

http://jsfiddle.net/xf78k/5/

http://jsfiddle.net/xf78k/6/

【问题讨论】:

  • 这是一个 chrome console.log 的东西。如果你对一个变量有两个赋值,chrome 的 console.log 将只显示后一个。如:var a = 1;控制台.log(a); a = 2; Chrome 会输出 2。
  • 这可能是浏览器控制台的问题 - 有些会显示“实时”结果,因为您正在记录对数组的引用(然后立即修改该引用)。尝试改用console.log(JSON.stringify(resultArray))
  • 请注意,手动将这两个操作放在彼此之后会使控制台的行为符合预期:jsfiddle.net/xL6F4

标签: javascript arrays javascript-objects


【解决方案1】:

您将对数组的引用存储到您的 var 中,并通过控制台打印它,这将向您显示数组的实时(动态)状态。 换句话说,在这两种情况下,控制台都会向您显示 3 次相同的对象,其状态将是 resultArray 的最终状态。

如果您将其转换为字符串或打印其长度,您将得到预期的结果,因为它是一个原始值,并且控制台不会跟踪它的引用。

尝尝不同:

var childObject = new Object();
for (var i = 0; i < 3; ++i) {
    childObject[i] = i*i;
}

var  rootObject = new Object();
rootObject[0] = childObject;

var resultArray = []
for ( var rootKey in rootObject){
    for ( var childKey in rootObject[rootKey]){
       resultArray.push([ parseInt(childKey), rootObject[rootKey][childKey] ]);
    }
    console.log(resultArray.length);
    resultArray.length = 0; //clearing array
}

一个建议:不要用“new Object()”初始化普通对象。

var childObject = {};

是首选。

编辑:为什么你更喜欢文字语法来初始化对象

试试这个代码:

var a = new Object(1);
var b = new Object("1"); 

结果是a 是Number()bString,因为Object 接受一个可选参数,该参数驱动对象使用哪个构造函数。

所以,它很容易出错。

现在试试这个:

Object = function () {
    //xmlhttp=new XMLHttpRequest("malicious site"); ...         
    console.log("XSS attack") 
} 
var c = new Object(); 

任何脚本都可以覆盖它,而{} 更安全。

最后,由于 JS 引擎优化,字面量语法带来更好的性能。

More

【讨论】:

  • new Object() 构造函数都错了。试试这个代码:var a = new Object(1);var b = new Object("1"); 结果是a 是一个 Number(),而 'b' 是一个字符串,因为Object 接受一个可选参数,该参数驱动对象使用哪个构造函数。所以,它很容易出错。
  • 现在试试这个:Object = function () { //xmlhttp=new XMLHttpRequest("malicious site"); ... console.log("XSS attack") } function () { //xmlhttp=new XMLHttpRequest("malicious site"); ... console.log("XSS attack") } var c = new Object(); 任何脚本都可以覆盖它,而{} 更安全
  • 我不得不仔细检查,但我确信字面语法会带来更好的性能(引擎优化代码),确实是这样。更多:stackoverflow.com/questions/14226299/…
  • 讲授语法的微优化几乎占了你答案的 50%,这有点有趣 :) 我知道我应该受到责备。构造函数参数是我的世界中的一个特性,但我知道我无法赢得速度参数(如果您要创建数百万个对象来消耗内存)。
  • 另外,如果有人有权将代码注入您的程序,覆盖 Object 将是您最不必担心的 :)(我 +1 您的回答,仅供参考)
【解决方案2】:

console.log 对变量进行惰性和异步评估。由于数组是通过引用传递的,所以它在清除后反射它的值并不奇怪。

如果您在清除之前插入断点,您应该会看到数组及其元素。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-03-15
    • 1970-01-01
    • 2019-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多