This article explains why I have a warning if I use a code like this:
var htmlCollection = document.getElementsByClassName("class-name"),
i = htmlCollection.length,
htmlElement;
// Because htmlCollection is Live, we use a reverse iteration.
while (htmlElement = htmlCollection[--i]) { // **Warning?! Why?!**
htmlElement.classList.remove("class-name");
}
But this no explaination about « why is a bad practice to assignment expression in a while condition? ».
I also read this stackoverflow answers that point this practice as good. So...
There is a performance problem with while (element = element.parentNode) syntax-like or is just a style-code recommandation?
By the way, seems the « --i » operator is also a bad practice. I read in this article :
The ++ (increment) and -- (decrement) operators have been known to contribute to bad code by encouraging excessive trickiness.
It's some sort of joke?
There should be no performance problems with it (arguably, indexing with prefix increment can be slightly slower than postfix increment, due to issues with CPU pipelines; this is a microoptimization so ridiculously micro that it almost certainly means nothing in the context of JS engine overhead, even in C the compiler is likely to reorder expressions if it can to ensure it's not stalled waiting on the increment).
Either way, the main argument against assignment in a conditional is basically that most of the time when you do it, it's a mistake (you meant == or in JS, ===). Some code checkers (and C# requires this as a language feature to avoid accidents) are satisfied if you wrap the assignment in an additional layer of parens, to say, "Yup, I really meant to assign" (which is also necessary when you're comparing the result of the assignment to some other value; omitting the parens would instead compare, then assign a boolean, which even more likely to be wrong).
Some people have a hate on for increment/decrement operators used as part of larger expressions, because remembering order of operations is hard I guess, and because C programmers have been known to write horrible things like ++*++var and the like. I ignore these people; just don't use it for excessively tricky things.
As an orthogonal approach, and possible 'cleaner/clearer' there is:
// var htmlCollection = document.getElementsByClassName("class-name");
var htmlCollection = document.querySelectorAll('.class-name');
for(let htmlElement of htmlCollection) {
htmlElement.classList.remove("class-name");
}
as a method of iterating over DOM elements.
UPDATED to include suggestion from ShadowRanger below.
Related
I've been using object literals as a poor man's enum, something like this:
let enum = {
option1: Symbol("o1"),
option2: Symbol("o2"),
option3: Symbol("o3")
};
let item = enum.option2;
if(item === enum.option2) { console.log("Item is Option 2!") }
I use Symbol because I think it makes more semantic sense than using numbers -- in this case I don't really care about which value the "enum" carries, I just want to check equality -- but am slightly worried about performance considerations of doing it that way. Am I putting a bigger strain on the processor if I keep using Symbols in place of integers?
No, symbols are primitive values just like numbers and should be compared equally fast. The only downside might be that you have to use a variable to refer to them instead of a trusted literal, but if your variables are const and never assigned, an optimising compiler should be able to inline symbol values as well.
In any case, you should definitely use what makes more sense semantically, and helps you with development performance. Execution speed is secondary, and the difference here will be negligible.
It is the predominant opinion that built-in Javascript prototypes should not be extended (or altered in any way):
Array.prototype.empty = function () { return this.length === 0; } // don't try that
Does this rule also apply to ES2015 symbols?
const empty = Symbol("empty");
Array.prototype[empty] = function empty() { return this.length === 0; }
Since symbol is a mix of string (primitive, immutable) and object (identity) there can be no object property naming conflicts by definition.
Normal object reflection is not affected by symbols:
Object.getOwnPropertyNames(Array.prototype).indexOf("empty"); // -1
But ES2015 reflection with Reflect.ownKeys(Array.prototype) is.
So this question is mainly about how we'll use Reflect.ownKeys and Object.getOwnPropertySymbols in the future.
Yes.
There are two parts to the "don't modify something you don't own" rule:
You can cause name collisions and you can break their code.
By touching something you don't own, you may accidentally overwrite something used by some other library. This will break their code in unexpected ways.
You can create tight dependencies and they can break your code.
By binding your code so tightly to some other object, if they make some significant change (like removing or renaming the class, for example), your code might suddenly break.
Using symbols will avoid #1, but you still run into #2. Tight dependencies between classes like that are generally discouraged. If the other class is ever frozen, your code will still break. The answers on this question still apply, just for slightly different reasons.
You want to focus on loosely binding your dependencies to support better testing (loose bindings are easier to mock) and easier maintenance (a few obvious connections are easier to document and update).
To be clear: the name collisions are just a symptom of the problems caused by tightly-bound dependencies.
I stumbled upon that performance test, saying that RegExps in JavaScript are not necessarily slow: http://jsperf.com/regexp-indexof-perf
There's one thing i didn't get though: two cases involve something that i believed to be exactly the same:
RegExp('(?:^| )foo(?: |$)').test(node.className);
And
/(?:^| )foo(?: |$)/.test(node.className);
In my mind, those two lines were exactly the same, the second one being some kind of shorthand to create a RegExp object. Still, it's twice faster than the first.
Those cases are called "dynamic regexp" and "inline regexp".
Could someone help me understand the difference (and the performance gap) between these two?
Nowadays, answers given here are not entirely complete/correct.
Starting from ES5, the literal syntax behavior is the same as RegExp() syntax regarding object creation: both of them creates a new RegExp object every time code path hits an expression in which they are taking part.
Therefore, the only difference between them now is how often that regexp is compiled:
With literal syntax - one time during initial code parsing and
compiling
With RegExp() syntax - every time new object gets created
See, for instance, Stoyan Stefanov's JavaScript Patterns book:
Another distinction between the regular expression literal and the
constructor is that the literal creates an object only once during
parse time. If you create the same regular expression in a loop, the
previously created object will be returned with all its properties
(such as lastIndex) already set from the first time. Consider the
following example as an illustration of how the same object is
returned twice.
function getRE() {
var re = /[a-z]/;
re.foo = "bar";
return re;
}
var reg = getRE(),
re2 = getRE();
console.log(reg === re2); // true
reg.foo = "baz";
console.log(re2.foo); // "baz"
This behavior has changed in ES5 and the literal also creates new objects. The behavior has also been corrected in many browser
environments, so it’s not to be relied on.
If you run this sample in all modern browsers or NodeJS, you get the following instead:
false
bar
Meaning that every time you're calling the getRE() function, a new RegExp object is created even with literal syntax approach.
The above not only explains why you shouldn't use the RegExp() for immutable regexps (it's very well known performance issue today), but also explains:
(I am more surprised that inlineRegExp and storedRegExp have different
results.)
The storedRegExp is about 5 - 20% percent faster across browsers than inlineRegExp because there is no overhead of creating (and garbage collecting) a new RegExp object every time.
Conclusion:
Always create your immutable regexps with literal syntax and cache it if it's to be re-used. In other words, don't rely on that difference in behavior in envs below ES5, and continue caching appropriately in envs above.
Why literal syntax? It has some advantages comparing to constructor syntax:
It is shorter and doesn’t force you to think in terms of class-like
constructors.
When using the RegExp() constructor, you also need to escape quotes and double-escape backslashes. It makes regular expressions
that are hard to read and understand by their nature even more harder.
(Free citation from the same Stoyan Stefanov's JavaScript Patterns book).
Hence, it's always a good idea to stick with the literal syntax, unless your regexp isn't known at the compile time.
The difference in performance is not related to the syntax that is used is partly related to the syntax that is used: in /pattern/ and RegExp(/pattern/) (where you did not test the latter) the regular expression is only compiled once, but for RegExp('pattern') the expression is compiled on each usage. See Alexander's answer, which should be the accepted answer today.
Apart from the above, in your tests for inlineRegExp and storedRegExp you're looking at code that is initialized once when the source code text is parsed, while for dynamicRegExp the regular expression is created for each invocation of the method. Note that the actual tests run things like r = dynamicRegExp(element) many times, while the preparation code is only run once.
The following gives you about the same results, according to another jsPerf:
var reContains = /(?:^| )foo(?: |$)/;
...and
var reContains = RegExp('(?:^| )foo(?: |$)');
...when both are used with
function storedRegExp(node) {
return reContains.test(node.className);
}
Sure, the source code of RegExp('(?:^| )foo(?: |$)') might first be parsed into a String, and then into a RegExp, but I doubt that by itself will be twice as slow. However, the following will create a new RegExp(..) again and again for each method call:
function dynamicRegExp(node) {
return RegExp('(?:^| )foo(?: |$)').test(node.className);
}
If in the original test you'd only call each method once, then the inline version would not be a whopping 2 times faster.
(I am more surprised that inlineRegExp and storedRegExp have different results. This is explained in Alexander's answer too.)
in the second case, the regular expression object is created during the parsing of the language, and in the first case, the RegExp class constructor has to parse an arbitrary string.
I normally use this pattern to iterate over object properties:
for(var property in object) {
if(object.hasOwnProperty(property)) {
...
}
}
I don't like this excessive indentation and recently it was pointed out to me that I could get rid of it by doing this:
for(var property in object) {
if(!object.hasOwnProperty(property)) {
continue;
}
...
}
I like this because it doesn't introduce the extra level of indentation. Is this pattern alright, or are there better ways?
I personally prefer:
for(var property in object) if(object.hasOwnProperty(property)) {
...
}
There is no extra level of indentation because for, if, etc. will take the next statement if you leave out the curly braces. Since we put all of our code inside the if hasOwnProperty block it makes any braces for the for statement unnecessary.
Essentially it's equivalent to:
for(var property in object) {
if(object.hasOwnProperty(property)) {
...
} else {
continue;
}
}
Syntacticly I'd prefer something like this
function own(obj) {
var ownprops = {};
for (var prop in obj)
if (obj.hasOwnProperty(prop)) ownprops[prop] = 1;
return ownprops;
}
for (var property in own(object)) {
//code
}
Looks nice, but it entails two loops over the same object, not pretty performance wise.
The other way to do it is functionaly
function foreach(obj, func, thisp) {
for (var prop in obj)
if (obj.hasOwnProperty(prop)) func.call(thisp, obj[prop], prop);
}
foreach(object, function(val, key) {
//code
});
Only one loop, but a function is called for every iteration, which is not great performance wise but better than the last solution. Note that it also clobbers the value of this, but you can pass that value explicitly as the optional 3rd argument.
Just some alternatives. The way you are doing it, and the way explained by Daniel is just fine, and without performance compromises.
Also, I'd like to point out that you do not have to indent your code for every single curly brace...
One factor depends on whether you listen to Douglas Crockford. In his book, JavaScript: The Good Parts, he lumps continue in with the bad parts.
"I have never seen a piece of code that was not improved by refactoring it to remove the continue statement." - Douglas Crockford, JavaScript: The Good Parts
As Tim Down mentioned in his comment, Crockford gives no reason in the book to explain why continue should be avoided. But on his website he says, "It tends to obscure the control flow of the function." I only mention Crockford's opinion since many consider him an authority.
Personally I don't see any problem with how you've coded your loop, especially since the continue appears right at the top where it won't easily be overlooked. Are you working with a team of developers? Do they have a good understanding of what continue does? Do you have a code conventions document that talks about how to handle deep nesting of statements?
Mcconnel:
A loop with many breaks may indicate
unclear thinking about the structure
of the loop or its role in the
surrounding code. Excessive breaks
raises often indicates that the loop
could be more clearly expressed as a
series of loops. Use of break
eliminates the possibility of treating
a loop as a black box. Control a
loop's exit condition with one
statement to simplify your loops.
'break' forces the person reading your
code to look inside to understand the
loop's control, making the loop more
difficult to understand.
Dijkstra:
features like break tend to sabotage
the benefits of structured
programming, and prevent the
programmer from understanding the
program as a composition of
independent units
Loops with continue can be factored into this form and thus the loop may be treated as a black box. Crawford is wrong. Breaks smell, but continue is good.
further analysis: http://sites.google.com/site/dustingetz/dev/break-and-continue
Can you guys help me determine the performance difference of each of these
statements? Which one would you use?
Making a new Array using
- var new_list = new Array(); //or
- var new_list = [];
Appending element using
- push('a')
- new_list[i]; (if i know the length)
Ternary operator or if() {} else (){}
Trying to make isodd function, which is faster
(! (is_even)) or (x%2!=0)
forEach() or normal iteration
one more
a= b = 3; or b=3; a=b;
[edit: I'm making a Math Library. So any performance hacks discussions are also welcome :) ]
Thanks for your help.
I've always assumed that since (x&1) is a bitwise operation, it would be the fastest way to check for even/odd numbers, rather than checking for the remainder of the number.
Performance characteristics for all browser (especially at the level of individual library functions) can vary dramatically, so it's difficult to give meaningful really meaningful answers to these questions.
Anyhoo, just looking at the fast js engines (so Nitro, TraceMonkey, and V8)
[ ] will be faster than new Array -- new Array turns into the following logic
cons = lookup property "Array", if it can't be found, throw an exception
Check to see if cons can be used as a constructor, if not: throw an exception
thisVal = runtime creates a new object directly
res = result of calling cons passing thisVal as the value for this -- which requires logic to distinguish JS functions from standard runtime functions (assuming standard runtime functions aren't implemented in JS, which is the normal case). In this case Array is a native constructor which will create and return a new runtime array object.
if res is undefined or null then the final result is thisVal otherwise the final result is res. In the case of calling Array a new array object will be returned and thisVal will be thrown away
[ ] just tells the JS engine to directly create a new runtime array object immediately with no additional logic. This means new Array has a large amount of additional (not very cheap) logic, and performs and extra unnecessary object allocation.
newlist[newlist.length] = ... is faster (esp. if newlist is not a sparse array), but push is sufficiently common for me to expect engine developers to put quite a bit of effort into improving performance so this could change in time.
If you have a tight enough loop there may be a very slight win to the ternary operator, but arguably that's an engine flaw in the trival case of a = b ? c : d vs if (b) a = c; else a = d
Just the function call overhead alone will dwarf the cost of more or less any JS operator, at least in the sane cases (eg. you're performing arithmetic on numbers rather than objects)
The foreach syntax isn't yet standardised but its final performane will depend on a large number of details; Often JS semantics result in efficient looking statements being less efficient -- eg. for (var i in array) ... is vastly slower than for (var i = 0; i < array.length; i++) ... as the JS semantics require in enumeration to build up a list of all properties on the object (including the prototype chain), and then checking to make sure that each property is still on the object before sending it through the loop. Oh, and the properties need to be converted from integers (in the array case anyway) into strings, which costs time and memory.
I'd suggest you code a simple script like:
for(var i = 0; i < 1000; i++){
// Test your code here.
}
You can benchmark whatever you want that way, possibly adding timing functions before and after the for statement to be more accurate.
Of course you'll need to tweak the upper limit (1000 in this example) depending on the nature of your operations - some will require more iterations, others less.
Both are native constructors probably no difference.
push is faster, it maps directly to native, where as [] is evaluative
Probably not much of a difference, but technically, they don't do the same thing, so it's not apples to apples
x%2, skips the function call which is relatively slow
I've heard, though can't find the link at the moment, that iteration is faster than the foreach, which was surprising to me.
Edit: On #5, I believe the reason is related to this, in that foreach is ordered forward, which requires the incrementor to count forward, whereas for loops are ever so infinitesimally faster when they are run backward:
for(var i=a.length;i>-1;i--) {
// do whatever
}
the above is slightly faster than:
for(var i=0;i<a.length;i++) {
// do whatever
}
As other posters suggest, I think doing some rough benchmarking is your best bet... however, I'd also note that you'll probably get very different results from different browsers, since I'm sure most of the questions you're asking come down to specific internal implementation of the language constructs rather than the language itself.
This page says push is slower.
http://dev.opera.com/articles/view/efficient-javascript/?page=2