Out of curiosity. I check whether some string is longer than a maximum specified length:
var name = "This Is a Name";
if (!name.length >= 10)
{
//valid length
}
else
{
alert("Too long");
}
Is this any better / faster (?):
if (name.length <= 10)
I remember that in some languages it's better to write the negation first so is it even betterer (yip, I just wrote that) like so (?):
if (10 >= name.length)
I know that 10 is overlapping in the code - don't mind that. I just want to know if there is any performance / best practice on this.
I almost always use < and <= instead of > or >=. I find that always having the smaller value on the left (when the test succeeds) is quicker to mentally parse. It also makes range tests:
if (0 <= a && a < 10) …
read more like the mathematical equivalent 0 ≤ a < 10.
Performance-wise, I'd be surprised if there was any measurable difference.
This is out of your hands, the interpreter will do whatever it deems right with this. Javascript interpreters might be so advanced nowadays they will optimize this, but more likely those interpreters themselves are compiled with a compiler that will have optimized the translation itself so it was even out of the hands of the person that wrote the interpreter.
So really, if you want a language where you want to control this kind of behaviour, you need asm. Not even in (optimized) C do you really control this.
The only thing you can say with certainty is that n.length > 9 could be marginally faster because it contains less characters so it will be parsed quicker. We're talking nanoseconds, maybe even picoseconds there, though.
Let me just comment on your last example: I am fairly sure that your if(10 >= name.length) convention was started in the era of bad C compiler warnings as an effort to avoid errors of the if(pointer = NULL) { error(); } else { i = *pointer; } type, since the reversed version would make the typo cause a compiler error. This is still surprisingly relevant in jslint-less JavaScript, but I don't think it can affect non-equality comparisons.
For the rest of it, I'm also firmly in the "no difference" camp, even though I haven't experimented, I just can't think of plausible causes where the order would make a performance difference.
If it's not actually the bottleneck of your application, I'd recommend the most readable, not the most performant code - even if there was a slight difference in performance, which I doubt there really is in your case.
In your case, the most easily understandable code piece as far as I am concerned, would be:
if (name.length <= 10)
If you're really intent on getting the most performance out of your code, you would have to write some tests; because speaking generically about this is not possible in most cases, e.g. nearly every JavaScript implementation already will behave slightly different.
Also make sure to check up on "Premature Optimization", e.g. in the wikipedia article on Program optimization (section "When to optimize").
Related
I am learning JS and came across this exercise:
Write a loop which prompts for a number greater than 100.
If the visitor enters another number – ask them to input again.
The loop must ask for a number until either the visitor enters a number greater than 100 or
cancels the input/enters an empty line.
Here we can assume that the visitor only inputs numbers.
There’s no need to implement a special handling for a non-numeric input in this task.
My solution works and was as follows:
let value;
while (true) {
value = prompt('Enter a number greater than 100', 0);
if (value > 100 || value === '');
console.log(value);
break;
}
The MDN solution was this, and though it is shorter and more simple, it seems to accomplish the same task.
let num;
do {
num = prompt("Enter a number greater than 100?", 0);
} while (num <= 100 && num);
Is my solution still valid? Is the MDN one more proper?
I just want to make sure I am understanding things correctly as I go.
If your solution worked before, I think you probably typed in your solution incorrectly here. I am going to assume you meant to write:
if (value > 100 || value === '') {
console.log(value);
break;
}
Since you're just starting out with JS, you will eventually learn that there will be multiple ways you can handle any given coding problem. It will not always be a good answer/wrong answer type of scenario. Sometimes there are multiple ways to accomplish the same thing.
In this example, the MSN solution is better in terms of readability and possibly safety.
The MSN solution creates a while loop with the exit condition identified in the while statement. This loop will exit when that condition is met.
In your solution, the loop will never exit on it's own, the while() statement will always evaluate to 'true'. This loop needs an explicit exit statement, which you provide with the if() condition.
Your method, although it works, is a little bit less safe in terms of code readability and overall maintenance profile. For example, a future developer could by mistake change the if() condition and inadvertently create a never ending loop.
Or, if the loop contained several dozen lines of code, a developer may miss the if condition, and may add some important code after the if condition (such code would not execute when the exit condition is met.)
Yes, this specific sample exercise is trivial, so the code complexity and readability may not matter. But in large enterprise applications with hundreds of lines of code, such code choices carry serious risks with costly implications.
That said, I'll reiterate - as you learn more about JS, you will often find that there are multiple ways of solving any given problem. Sometimes you do want to create an explicit exit condition through an if() statement, on rare occasions you will want to create a never ending loop.
As you explore more complex problems, you will find needs for such solutiosn. So keep learning, keep trying different solutions, and keep asking questions.
I run performance test jsperf for three simple if else statements with same logic:
test if1:
var a = "1";
if (a == "1") {
a = "1"
} else {
a = "2"
}
test if2:
var a = "1";
if (a == "1")
a = "1"
else
a = "2"
test if3:
var a = "1";
a == "1" ? a="1" : "2";
Can someone tell me why test if1 is fastest of three?
The first time i compare test if1 with test if2 and test if1 was faseter. After i check test if1 with test if3 and test if1 was faster again. Now i compare all of them and test if2 was faster.
All three together
tested on Chrome 34.0.1847
Did you run them many times to see if you consistently get the same results?
Even if you do, they're probably a very tiny difference. Such a difference would never make a practical difference in the overall performance of a full system. Trying to optimize through trivial syntax changes like these would be a very bad case of premature optimization which can make your code harder to read, and is a waste of time because it won't give you any real benefits.
Now I hope you understand that your question is actually a "wrong question", but in case you still want an answer as to why the first test performs fastest (if it really does), that would depend on some deep details of the JavaScript engine executing the code. JS engines are very complex nowadays, with huge amounts of optimization, so you can't really tell e.g. what CPU instructions will be emitted for a piece of code. In the next minor update of Chrome, the other tests could suddenly become faster due to some change somewhere in Chrome's JS engine.
There is no meaningful performance difference in your three cases--the difference is on the order of 1%.
Note that in the third case, you are failing to set a to "2", but instead merely returning "2".
The presence or absence of brackets is highly unlikely to have any significant impact on performance, or more likely no impact whatsoever. It's a one-time, parse-time issue. The ternary form, your third case, is in essence logically identical to the first two cases. In fact, most minifiers would turn your cases 1 and 2 into a ternary operator.
I work with JavaScript but I always wonder this for all the languages.
Do I get better performance doing this:
var i = 0;
if(j < 0)
{
i = 1;
}
Or this?
var i;
if(j < 0)
{
i = 1;
}
else
{
i = 0;
}
With 50% chance to have j < 0
That will depend on the implementation of javascript engine, which, at least if you write your code for the Web, is out of your control.
One browser might be faster with first version of the code, the other with the second version. And tomorrow it might change.
Do not optimize things like this unless you have pinned down this one line of code as a bottleneck of your task.
You might want to read when to optimize.
You will be better of to write readable and well designed code, and let the browser vendors wory about machine level optimisations.
The things you should optimize are algorithms, and not language specific constructions.
Neither of your code makes much of a difference. Depends on the JS engine of course but todays engines are pretty advanced and optimize code very well(especially V8 on chrome and node.js).
Benchmark it. You can use simple console.time('label'); console.timeEnd('label') at least in Chrome.
In my opinion your code looks ugly and like a bloat. A lot of space is consumed with no content. I would prefer this approach as it reads much faster and you should care about readability as much as performance:
var i;
if(j < 0) {
i = 1;
} else {
i = 0;
}
Also you have an access to ternary operator:
var i = j < 0 ? 1 : 0;
which is readable if you do not nest it. Again - performance wise all of them are equal and will differt by maybe a millisecond or two so you should not care about performance in such simple cases. Care about readability :)
Also performance will depend on your j value. If optimizer will see that you set j to 1. It will short-circuit the whole code and simply set i = 0. IMHO in such simple cases it's not useful to spend time to search for improvement except for readability :).
Is it a bad habit to write reverse loops as:
for (i = N; i--;)
in order to access (N-1) to 0
If so, why? jsLint certainly doesn't like it.
There's no technical reason that this won't work. However, it clearly has readability issues since someone had an immediate "well that won't work!" reaction.
This is the kind of issue that the jQuery team struggles with – whether to use novel constructs that save bytes at the expense of clarity and maintainability. It really comes down to whether it's worth 1 or 3 bytes of savings:
for(var i=9;i--;)
var i=9;while(i--)
for(var i=9;i>0;i--)
In this case, probably not.
It is less readable, without your explanation it would take me few seconds to understand what the loop does. Why not simply:
while(i-- > 0)
?
Did you consider readability? You may very well understand it yourself, but other developers might get confused since the parts of the for "idiom" are usually named as:
for ([initialization]; [condition]; [final-expression])
While the condition can technically be any expression, your version does not conform to this idiom, since the "condition" part you use does more than just defining a condition - it sneakily decrements i as well.
"Is it a bad habit to write reverse loops as:"
for (i = N; i--;)
That's a matter of opinion, but it's effectively a reverse while with initialization, so in my opinion it's not a "bad habit". It's just a coding style.
The specification makes the parts of a for optional to give the developer that flexibility.
"jsLint certainly doesn't like it."
Who cares. You're not bound to follow the opinions of jsLint.
The answers would be very subjective I guess. I don't think it is a bad habit but I do find it aesthetically unpleasing. This can be expressed more elegantly as:
for (i = N - 1; i >= 0; i--) {
// do something here.
}
// And if it is really important that i should be 0 here
// as it is in your original code.
i = 0
This code is easier on our brain while browsing a lot of code that happens to contain this.
Yes. There is a good reason. Readability.
Which way is more efficient? Is there a difference?
This one:
var str = 'abc';
if(str.length == 20) {
//...
}
if(str.length == 25) {
//...
}
// and so on
Or this one:
var str = 'abc';
var length = str.length;
if(length == 20) {
//...
}
if(length == 25) {
//...
}
// and so on
In the browsers where this might actually matter (read: IE) it will be calculated every time, so it's faster to store the value in a local variable.
http://jsperf.com/string-length
It used to be that
var len = someArray.length;
for (var i=0; i<len; i++) {
// ...
}
was faster than
for (var i=0; i<someArray.length; i++) {
// ...
}
but these days, V8's (Chrome's JS engine) optimizes the latter to run faster than the former. That's great - just remember, you don't really need to worry about performance in Chrome.
If you're curious to learn more about JavaScript performance, High Performance JavaScript is a solid read. Take its recommendations with a grain of salt, though, since a trick that makes code run faster in IE (6, 7, 8 or even 9) might very well make the code run slower in Chrome or Firefox 4.
The second is by far the safer way to go. In the first you are assuming that it won't get recalculated. In the second you know that it won't. The second isn't always the best way though. It will only work when you know other processes won't affect the length of the array. So with global variables etc. you have to be careful. This can also apply to modifying the contents (length) of an array inside a for loop which stops at the upper bound of the array.
Strings are immutable in JavaScript, so it is unlikely that even bad implementations of Javascript would recalcuate the length property of the string every time you access it.
You can actually test this yourself using jsperf; using Chrome 12, it actually looks like your first example is faster.
In theory, I would expect that the second code block should be quicker.
However, given that today's JS interpreters are actually highly optimised JIT compilers, I would imagine that they would spot that kind of thing and optimise it.
That should apply to pretty much all browsers in current mainstream use, with the obvious exception of IE8 and lower, where it's anyone's guess how it does it, but it'll be slow either way.