Is there a way to loop backwards through an array using forEach
(not any other kind of loop, I know how to do with with a for / standard ways) and without actually reversing the array itself?
有没有办法使用forEach向后循环数组(不是任何其他类型的循环,我知道如何使用for /标准方法)并且实际上没有反转数组本身?
3 个解决方案
#1
13
var arr = [1, 2, 3];
arr.slice().reverse().forEach(function(x) {
console.log(x);
})
will print:
将打印:
3
2
1
arr
will still be [1, 2, 3]
, the .slice()
creates a shallow copy.
arr仍然是[1,2,3],.slice()创建一个浅表副本。
#2
2
No, forEach
only processes forward through the array. So you'd have to do something else, which you've said in your question was out of scope.
不,forEach只通过数组进行处理。所以你必须做一些其他事情,你在问题中说过的事情超出了范围。
I can think of two options which just use precursors to using forEach
(so, they don't use a for
loop or other kind of loop). I don't know if those would be out of scope or not, so here they are:
我可以想到两个选项只使用前驱来使用forEach(因此,它们不使用for循环或其他类型的循环)。我不知道这些是否超出范围,所以这里是:
-
Copy the array and reverse the copy, then use
forEach
on it复制数组并反转副本,然后在其上使用forEach
-
Use
Object.keys
to get the indexes, reverse that, then useforEach
on it (which will loop through the indexes, not the values, but then we can look them up)使用Object.keys获取索引,反转它,然后在其上使用forEach(它将遍历索引,而不是值,但我们可以查找它们)
Here's #1:
这是#1:
slice
copies the array (shallow copy, so not likely to be expensive), then we reverse it, then forEach
:
slice复制数组(浅拷贝,所以不太可能是昂贵的),然后我们反转它,然后forEach:
var a = ['one', 'two', 'three'];
a.slice().reverse().forEach(function(entry) {
snippet.log(entry);
});
snippet.log("Proof that a is not, itself, reversed: " +
JSON.stringify(a));
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
Here's #2:
这是#2:
We use Object.keys
to get the array indices (using filter
if you store non-element properties in your arrays), reverse that, and then loop through the result:
我们使用Object.keys来获取数组索引(如果在数组中存储非元素属性,则使用过滤器),反过来,然后遍历结果:
var a = ['one', 'two', 'three'];
Object.keys(a).reverse().forEach(function(index) {
snippet.log(a[index]);
});
snippet.log("Proof that a is not, itself, reversed: " +
JSON.stringify(a));
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
Side note: Here's what I mean about using filter
if you have non-element properties on your array:
旁注:如果您的数组上有非元素属性,那么我的意思是使用过滤器:
var a = ['one', 'two', 'three'];
a.nonElementProperty = "foo";
Object.keys(a).filter(function(name) {
return String(+name) === name;
}).reverse().forEach(function(index) {
snippet.log(a[index]);
});
snippet.log("Proof that a is not, itself, reversed: " +
JSON.stringify(a));
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
#3
2
As yet the browsers do not seem to have optimised the Array.forEach
function. With not much effort you can write a simple polyfill that out performs the Array.forEach
method by at least 10 to 1.
到目前为止,浏览器似乎还没有优化Array.forEach功能。通过不费力气,您可以编写一个简单的polyfill,它执行Array.forEach方法至少10比1。
So you can create your own Array.revEach
and have it outperform the native Array.forEach
, thought I hope that the browsers address the very slow performance of Array.forEach
soon and make the need to polyfill actual existing methods not necessary.
因此,您可以创建自己的Array.revEach并使其优于本机Array.forEach,我希望浏览器能够很快解决Array.forEach的非常慢的性能,并且需要填充实际现有的方法,而不是必需的。
For Array.revEach
out performs Array.forEach
running 17 times faster on "Chrome 46.0.2490.22 beta-m"
对于Array.revEach,在“Chrome 46.0.2490.22 beta-m”上执行运行速度快17倍的Array.forEach
if (Array.prototype.revEach === undefined) {
Object.defineProperty(Array.prototype, 'revEach', {
writable : false,
enumerable : false,
configurable : false,
value : function (func) {
var i;
var len = this.length-1;
for (i = len; i >= 0; i--) {
func(this[i], i, this);
}
}
});
}
Just to add the actual official polyfill modified to reverse. Comments show my changes.
只是添加实际的官方polyfill修改为反向。评论显示我的变化。
// Production steps of ECMA-262, Edition 5, 15.4.4.18
// Reference: http://es5.github.io/#x15.4.4.18
// Modified by Blindman67 to revEach
if (!Array.prototype.revEach) { // name changed
Array.prototype.revEach = function(callback, thisArg) { // name changed
var T; // k defined where len was
if (this == null) {
throw new TypeError(' this is null or not defined');
}
var O = Object(this);
var k = (O.length >>> 0)-1; // set k (counter) ToUint32
// len var removed
if (typeof callback !== "function") {
throw new TypeError(callback + ' is not a function');
}
if (arguments.length > 1) {
T = thisArg;
}
while (k >= 0) { // reverse condition
var kValue;
if (k in O) {
kValue = O[k];
callback.call(T, kValue, k, O);
}
k--; // dec counter
}
};
}
#1
13
var arr = [1, 2, 3];
arr.slice().reverse().forEach(function(x) {
console.log(x);
})
will print:
将打印:
3
2
1
arr
will still be [1, 2, 3]
, the .slice()
creates a shallow copy.
arr仍然是[1,2,3],.slice()创建一个浅表副本。
#2
2
No, forEach
only processes forward through the array. So you'd have to do something else, which you've said in your question was out of scope.
不,forEach只通过数组进行处理。所以你必须做一些其他事情,你在问题中说过的事情超出了范围。
I can think of two options which just use precursors to using forEach
(so, they don't use a for
loop or other kind of loop). I don't know if those would be out of scope or not, so here they are:
我可以想到两个选项只使用前驱来使用forEach(因此,它们不使用for循环或其他类型的循环)。我不知道这些是否超出范围,所以这里是:
-
Copy the array and reverse the copy, then use
forEach
on it复制数组并反转副本,然后在其上使用forEach
-
Use
Object.keys
to get the indexes, reverse that, then useforEach
on it (which will loop through the indexes, not the values, but then we can look them up)使用Object.keys获取索引,反转它,然后在其上使用forEach(它将遍历索引,而不是值,但我们可以查找它们)
Here's #1:
这是#1:
slice
copies the array (shallow copy, so not likely to be expensive), then we reverse it, then forEach
:
slice复制数组(浅拷贝,所以不太可能是昂贵的),然后我们反转它,然后forEach:
var a = ['one', 'two', 'three'];
a.slice().reverse().forEach(function(entry) {
snippet.log(entry);
});
snippet.log("Proof that a is not, itself, reversed: " +
JSON.stringify(a));
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
Here's #2:
这是#2:
We use Object.keys
to get the array indices (using filter
if you store non-element properties in your arrays), reverse that, and then loop through the result:
我们使用Object.keys来获取数组索引(如果在数组中存储非元素属性,则使用过滤器),反过来,然后遍历结果:
var a = ['one', 'two', 'three'];
Object.keys(a).reverse().forEach(function(index) {
snippet.log(a[index]);
});
snippet.log("Proof that a is not, itself, reversed: " +
JSON.stringify(a));
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
Side note: Here's what I mean about using filter
if you have non-element properties on your array:
旁注:如果您的数组上有非元素属性,那么我的意思是使用过滤器:
var a = ['one', 'two', 'three'];
a.nonElementProperty = "foo";
Object.keys(a).filter(function(name) {
return String(+name) === name;
}).reverse().forEach(function(index) {
snippet.log(a[index]);
});
snippet.log("Proof that a is not, itself, reversed: " +
JSON.stringify(a));
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
#3
2
As yet the browsers do not seem to have optimised the Array.forEach
function. With not much effort you can write a simple polyfill that out performs the Array.forEach
method by at least 10 to 1.
到目前为止,浏览器似乎还没有优化Array.forEach功能。通过不费力气,您可以编写一个简单的polyfill,它执行Array.forEach方法至少10比1。
So you can create your own Array.revEach
and have it outperform the native Array.forEach
, thought I hope that the browsers address the very slow performance of Array.forEach
soon and make the need to polyfill actual existing methods not necessary.
因此,您可以创建自己的Array.revEach并使其优于本机Array.forEach,我希望浏览器能够很快解决Array.forEach的非常慢的性能,并且需要填充实际现有的方法,而不是必需的。
For Array.revEach
out performs Array.forEach
running 17 times faster on "Chrome 46.0.2490.22 beta-m"
对于Array.revEach,在“Chrome 46.0.2490.22 beta-m”上执行运行速度快17倍的Array.forEach
if (Array.prototype.revEach === undefined) {
Object.defineProperty(Array.prototype, 'revEach', {
writable : false,
enumerable : false,
configurable : false,
value : function (func) {
var i;
var len = this.length-1;
for (i = len; i >= 0; i--) {
func(this[i], i, this);
}
}
});
}
Just to add the actual official polyfill modified to reverse. Comments show my changes.
只是添加实际的官方polyfill修改为反向。评论显示我的变化。
// Production steps of ECMA-262, Edition 5, 15.4.4.18
// Reference: http://es5.github.io/#x15.4.4.18
// Modified by Blindman67 to revEach
if (!Array.prototype.revEach) { // name changed
Array.prototype.revEach = function(callback, thisArg) { // name changed
var T; // k defined where len was
if (this == null) {
throw new TypeError(' this is null or not defined');
}
var O = Object(this);
var k = (O.length >>> 0)-1; // set k (counter) ToUint32
// len var removed
if (typeof callback !== "function") {
throw new TypeError(callback + ' is not a function');
}
if (arguments.length > 1) {
T = thisArg;
}
while (k >= 0) { // reverse condition
var kValue;
if (k in O) {
kValue = O[k];
callback.call(T, kValue, k, O);
}
k--; // dec counter
}
};
}