【问题标题】:weird array behaviour in javascript [duplicate]javascript中奇怪的数组行为[重复]
【发布时间】:2018-09-25 02:07:33
【问题描述】:

我知道 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 的全局变量,我没有修改原型.

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

【问题讨论】:

  • 这不应该发生,因为arr 在您记录它时应该是一个空数组,而不是一个奇怪的对象。我确定您已经省略了代码的关键部分。
  • 我同意,这不应该发生 - 为清楚起见将添加整个功能
  • 这对我来说毫无意义
  • 不,@Tigger 它是一个数组,我想知道为什么 arr[0] 填充了一个嵌套对象。如果不是来自全球范围,这种污染来自哪里?
  • 控制台位于 - 在 chrome 控制台中(如果您使用的是 chrome),它甚至会告诉您显示的对象是“刚刚”评估的 - 因此,在控制台中您看到 arr[0]createProgBar 的结果 - 尽管 console.log 出现得更早

标签: javascript arrays


【解决方案1】:

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 - 取决于您的浏览器,它可能仅在您打开控制台后在您的控制台中填充,在此行运行后: p>

arr[arr.length] = createProgBar('master', 'bg', window, ...

【讨论】:

  • 只是一个快速的后续问题,第一个 console.log(arr); 怎么来的?在 if 语句返回“未定义”之前?
  • @DanielBengtsson 正是我想知道的。第一个console.log(arr) 打印undefined
  • arr is a parameter to your function already, and it is not undefined 如果是呢?即您使用setupWindowProgBar(settings, window, palette) 拨打电话
  • 我添加了这个:console.log('test');在 if 语句中 - 它确实运行。
  • @Ooops,误读 - 是的,你是对的 - 有时是这样。我知道逻辑搞砸了,我现在正在重构代码,修复它没有问题 - 我对它为什么会发生更感兴趣,所以我知道将来如何使用/避免它。
【解决方案2】:

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

这是来自MDN的sn-p

请注意,如果您在最新版本的 Chrome 和 Firefox 您在控制台上登录的内容是参考 到对象,这不一定是对象的“价值” 你调用 console.log() 的那一刻,但它是 对象在您单击它的那一刻打开。

【讨论】:

    【解决方案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

    【讨论】:

    • 我猜这就是答案。
    • 但我在 Chrome 中看到了另一个奇怪的行为。 var obj; console.log(obj); obj = {test: 1}; 此代码打印 undefined 而不是 obj 的当前值
    • 是的,因为它是 undefined - 并且分配了一个 new 对象,因此 console 不会“稍后”显示这个新对象 - 所以,有实际上一点也不奇怪
    • 啊!好的。知道了。如果我写var obj = {}; console.log(obj); obj.a = 2,我猜它可能在做的是维护对 obj 对象的引用并输出该对象的当前值。
    • 是的,这正是我发布的代码,只是你使用了一个名为 a 的属性,而我使用了 test ... test 没什么特别的
    猜你喜欢
    • 2015-10-24
    • 2021-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-05
    相关资源
    最近更新 更多