JavaScript for-loop alternative: repeat(n, function(i) { ... });
This is the regular for-loop:
for (var i = 0; i < n; i++) { ... }
It is used to iterate over arrays, but also to just repeat some process n
times.
I use the above mentioned form, but it repulses me. The header var i = 0; i < n; i++
is plain ugly and has to be rewritten literally every time it is used.
I am writing this question because I came up with an alternative:
repeat(n, function(i) { ... }开发者_开发百科);
Here we use the repeat
function which takes two arguments:
The "code-behind" would be like so:
function repeat(n, f) {
for (var i = 0; i < n; i++) {
f(i);
}
}
(I am aware of the performance implications of having two additional "levels" in the scope chain of the process)
BTW, for those of you who use the jQuery library, the above mentioned functionality can be achieved out-of-the-box via the $.each
method like so:
$.each(Array(n), function(i) { ... });
So what do you think? Is this repeat
function a valid alternative to the native for loop? What are the down-sides of this alternative (other than performance - I know about that)?
Native:
for (var i = 0; i < 10; i++) {
// do stuff
}
Alternative:
repeat(10, function(i) {
// do stuff
});
You say you want a revolution... Well, you know: ruby did it just before (?)
Number.prototype.times = function(func) {
for(var i = 0; i < Number(this); i++) {
func(i);
}
}
means
(50).times(function(i) {
console.log(i)
})
Anyway, don't fight against C, you'll always lose :-P
it's an interesting thought, but if you dislike the syntax for the loop, you could always do a different type of loop:
var i = arr.length;
while (i--) {
// do stuff
}
the reverse while loop is generally faster than a for loop as well.
To address the issue of not having the break statement as others have mentioned, I would solve it this way:
function repeat(n, f) {
for (var i = 0; i < n; i++) {
if (f(i) === false) return;
}
}
Then returning false
from within a loop handler will be equivalent to break
.
Another disadvantage is that the context changes. You may want to add the option of proxying a context into the loop handlers:
function repeat(context, n, f) {
if (!f) f = n, f = context, context = window;
for (var i = 0; i < n; i++) {
if (f.call(context, i) === false) return;
}
}
Now, an advantage is that the index is preserved by the function scope, to avoid a common bug:
for (var i = 0; i < 10; i++) {
setTimeout(function () {
alert(i); // Will alert "10" every time
}, 1000);
}
repeat(10, function (i) {
setTimeout(function() {
alert(i); // Will alert "0", "1", "2", ...
}, 1000);
});
It seems pretty valid. I honestly don't think that performance would decrease too much. But there is however one big downside, that is easily fixable: the break statement.
function repeat(n, f) {
for (var i = 0; i < n; i++) {
var tcall=i;
tcall.die=function(){i=n}
f.call(tcall);
}
}
This way you would be able to call this.die()
instead of break;
which I think would throw an error.
Besides what you have already stated the main downside I see is that a "return" statement will work differently. (Which is often why I end up using "for" over "$.each" many times in my own ventures.)
精彩评论