Why You Should Always Use === and Other Bad Practices
fifod.com
fifod.com
The speed shouldn't be the issue. If it is, please start using a library like Lo-Dash [1], a faster version of Underscore.js. Actually, please just do that in general so you won't make mistakes like this.
The proper way to do alternate behavior for the first iteration, would be this... It's O(n) versus the authors O(2n)
if(attributeArray instanceof Array) {
if (attributeArray.length >= 1){
// do something with attributeArray[0]
for (var i = 1; i < attributeArray.length; ++i)
// do something different with attributeArray[index]
}
}When manipulating collections - you almost always want .map .filter .reduce .some .all or a variation of thereof and not a plain old for loop for this sort of thing, doing this a million or a billion times a second theoretically shouldn't matter. (explained in : http://stackoverflow.com/a/17253577/1348195)
Also, checking for instanceof Array is a JS anti pattern to begin with and makes code a lot less generic.
if(array.length > 0) doFunction(array[0]);
array.slice(1).forEach(doOtherFunction);If you have a very large array of course optimization can/should be considered but that's simply not the average case.
I never heard of Dequeue [1], that is mighty cool. I agree that premature optimization is not good - but when it can be done cleanly without hurt to the readability of the code, I'd say to keep it in ones' repertoire, to effectively write more performant code, more often, on average.
Agreed on the hideousness of that 'instanceof Array' check.
Effectively, you're checking 'the performance of interperted JavaScript' most the the time.
2n implies looping twice or something, not a single extra operation.
(and 20 is probably a gross underestimate if we're comparing console.log to a mere ==)
Both the different types and the delete (array with holes) are _very_ harmful for performance in v8.
JSPerf is a horrible place to benchmark these things, see http://mrale.ph/blog/2012/12/15/microbenchmarks-fairy-tale.h... and http://mrale.ph/blog/2013/08/14/hidden-classes-vs-jsperf.htm... by Vyacheslav Egorov (worked on v8)
For example:
if(array.length > 0) doFunction(array[0]);
array.slice(1).forEach(doOtherFunction);
Is far more readable and maintainable than that mess with the useless indexes and does the same thing.Optimizing based on microbenchmarks and not checking for deopts and doing profiling is worthless.
I agree 1000-fold that the Array manipulation techniques are extremely easy to read. Keep in mind though, you are creating a new copy of the [1-n]array through the slicing, and the overhead of the function call with forEach will matter on large Arrays. Really depends what you are building. Don't call performance optimization worthless.
Micro benchmarks are not how we optimize - we profile.
In this particular case I am not sure I would prefer slicing+forEach to writing a old-style for-loop on any relatively hot path. Of course either profiling or thorough knowledge of the code should be applied before making this decision to determine whether this code path is hot or not, what's the average size of the array and so on. The main motivation for this decision would be the fact that slice produces the copy of the array. This is both hindrance in terms of performance (as VMs right now would not elide copy operation) and in terms of readability (e.g. when I see such code I would have to ask myself: does doOtherFunction require fresh copy or not, does it use only the first argument or all of what forEach passes into it and so on?).
So you can see the choice for me is pretty complicated.
If we're going to talk "practically" here :) things like branch prediction will ensure that nothing like 2x the execution time will be spent on just the double conditional.
Meanwhile, what you do inside that loop becomes much more important to the time estimate than the conditional (.length is a fast single property lookup, whereas just accessing a value in the array (which is presumably the purpose of this method) will often trigger a bounds check on length, then an offset into a looked-up offset into memory, etc).
So it's not really worth doing for speed. All that said, I think yours reads better anyway.
You should be using Array.isArray ( ES5 compatible browsers ), or Object.prototype.toString.call( obj ) === '[object Array].
Lodash, Underscore, and jQuery all provide utility methods to do that comparison for you.
In JavaScript the rules for scope are clear—it's lexical scoping nested at the function level. Loops, conditionals, etc... have no bearing on scope.
Strict equals is something I only use when necessary in javascript. Despite the "taboo" surrounding double equals, I rarely face situations where its use adds brittleness to the code. Is there some horrible danger that I am just not seeing?
> overzealous developers might accidentally break your code trying to be proactive
It's not just people changing your code, it's people trying to read your code (including you, months later).
It's using reflection over object keys to iterate an array. This just happens to work because JavaScript arrays are also objects.
`myArr.forEach(function(el){ // do things here });`
Is perfectly fine.