javascript中奇怪的数组行为

IT技术 javascript arrays
2021-03-15 03:10:22

我知道与其他语言相比,javascript 中的数组有点特殊,但我并没有真正理解这种行为,或者这里发生了什么。

我想知道为什么会发生这种情况以及为什么我没有得到一个空数组:

function setupWindowProgBar(settings, window, palette, arr){
    console.log('start');
    console.log(arr);
    if(typeof arr == 'undefined'){
        var arr = [];
    }
    console.log(arr);
    console.log('stop');
    var arrLen = arr.length;
    arr[arr.length] = createProgBar('master', 'bg', window, 0, settings.fillColor, settings.strokeColor, settings.textColor, palette, 'percent', settings.reqType, settings.sourceType, settings.sourceTarget, settings.sourceId);
    return arr;
}

在控制台中产生这个:

start
undefined
[]
    0:
    barType:"master"
    bgcolor:"#12181f"
    curVal:160
        data:
        all_goals:160
        cost_hours:160
        cost_hours_spent:0
        cost_money:31610
        cost_money_owned:0
        parentObj:"progBar"
        progress_goals:5
        recurring:"no"
        wanted_timer:"2018-03-26 05:19:33"
        __proto__:Object
    fill:"#255f6f"
    height:59
    maxVal:5
    maxWidth:168
    sectionHeight:59
    stroke:"#7b9dac"
    text:"3%"
    textColor:"#dee5ed"
    textOpt:"percent"
    width:200
    x:33
    y:81
__proto__:Object
height:100
text:"omanko"
length:1
__proto__:Array(0)
stop

我确实认出了这里的对象,但据我所知,它不是来自全局污染 - console.log(window.arr) 说没有名为 arr 的全局变量,我还没有修改原型。

当然,这不应该影响新的数组声明吗?

3个回答

这种行为不仅限于数组,任何对象在控制台中的行为方式都是如此

您所看到的是所有浏览器中的控制台对您“撒谎”的结果

如果您console.log(anyobject)在控制台中检查该对象,您将看到的是当前的anyobject- 而不是console.log执行时的内容

var obj = {}
console.log(obj);
obj.test = 1;

var arr = [1];
console.log(arr);
arr.push(2);

现在,如果你打开开发者控制台,点击对象,你会看到 test:1

查看控制台中的数组 - 它输出为[1]... 然而,单击您看到两个元素的数组

注意:chrome 开发者控制台至少暗示了它在骗你的事实——有一个蓝色i,如果你悬停(或点击,不记得,不要经常使用 Chrome)你会看到一条消息说显示的值是evaluated just now

是的,这正是我发布的代码,除了您使用了一个名为的属性,a而我使用了test...test不是什么特别的东西
2021-04-20 03:10:22
但是我在 Chrome 中看到了另一个奇怪的行为。 var obj; console.log(obj); obj = {test: 1};此代码打印undefined而不是 obj 的当前值
2021-04-23 03:10:22
这就是我猜的答案。
2021-04-24 03:10:22
是的,因为它是undefined- 并且分配了一个对象,因此console不会“稍后”显示这个新对象 - 所以,实际上根本没有什么奇怪的
2021-05-08 03:10:22
啊! 好的。知道了。如果我写var obj = {}; console.log(obj); obj.a = 2,我猜它可能在做的是维护对obj对象的引用并输出该对象的当前值。
2021-05-09 03:10:22

问题是当你调用console.log(arr)时,它会在控制台中放置一个对数组的引用,当你“打开”它(单击箭头)时,它会被取消引用,因此它将显示稍后在代码中所做的更改。使用console.table(arr)console.log(JSON.stringify(arr))代替。

这是MDN 的一个片段

请注意,如果您在最新版本的 Chrome 和 Firefox 中记录对象,则您在控制台上记录的是对对象的引用,这不一定是您调用 console.log 时对象的“值”。 log(),但它是您单击打开时对象的值。

arr已经是您的函数参数,并且它不是未定义的。var被提升,所以对解释器来说,你当前的代码实际上看起来像:

function setupWindowProgBar(settings, window, palette, arr){
  var arr; // **does not reassign the parameter**
  console.log('start');
  console.log(arr);
  if(typeof arr == 'undefined'){
    arr = [];
  }
  console.log(arr);
  console.log('stop');
}

你永远不应该声明一个变量,其名称已经限定在你正在使用它的块/函数中。

如果arr实际上没有在参数中定义,那么它将被分配给行上的一个数组arr = [];,但至少在 Chrome 上,该空数组不一定会在你console.log时打印出来

console.log(arr);不一定立即显示arr- 取决于您的浏览器,它可能只会在您打开控制台填充到您的控制台中,在此行运行后:

arr[arr.length] = createProgBar('master', 'bg', window, ...
不过,只是一个快速的后续问题,第一个 console.log(arr); 在 if 语句返回“未定义”之前?
2021-04-15 03:10:22
@Ooops,误读 - 是的,你是对的 - 有时是。我知道逻辑很混乱,我现在正在重构代码,而且我在修复它时没有问题 - 我对它为什么会发生更感兴趣,所以我知道将来如何使用/避免它。
2021-04-16 03:10:22
arr is a parameter to your function already, and it is not undefined如果是呢?即你打电话使用setupWindowProgBar(settings, window, palette)
2021-04-20 03:10:22
@DanielBengtsson 正是我想知道的。第一个console.log(arr)打印undefined
2021-05-05 03:10:22
我添加了这个:console.log('test'); 在 if 语句中 - 它确实运行了。
2021-05-06 03:10:22