regarding your edit, you're exactly right, of course a for loop will be faster. Sometimes you really do need a function call though, in which case fast forEach and map implementations become more useful.
The next step for fast.js are some sweet.js macros which will make writing for loops a bit nicer, because it's pretty painful to write this every time you want to iterate over an object:
var keys = Object.keys(obj),
length = keys.length,
key, i;
for (i = 0; i < length; i++) {
key = keys[i];
// ...
}
I'd rather write:
every key of obj {
// ...
}
and have that expanded at compile time.
Additionally there are some cases where you must use inline for loops (such as when slicing arguments objects, see https://github.com/petkaantonov/bluebird/wiki/Optimization-k...) and a function call is not possible. These can also be addressed with sweet.js macros.
To be fair, it's not obvious if you're not a JS expert: coming from some other language, you could naively assume that function call gets inlined, with no overhead.
A few months ago, I tried some image processing with JS and the canvas object (big Arrays).
They have a structure like image[pixel].color
What I found was, always traversing the object structure was much slower than putting every pixel color as an argument in a function, that gets called every iteration.
So I had the impression, reasonable simple function, like a greyscale filter, get inlined by engines like V8.
Most of the array methods are explicitly defined in terms of indexing rather that iterators, so for(of) is incorrect. On the other hand indexing is still faster than iteration in the major implementations.
My comment were intended as a direct reply to phpnode's code, 'ignoring' the rest of the thread.
How do you mean when you state that for(of) is incorrect?
Perhaps this 'example' clears something up?
« for (value in {a:1,b:2,c:3,d:4,e:5}) console.log(value)
» undefined
"a"
"b"
"c"
"d"
"e"
« for (value of {a:1,b:2,c:3,d:4,e:5}) console.log(value)
× TypeError: ({a:1, b:2, c:3, d:4, e:5})['@@iterator'] is not a function
the only issue is i'd like to differentiate between iterating arrays and objects at the syntax level. Coffeescript uses `in` for arrays and `of` for objects, but I agree that becomes confusing. Open to other suggestions!
I've been spending some time thinking about CoffeeScript's choice for `in` and `of` and I think I have the answer: they should be more regular. One (probably `of`) should be used for the keys/indexes and the other (probably `in`) should be used for contents.
These are legal CoffeeScript examples:
for key, value of object
if key of object
for value in array
if value in array
for index, value of array
if index of array
The issue with coffeescript is that it uses the opposite syntax to JS - `in` for arrays instead of objects. ES6 introduces the `of` keyword for real iterators so i don't really want to use that for either of them. It's tricky.
There are other options but they're verbose
every element as key, value from arr {
console.log(key, value);
}
every property as key, value from obj {
console.log(key, value);
}
every [key, value] from arr {
console.log(key, value);
}
every {key, value} from obj {
console.log(key, value);
}
every [key] from arr {
console.log(key);
}
every {_, value} from obj {
console.log(value);
}
Looks a bit cramped to me but I get the impression that array comprehension is one of the major reasons that people use Coffeescript, so perhaps it's not too much trouble?
There's also the issue with some fonts making it hard to differentiate between { and [ but it's an idea that might be worth to think about at least.
I quite like this suggestion. If we flip the key, value around to make it inline with what forEach etc do, then we don't need the placeholder for iterating without the key:
fast-each [value] from arr {
}
fast-each {value} from obj {
}
fast-each [value, key] from arr {
}
fast-each {value, key} from obj {
}
The disadvantage is that this looks like array comprehension but isn't.
Alternative:
fast-properties key, value from obj {
}
fast-elements index, value from arr {
}
fast-properties value from obj {
}
fast-elements value from arr {
}
The next step for fast.js are some sweet.js macros which will make writing for loops a bit nicer, because it's pretty painful to write this every time you want to iterate over an object:
I'd rather write: and have that expanded at compile time.Additionally there are some cases where you must use inline for loops (such as when slicing arguments objects, see https://github.com/petkaantonov/bluebird/wiki/Optimization-k...) and a function call is not possible. These can also be addressed with sweet.js macros.