How much slower faster is the typeof operator than a function call? Or is it negligible and micro-optimising?
if (isNumber(myVar)) {
}
if (typeof myVar === 'number') {
}
Or is it negligible and micro-optimising?
Yes, this is definitely something to worry about if and only if you identify the code in question as being a performance bottleneck, which is really unlikely. It's micro-optimization. Function calls are really, really fast even if they don't get optimized out by the JavaScript engine. I used to worry about function call overhead when Array#forEach first appeared on the scene. Even back then, it wasn't an issue, even on the oldest, slowest JavaScript interpreter I could find: The one in IE6. Details on my blog: foreach and runtime cost
Re whether it takes longer... How long is a piece of string? It totally depends on the JavaScript engine you're using and whether the code in question is identified as a "hot" spot by the engine (assuming it's an engine like V8 that works in stages and optimizes hot spots).
A modern engine is likely to inline that if it becomes important to do so. That is not a guarantee.
Or is it negligible and micro-optimising?
It's negligible and micro-optimizing.
If you want to check if something's a number, I recommend using an isNaN check and then casting to a number.
if (!isNaN(myVar)) {
myVar = +myVar;
}
In this way, you don't actually care how the value gets treated as a number.
Someone using the API could then choose to pass an object that can be treated as a number:
myVar = {
valueOf: function () {
return 5;
}
};
Related
I was doing some benchmarking and found some absurd results that I cant seem to explain.
const a = undefined;
const b = {};
// add tests
suite
.add('Undefined variable', function () {
if(a > 0){
return true;
}
else{
return false;
}
})
.add('Undefined property', function () {
if(b.a > 0) {
return true;
}
else{
return false;
}
})
Test Results:
Undefined variable x 69,660,401 ops/sec ±2.48% (36 runs sampled)
Undefined property x 994,939,175 ops/sec ±0.85% (40 runs sampled)
Test Results
--------------------------------------------------------------------------
Undefined property : 994939174.67 ops/sec (+1328.27 %)
Undefined variable : 69660400.51 ops/sec ( +0.00 %)
--------------------------------------------------------------------------
Anyone have any idea why the first case Undefined variable is so much slower than the other one ?
I found similiar performance results on a jsbench test : https://jsbench.me/vdku4ert4l/2
(V8 developer here.)
Comparing undefined > 0 always has the same performance. The difference here is that in one of your cases, V8 can optimize away the comparison: for a property access like b.a, it remembers the hidden class of the object(s) seen (i.e. the values of b); that's the key idea of the technique called "inline caching".
V8 takes this idea one step further: if all encountered objects had the same hidden class, and that hidden class didn't have an a property, then when that function gets optimized, V8 takes that experience into account and produces optimized code that assumes that this will still be the case in the future, which in this case enables it to constant-fold away the property load and the comparison. In other words, it optimizes that function to something like:
function undefined_property_optimized() {
(if b.__hidden_class__ !== kPreviousHiddenClass) Deoptimize;
return false;
}
Where Deoptimize means: throw away this optimized code and go back to unoptimized code for this function (resuming execution exactly at the right point, of course).
the first test Undefined variable is being heavily slowed down
No, it's not being slowed down at all. The other case is "cheating", so to speak.
adding const b = { a: undefined }; doesn't change anything
That actually depends a lot on how exactly you run the test. In local testing, with minor modifications to what I force the engine to do, this addition either has no effect, or makes both functions have equal speed.
Rule of thumb #1: when you run a microbenchmark and you see several hundred million operations per second, then the optimizing compiler was able to optimize away pretty much everything, and you're testing an empty (or trivial) function.
Rule of thumb #2: the results of microbenchmarks are difficult to interpret correctly. You may have thought you were measuring property loads here, or > 0 comparisons; both assumptions would be incorrect: in the faster case, there are no properties being loaded and no > 0 comparisons being performed. To make sense of a microbenchmark, you really need to study the generated machine code (and/or other engine internals), to make sure it's testing what you think it's testing.
Rule of thumb #3: modern high-performance JavaScript engines are incredibly complex beasts, and the same snippet of JS will not always have the same performance; it depends heavily on the code around it (both the immediately surrounding lines, and far-away code elsewhere in your app can affect it).
Rule of thumb #4: the results of microbenchmarks almost never carry over to real-world code -- mostly because of the above three rules :-)
Side note: when you find yourself writing:
if (some_condition) {
return true;
} else {
return false;
}
then you can just replace that with return some_condition. Probably won't be faster, but makes your code shorter.
I have been looking through the polyfill implementations on the Mozilla Developer Network (MDN) as I require a few of these for a library. I know shim.js exists, but I'm not using that.
It seems that the polyfills are not consistent in code styling. It almost appears that they are written by the community in an almost "wiki" style.
Take for example String.prototype.contains
if(!('contains' in String.prototype)) {
String.prototype.contains = function(str, startIndex) {
return -1 !== String.prototype.indexOf.call(this, str, startIndex);
}
}
it seems more logical to me to implement this as such:
if(!String.prototype.contains) {
String.prototype.contains = function(str, startIndex) {
return this.indexOf(str, startIndex) !== -1;
}
}
Given that JavaScript is a size critical language (in that everything should be as small as possible for network transmission), my example should be favourable to the example on MDN as this saves a few bytes.
As the title suggests, I want to know how reliable the code is on MDN, and should I modify this as necessary to provide really clean, tiny implementations where possible?
It seems that your question refers to the article on String.contains().
Yes, MDN is a wiki so the quality of its content (including code examples) can vary. However, the content on general web topics (as opposed to extension development for example) is usually pretty good. Still, you shouldn't forget to use common sense.
The polyfill suggested on MDN and your version differ in three points:
!('contains' in String.prototype) vs. !String.prototype.contains to check whether a property exists: The former is clearly preferable. The in operator merely looks up a property, there are no side-effects. !String.prototype.contains on the other hand will actually retrieve the value of that property and convert it to a boolean value. Not only is this marginally slower, some property values like 0 will be wrongly coerced to false. You probably won't notice the difference with functions but this might become a real issue when polyfilling other property types.
-1 !== foo vs. foo !== -1 for comparisons: This is a matter of taste but some people prefer the former variant. The advantage of always putting the constant first in comparisons is that you won't unintentionally turn a comparison into an assignment: writing -1 = foo when you meant -1 == foo will cause an error. On the other hand, foo = -1 instead of foo == -1 will succeed and noticing that issue in your code might take a while. Obviously, if you choose to adapt that style you need to use it consistently throughout all your code.
String.prototype.indexOf.call vs. this.indexOf: The former guards against the situation that the indexOf method on the this object is overwritten. As a result, it is closer to the behavior of the native String.contains() function. Consider this example:
var a = "foo";
a.indexOf = function() {something_weird};
alert(a.contains("f"));
The native implementation of String.contains and a polyfill using String.prototype.indexOf.call will work even if this.indexOf is overwritten - a polyfill using this.indexOf however will fail.
Altogether, the code provided on MDN has a few more fail-safes. Whether these are required in your individual scenario is not given of course. However, dropping them to save a few bytes is the wrong approach to optimization ("premature optimization is the root of all evil"). Personally, I prefer good style over efficiency unless the difference in performance is known to be relevant.
EDIT: Based on everyone's feedback, the original version of this question is more design-related, not standards-related. Making more SO-friendly.
Original:
Should a JS primitive be considered "equivalent" to an object-wrapped version of that primitive according to the ECMA standards?
Revised Question
Is there a universal agreement on how to compare primitive-wrapped objects in current JavaScript?
var n = new Number(1),
p = 1;
n === p; // false
typeof n; // "object"
typeof p; // "number"
+n === p; // true, but you need coercion.
EDIT:
As #Pointy commented, ECMA spec (262, S15.1.2.4) describes a Number.isNaN() method that behaves as follows:
Number.isNaN(NaN); // true
Number.isNaN(new Number(NaN)); // false
Number.isNaN(+(new Number(NaN))); // true, but you need coercion.
Apparently, the justification for this behavior is that isNaN will return true IF the argument coerces to NaN. new Number(NaN) does not directly coerce based on how the native isNaN operates.
It seems that the performance hit and trickiness in type conversion, etc, of directly using native Object Wrappers as opposed to primitives outweighs the semantic benefits for now.
See this JSPerf.
The short answer to your question is no, there is no consensus on how to compare values in JS because the question is too situational; it depends heavily on your particular circumstances.
But, to give some advice/provide a longer answer .... object versions of primitives are evil (in the "they will cause you lots of bugs sense", not in a moral sense), and should be avoided if possible. Therefore, unless you have a compelling reason to handle both, I'd suggest that you do not account for object-wrapped primitives, and simply stick to un-wrapped primitives in your code.
Plus, if you don't account for wrapped primitives it should eliminate any need for you to even have an equals method in the first place.
* Edit *
Just saw your latest comment, and if you need to compare arrays then the built-in == and === won't cut it. Even so, I'd recommend making an arrayEquals method rather than just an equals method, as you'll avoid lots of drama by keeping your function as focused as possible and using the built-in JS comparators as much as possible.
And if you do wrap that in some sort of general function, for convenience:
function equals(left, right) {
if (left.slice && right.slice) { // lame array check
return arrayEquals(left, right);
}
return left == right;
}
I'd still recommend against handling primitive-wrapped objects, unless by "handle" you make your function throw an error if it's passed a primitive-wrapped object. Again, because these objects will only cause you trouble, you should strive to avoid them as much as possible, and not leave yourself openings to introduce bad code.
I just read through this article on named function expressions and their incompatibilities with IE <= 8.
I'm curious about one statement in particular:
A common pattern in web development is to “fork” function definitions based on some kind of a feature test, allowing for the best performance.
An example taken from his page:
var contains = (function() {
var docEl = document.documentElement;
if (typeof docEl.compareDocumentPosition != 'undefined') {
return function(el, b) {
return (el.compareDocumentPosition(b) & 16) !== 0;
};
}
else if (typeof docEl.contains != 'undefined') {
return function(el, b) {
return el !== b && el.contains(b);
};
}
return function(el, b) {
if (el === b) return false;
while (el != b && (b = b.parentNode) != null);
return el === b;
};
})();
When I see this, my immediate reaction is that this would be terrible to maintain. Code written this way doesn't really lend itself to being easily understandable.
In this case, instead of conditionally defining a function within another function which is then called immediately after the outer function is declared, one could write a function of nested ifs. It would be longer, but in my opinion easier to understand (though I am coming from C/C++/Java).
I would prefer answers that include some test numbers or explanations on how these functions would differ at run time.
It is very efficient. Notice the (); at the very end. This executes and assigns the result of the outer function to contains immediately. It is much more efficient than executing the underlying logic every time that the function contains is used.
Instead of checking each time contains() is called that compareDocumentPosition exists, this is done once when the code first executes. The fact that compareDocumentPosition exists or doesn't exist won't change, so only checking it once is ideal.
Javascript: how much more efficient is forked function declaration?
Barring any magic optimization done with a JIT/run-time it "costs" the same to invoke any function. Functions are just objects that are often stored in variables (or properties).
How much more "efficient" the version that returns a specialized function-object is depends upon factors including (but not limited to):
the number of times the resultant function is executed (1x = no gain) and
the "cost" of the branch vs. other code (depends) and
the "cost" of creating said closure (very cheap)
For a cheap branch or a low number of execution counts the "efficiency" is diminished. If there is a specific use-case, then benchmark that and you will have "the answer".
When I see this, my immediate reaction is that this would be terrible to maintain. Code written this way doesn't really lend itself to being easily understandable.
This example doesn't necessarily do it justice, IMOHO and is messy for other reasons. I think that giving the anonymous outer function an explicit name -- this can be done even for function-expressions -- would help clarify the intent better, for instance. Write code to be clean first. Then run a performance analysis (benchmark) and fix as appropriate. Chance are the "slow parts" won't be what are initially expected.
Some of it "not being easy to understand" is just a lack of familiarity with this construct (not trying to imply anything negative here) -- on the other hand, every language I know of has features which are abused in cases where there are cleaner solutions.
In this case, instead of conditionally defining a function within another function which is then called immediately after the outer function is declared, one could write a function of nested ifs. It would be longer, but in my opinion easier to understand (though I am coming from C/C++/Java).
Again, the exact case is sort of messy, IMOHO. However, JavaScript is not C/C++/Java and functions-as-first-class-values and closures do not exist in C/C++/Java (this is a little white lie, closures can be emulate in Java and the newest C++ supports some form of closures AFAIK -- but I don't use C++).
This construct is thus not seen in those other languages because the other languages do not support it easily (or at all) -- it says nothing about the viability of the approach (in JavaScript or elsewhere) in general.
I would prefer answers that include some test numbers or explanations on how these functions would differ at run time.
See above.
Expanding upon the bold section at top:
A function is "just an object" that is "applied" (read: called) with the (...) operator.
function x () {
alert("hi")
}
x() // alerts
window.x() // alerts -- just a property (assumes global scope above)
a = {hello: x}
a.hello() // alerts (still property)
b = a.hello
b() // alerts (still just a value that can be invoked)
Happy coding.
The main advantage as mentioned is speed. Having a single function with nested ifs means the condition needs to be re-evaluated every time the function is called. However, we know that the results of the conditions will never change.
If you are concerned about readability, a similar effect can be achieved in a more readable way:
var contains = (function () {
var docEl = document.documentElement;
if (typeof docEl.compareDocumentPosition != 'undefined') {
return contains_version1;
} else if (typeof docEl.contains != 'undefined') {
return contains_version2;
} else {
return contains_version3;
}
function contains_version1() {
...
}
function contains_version2() {
...
}
function contains_version3() {
...
}
})();
Or:
(function () {
var docEl = document.documentElement;
var contains =
typeof docEl.compareDocumentPosition != 'undefined' ? contains_version1 :
typeof docEl.contains != 'undefined' ? contains_version2 :
contains_version3;
function contains_version1() {
...
}
function contains_version2() {
...
}
function contains_version3() {
...
}
})();
This is relatively strange construct if you are coming from pure C background, but should be easily to map to known concepts for C++/Java person. This particular sample is essentially implementation base class with abstract function with 3 derived classes implementing it differently for different browsers. Using "if" or "switch" for such case is not exactly the best approach in either C++ nor Java.
Likely set of such functions will be packaged into a "class" and in such case it will closely map to base class with virtual functions and multiple implementations for each browser...
As a rule of thumb, which of these methods of writing cross-browser Javascript functions will perform better?
Method 1
function MyFunction()
{
if (document.browserSpecificProperty)
doSomethingWith(document.browserSpecificProperty);
else
doSomethingWith(document.someOtherProperty);
}
Method 2
var MyFunction;
if(document.browserSpecificProperty) {
MyFunction = function() {
doSomethingWith(document.browserSpecificProperty);
};
} else {
MyFunction = function() {
doSomethingWith(document.someOtherProperty);
};
}
Edit: Upvote for all the fine answers so far. I've fixed the function to a more correct syntax.
Couple of points about the answers so far - whilst in the majority of cases it is a fairly pointless performance enhancement, there are a few reasons one might want to still spend some time analyzing the code:
Has to run on
slow computers, mobile devices, old
browsers etc.
Curiosity
Use the same
general principal to performance
enhance other scenarios where the
evaluation of the IF statement does
take some time.
Unless you're doing this a trillion times, it doesn't matter. Go with the one that is more readable and maintainable to you and/or your organization. The productivity gains you will get from writing clean, simple code matters way more than shaving a tenth of a microsecond off your JS execution time.
You should only even start thinking about what performs better when and only when you've written code and it is unacceptably slow. Then you should start tracking down the bottleneck, which will never be something like this. You will never get a measurable performance gain out of switching from one to the other here.
Unfortunately the code above is not actually cross-browser friendly as it relies on a mozilla quirk not present in other browsers -- namely that function statements are treated as function expressions inside branches. On browsers other that aren't built on mozilla the above code will always use the second function definition. I made a simple testcase to demonstrate this here.
Basically the ECMAScript spec says that function statements are treated similarly to var declarations, eg. they all get hoisted to the top of the current execution scope (eg. the start of a <script> tag, the start of a function, or the start of an eval block).
To clarify olliej's answer, your second method is technically a syntax error. You could rewrite it this way:
var MyFunction;
if(document.browserSpecificProperty) {
MyFunction = function() {
doSomethingWith(document.browserSpecificProperty);
};
} else {
MyFunction = function() {
doSomethingWith(document.someOtherProperty);
};
}
Which is at least correct syntax, but note that MyFunction would only be available in the scope in which that occurs. (Omit var MyFunction;, and preferably use window.MyFunction = function() ... for global.)
Technically, I would say that the second one would perform better, because the if statement is only executed once, rather than every time the function is run.
The difference, however, would be negligible to the point of being meaningless. The performance penalty of a single if statement such as this would be insignificant even compared to the performance penalty of simply calling a function. It would make a smallish difference even if if is called a million times.
The first one is easier to understand, because it doesn't have the awkwardness of defining the same function twice based on a condition, with both versions behaving differently. That seems to be a recipe for confusion later on.
I wouldn't be the first person to say that unless you are really insane about this optimization thing, you'll get more of a win out of code readability.
I generally prefer the second version, as the condition only has to be evaluated once and not on every call, but there are times when it's not really feasible because it will hamper readability.
Btw, this is a case where you might want to use the ?: operator, e.g (taken from production code):
var addEvent =
document.addEventListener ? function(type, listener) {
document.addEventListener(type, listener, false);
} :
document.attachEvent ? function(type, listener) {
document.attachEvent('on' + type, listener);
} :
throwError;
For your simplified example I would do what's below assuming that your browser property check only needs to be done once:
var MyFunction = (function() {
var rightProperty = document.browserSpecificProperty || document.someOtherProperty;
return function doSomethingWith() {
// use the rightProperty variable in your function
}
})();
The performance should be nearly equal!
Thing about using Frameworks like JQuery to get rid of the Browser compability problems!
If performance is your main goal, have a look at SlickSpeed! It is a page which benchmarks different JavaScript frameworks!