对于每个循环行为的vs - JavaScript

时间:2015-10-29 09:05:15

标签: javascript arrays for-loop foreach

我正在搜索谷歌找到一个能够检测数组中元素重现的函数。我找到了以下解决方案:

var arr = ["dog","dog","cat","lion","dog","cat" ]
arr.forEach(function(x) { 
    counts[x]= (counts[x] || 0)+1
});
console.log(counts);

上述输出是:

 Object {dog: 3, cat: 2, lion: 1}

使用简单的 FOR循环

for(var x=0; x<arr.length; x++){
    counts[x]= (counts[x] || 0)+1
}
console.log(counts);

上述输出是:

Object {0: 1, 1: 1, 2: 1, 3: 1, 4: 1, 5: 1}

的问题:

首先,我不会完全理解这里发生的事情:

counts[x]= (counts[x] || 0)+1

其次,如何在ForEach循环中检测到元素的重现?这已经内置了吗?

在下面的代码中,属性名称dog,cat和lion只出现一次。

Object {dog: 3, cat: 2, lion: 1}

此处的属性名称将单独显示在数组中的每个项目。

Object {0: 1, 1: 1, 2: 1, 3: 1, 4: 1, 5: 1}

也许我不明白ForEach循环是如何工作的,但为什么两个循环的行为都不同? for each循环似乎检测到重复的属性名称?

2 个答案:

答案 0 :(得分:3)

您已经提出了两个不同的问题:

  • 为什么使用forArray#forEach会得到不同的结果?

  • counts[x]= (counts[x] || 0)+1如何运作?

为什么使用forArray#forEach

会得到不同的结果

Alexander has answered the first one,但为了完整起见,因为x循环中的for是该循环迭代的(索引) (012等);但x回调中的Array#forEach是该循环迭代的"dog""dog""cat",依此类推)。

假设一个非稀疏数组,for相当于

theArray.forEach(function(value) {
    // ...do something with value
});

var index, value;
for (index = 0; index < theArray.length; ++index) {
    value = theArray[index];
    // ...do something with value
}

...当然除了for示例之外,我们还要声明两个我们不会用forEach示例声明的变量。

对于您正在做的事情,您需要,而不是索引,因此如果您想使用for循环,则应该是:

var x;
for(var index=0; index<arr.length; index++){
    x = arr[index];
    counts[x]= (counts[x] || 0)+1
}
console.log(counts);

counts[x]= (counts[x] || 0)+1如何运作?

您尚未显示counts的初始化方式,但我假设

var counts = {};

var counts = []; // (This would mostly be wrong, but it works)

这意味着,如果x"dog"counts[x]将为undefined,因为counts没有开始拥有一个名为dog的属性其中counts[x]= (counts[x] || 0)+1 。然后你这样做:

counts[x]= (counts["dog"] || 0)+1

......这是

counts[x]= (undefined || 0)+1

......这是

||

JavaScript undefined运算符为curiously powerful:它评估左侧,如果那个&#34; truthy&#34;,则采用左手一边是结果;如果左侧是&#34;假的&#34;,则操作员评估右侧并将其作为结果。 &#34; truthy&#34;值都是不是&#34;假的&#34 ;; &#34; falsey&#34;值为null0""NaNfalse,当然还有undefined || 0

这意味着0undefined,因为counts[x]= (0)+1 是假的,我们有:

counts[x]= 1

......这是

counts[x]

现在,x(其中"dog"1)包含x = "dog"

下次时间为counts[x]= (counts[x] || 0)+1 执行此操作

counts[x]= (counts["dog"] || 0)+1

......这是

counts[x]= (1 || 0)+1

......这是

1

由于1 || 0 truthy 1counts[x]= (1)+1 ,所以我们有:

counts[x]= 2

......这是

"dog"

此操作会继续,因此它会计算您在数组中看到"cat"的次数(以及"lion"library(data.table) DT <- data.table(A=1:20, B=1:20*10, C=1:20*100) DT A B C 1: 1 10 100 2: 2 20 200 3: 3 30 300 4: 4 40 400 5: 5 50 500 ... 20: 20 200 2000 等)。

答案 1 :(得分:2)

forEach回调中的第一个参数是value而非index

var arr = ["dog","dog","cat","lion","dog","cat" ]
var forEachCounts = {};

arr.forEach(function(x) { 
    forEachCounts[x]= (forEachCounts[x] || 0)+1
});

console.log(forEachCounts);


var forCount = {};
for(var x = 0; x < arr.length; x++){
    forCount[arr[x]] = (forCount[arr[x]] || 0)+1
}
console.log(forCount);