This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
JavaScript === vs == : Does it matter which “equal” operator I use?
When comparing two operands of the same type for equality in JavaScript, using == or === doesn't make any conceptual difference, so I'm wondering which operator is actually faster when, like in my case, a JavaScript file has to be downloaded from a remote Internet location.
While the strict equality operator === may perform faster on many user agents, it also requires 8 more bits of uncompressed information to be carried along the network with the JavaScript file.
As it happens, today's average CPUs are much faster in executing several hundred conditional jumps than Internet connections are in delivering one single bit, so I'd be keen to using == instead of === and != instead of !== when possible. Yet I'm confused by reading so many blogs that recommend doing the opposite.
Is there any important point I'm missing?
As you say, for comparison where both operands are guaranteed to be of the same type, the two operators are specified to perform precisely the same steps and, barring compiler optimizations, are likely to perform near enough identically. Therefore there is a slight advantage in terms of file size in using == over === in those cases.
However, some people argue that consistency is more important: === is usually closer to what you intend when testing equality, and only using === and !== is something many people find helpful and readable. Personally, I have the opposite rule and only use === when there is uncertainty about the types of the operands, but I wouldn't recommend either way over the other.
If you understand the differences between strict and non-strict equality and you're confident that using == and != won't cause you or anyone else working your code any problems reading and understanding code in the future, go ahead and use them.
Presumably blogs that recommend one over the other are doing so for reasons of logical consistency with analogous operations and not for speed. Trying to trim your Javascript programs to point of shaving off individual characters from the script is unwise; running it through minify or another automated tool before serving is one thing, but hand-tuning Javascript for minimum file size or for execution speed on the level of individual operands is an endless, thankless task that will make your site harder to maintain.
Use whichever operand makes more logical sense to you, so you won't be confused when you don't remember this line of inquiry two years from now.
If I may quote from Douglas Crockford's Javascript: The Good Parts:
JavaScript has two sets of equality operators: === and !==, and their
evil twins == and !=. The good ones work the way you would expect.
If the two operands are of the same type and have the same value, then
=== produces true and !== produces false. The evil twins do the right thing when the operands are of the same type, but if they are of
different types, they attempt to coerce the values. The rules by
which they do that are complicated and unmemorable ... The lack of
transitivity is alarming. My advice is to never use the evil twins.
Instead, always use === and !==.
Whether there is a performance difference or not, it would be difficult to justify the use of the "evil twins".
var test="1";
console.log(test==1); // true
console.log(test===1); // false
== checks whether test has 1 or not but === checks whether test has 1 and also checks it's data type. In that case 2nd expression is false because it's data type is string (test is string) but the right hand operand is not string. The following test is different
var test=1;
console.log(test==1); // true
console.log(test===1); // true
Because test contains Integer 1 that evaluates to Boolean true and right hand operand is also same. === also checks whether both operands type.
Related
I am looking to see how some Javascript functions work under the hood. For e.g. I want to learn how Chrome's V8 Engine implements the Unary (-) operation or the String.prototype.toString() method.
How can I see the native C/C++ implementation? I have seen many answers here linking to the Chromium repository and the V8 repository, but these are giant and not very beginner friendly, and there aren't really any guides anywhere as far as I could find.
I'm looking for something like this:
// Pseudo code
function -(arg) {
return arg * -1
}
Obviously, I understand that I wouldn't find this written in Javascript. I'm just looking for a similar level of detail.
I'm yet to find an answer that concisely shows how to find the native implementation of Javascript functions anywhere. Could someone point me in the right direction?
The ECMA specs here give the following specs for the Unary - operation:
Unary - Operator
The unary - operator converts its operand to Number type and then
negates it. Note that negating +0 produces −0, and negating −0
produces +0.
The production UnaryExpression : - UnaryExpression is evaluated as
follows:
Let expr be the result of evaluating UnaryExpression. Let oldValue be
ToNumber(GetValue(expr)). If oldValue is NaN, return NaN. Return the
result of negating oldValue; that is, compute a Number with the same
magnitude but opposite sign.
This is quite useful, but what I'm trying to understand is, how
compute a Number with the same magnitude but opposite sign
Is calculated. Is it the number * -1 or something else? Or is it multiple ways?
There is no piece of code or single implementation of individual operators in V8. V8 is a just-in-time compiler that executes all JavaScript by compiling it to native code on the fly. V8 supports about 10 different CPU architectures and for each has 4 tiers of compilers. That already makes 40 different implementations of every operator. In many of those, compilation goes through a long pipeline of stages that transform the input to the actual machine code. And in each case the exact transformation depends on the type information that is available at compile time (collected on previous runs).
To understand what's going on you would need to understand a significant part of V8's complicated architecture, so it is pretty much impossible to answer your question in an SO reply. If you are just interested in the semantics, I rather suggest looking at the EcmaScript language definition.
(The snippet you cite is just a helper function for the converting compiler-internal type information for unary operators in one of the many stages.)
Edit: the excerpt from the EcmaScript definition you cite in the updated question is the right place to look. Keep in mind that all JavaScript numbers are IEEE floating point numbers. The sentence is basically saying that - just inverts the sign bit of such a number. You'd have to refer to the IEEE 754 standard for more details. Multiplication with -1.0 is a much more complicated operation, but will have the same result in most cases (probably with the exception of NaN operands).
While trying to fully understand the difference between equality operator and identity operator, I came across an article at MSDN that explains what they both do, in terms of their inner workings, but I still had a few doubts and decided to create a flowchart so I could have a better picture. Now my question is, is this flowchart correct? or am I missing something?
It's also my understanding that the identity operator (===) would work pretty much the same way, but without attempting to convert A and B to boolean, number or string, in the first step. Is that correct?
You can see the image here too:
Ok here is the real thing, it was a matter of principles ;)
is this flowchart correct?
No. You should use the ECMAScript specification for the Abstract Equality Comparison Algorithm to create the flowchart. ToBoolean is certainly not the first step (it's not used in any step).
or am I missing something?
Yes, a lot.
It's also my understanding that the identity operator (===) would work pretty much the same way, but without attempting to convert A and B to boolean, number or string, in the first step. Is that correct?
The Strict Equality Comparison Algorithm is almost identical to the Abstract Equality Comparison Algorithm, there is a difference only if the argument Types are different, and in that case there is a precise order in which the Types are made equal before the comparison is made.
is this flowchart correct?
No. Apart from being layouted terrible, it is misleading and partially wrong.
Am I missing something?
Yes. The first step, "try to convert A and B to boolean, string or number" is wrong - that's not the first step in the equality comparison algorithm. Also, when to convert which of the variables to which type?
Then, the next step should be a type distinction, instead of repeatedly asking for identical values of a specific type.
The "last" step "Can they (the types) be coerced into any of the last 5 situations? -> Coerce types" lacks detail. All the detail. Which is the most relevant part of the sloppy equality comparison:
Which types can be coerced?
What types would be coerced to which?
How does the coercion of the values work?
And no, after the coercion the algorithm pretty much starts at the beginning, not with the question about strings.
It's also my understanding that the identity operator (===) would work pretty much the same way, but without attempting to convert A and B to boolean, number or string, in the first step.
That first step is not apparent in the actual algorithm, so No. In fact, === works the same except the last step, which coerces values into other types - instead, false is returned.
Edit: Your second diagram is accurate (correct), although it still features some odd layout decisions.
I'm trying to figure out how my script will behave if rendered in a browser using Chinese (or other) locale using Chinese numerals (or another non-Latin symbol set). Can't seem to find any info on this on the interwebs.
Looking at the page
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toLocaleString
we see examples of localized numbers when converting from number to string, but what about the other way around? I tried parseInt("一二三") in IE11 debug console which returned NaN, but I'm not using Chinese Windows. Could someone test this?
My confusion comes from JavaScript having loosely typed data, so what if I end up running into an implicit string-to-number conversion, such as this:
var a = "١٢٣";
var b = .01;
console.log(a*b);
Mind you my variables a and b could come from user input in a more complex example. How can you make sure that input coming from a non-Latin symbology is converted to the right number-representation internally before you do arithmetic if parseInt and implicit conversion don't work?
It won't work for several reasons. Notice firstly that while there is a toLocalString but there is no parseLocalStringInt or fromLocaleString. Secondly javascript only really does implicit type coercion when particular operators are used e.g. ==. * however can't be used in this fashion and even == and other operators only support very limited coercion in comparison with what you are describing.
This coercion can still be very dangerous or useful depending on your point of view e.g.
0 == false is true
but 0 === false is false but it certainly isn't as powerful and you think it is.
I'd like to write a little library for JavaScript enums. For me to do that, I need to decide how to store the enum values. Therefore, I'd like to use the fastest way when comparing, but I also want something that is debuggable, so I'm torn between using strings or numbers. I know I could use objects too, but that would be another question
For example
// I don't want this because when debugging, you'd see just the value 0
var Planets = {Earth:0, Mars:1, Venus: 2}
// I'd prefer this so that Planets.Earth gives me a nice readable value ("Earth")
var Planets = {Earth: 'Earth', Mars: 'Mars'}
But I'm afraid that when I compare them using if (myPlanet === Planet.Earth), the string comparison could take a lot longer (say if it were in a tight loop). This should be the case because http://ecma-international.org/ecma-262/5.1/#sec-11.9.6 says
If Type(x) is String, then return true if x and y are exactly the same sequence of characters (same length and same characters in corresponding positions); otherwise, return false.
But when I wrote a test case, I found that they take the same amount of time http://jsperf.com/string-comparison-versus-number-comparison/2 so it doesn't seem like it's scanning the whole string.
I know this could be a micro optimization, but my question is: is string equality comparison done using pointers and therefore just as fast as number equality comparison?
String comparison could be "just as fast" (depending on implementation and values) - or it could be "much slower".
The ECMAScript specification describes the semantics, not the implementation. The only way to Know for Certain is to create an applicable performance benchmark on run it on a particular implementation.
Trivially, and I expect this is the case1, the effects of string interning for a particular implementation are being observed.
That is, all string values (not String Objects) from literals can be trivially interned into a pool such that implIdentityEq("foo", "foo") is true - that is, there need only one string object. Such interning can be done after constant folding, such that "f" + "oo" -> "foo" - again, per a particular implementation as long as it upholds the ECMAScript semantics.
If such interning is done, then for implStringEq the first check could be to evaluate implIdentityEq(x,y) and, if true, the comparison is trivially-true and performed in O(1). If false, then a normal string character-wise comparison would need to be done which is O(min(n,m)).
(Immediate falseness can also be determined with x.length != y.length, but that seems less relevant here.)
1 While in the above I argue for string interning being a likely cause, modern JavaScript implementations perform a lot of optimizations - as such, interning is only a small part of the various optimizations and code hoistings that can (and are) done!
I've created an "intern breaker" jsperf. The numbers agree with the hypothesis presented above.
If a string is interned then comparison is approximate in performance to testing for "identity" - while it is slower than a numeric comparison, this is still much faster than a character-by-character string comparison.
Holding the above assertion, IE10 does not appear to consider object-identity for pass-fast string comparisons although it does use a fast-fail length check.
In Chrome and Firefox, two intern'ed strings which are not equal are also compared as quickly as two that are - there is likely a special case for comparing between two different interned strings.
Even for small strings (length = 8), interning can be much faster. IE10 again shows it doesn't have this "optimization" even though it appears to have an efficient string comparison implementation.
The string comparison can fail as soon as the first different character is encountered: even comparing long strings of equal length might only compare the first few characters.
Do common JavaScript implementations use string interning? (but no references given)
Yes. In general any literal string, identifier, or other constant string in JS source is interned. However implementation details (exactly what is interned for instance) varies, as well as when the interning occurs
See JS_InternString (FF does have string interning, although where/how the strings are implicitly interened from JavaScript, I know not)
There are cases when string comparison can be much slower (comparing dynamically generated strings)
The following is 77% slower (in chrome and IE) than all the other tests
var StringEarth = 'Ear' + 'th';
for (var i = 0; i < ITERATIONS; i++) {
x = StringPlanets.Venus === StringEarth;
}
The flaw in the tests mentioned in the question is the fact that we are testing against literal strings. It seems that JavaScript is optimized so that string comparison for string literals is done just by testing a pointer. This can be observed by creating the strings dynamically. My best guess is that strings from the literal string pool are marked so that they can be compared using addresses only.
Note that string comparison seems just as fast in FF even for dynamic strings. Also, that it's just as slow for even literal strings.
Conclusion All browsers behave differently so string comparison may or may not be slower.
In general, at best String interning (making a string with a given value into a unique reference or a O(1) comparable symbol) is going to take O(n) time, as it can't do that effectively without looking at all the characters involved.
The question of relative efficiency then amounts to over how many comparisons the interning is going to be amortized.
In the limit, a very clever optimizer can pull out static expressions which build up strings and intern them once.
Some of the tests above, use strings which will have been interned in which case the comparison is potentially O(1). In the case where enums are based on mapping to integers, it will be O(1) in any implementation.
The expensive comparison cases arise when at least one of the operands is a truly dynamic string. In this case it is impossible to compare equality against it in less than O(n).
As applied to the original question, if the desire is to create something akin to an enum in a different language, the only lookout is to ensure that the interning can is done in only a few places. As pointed out above, different Browser use different implementations, so that can be tricky, and as pointed out in IE10 maybe impossible.
Caveat lacking string interning (in which case you need the integer version of the enum implementation give), #JuanMendes' string-based enum implementations will be essentially O(1) if he arranges for the value of the myPlanet variable to be set in O(1) time. If that is set using Planets.value where value is an established planet it will be O(1).
What I'm doing is creating a truth table generator. Using a function provided by the user (e.g. a && b || c), I'm trying to make JavaScript display all combinations of a, b and c with the result of the function.
The point is that I'm not entirely sure how to parse the function provided by the user. The user could namely basically put everything he wants in a function, which could have the effect of my website being changed etc.
eval() is not secure at all; neither is new Function(), as both can make the user put everything to his liking in the function. Usually JSON.parse() is a great alternative to eval(), however functions don't exist in JSON.
So I was wondering how I can parse a custom boolean operator string like a && b || c to a function, whilst any malicious code strings are ignored. Only boolean operators (&&, ||, !) should be allowed inside the function.
Even if you check for boolean expressions, I could do this:
(a && b && (function() { ruinYourShit(); return true; })())
This is to illustrate that your problem is not solvable in the general case.
To make it work for your situation, you'd have to impose severe restrictions on variable naming, like requiring that all variables are a single alphabet letter, and then use a regular expression to kick it back if anything else is found. Also, to "match" a boolean expression, you'd actually have to develop a grammar for that expression. You are attempting to parse a non-regular language (javascript) and therefore you cannot write a regular expression that could match every possible boolean expression of arbitrary complexity. Basically, the problem you are trying to solve is really, really hard.
Assuming you aren't expecting the world to come crashing down if someone ruins your shit, you can develop a good enough solution by simply checking for the function keyword, and disallowing any logical code blocks contained in { and }.
I don't see the problem with using eval() and letting the user do whatever (s)he wants, as long as you have proper validation/filters on any of your server-side scripts that expect input. Sure, the user could do something that ruins your page, but (s)he can do that already. The user can easily enough run any javascript (s)he wants on your page already, using any number built-in browser features or add-ons.
What I would do would be to first split the user input into tokens (variable names, operators and possibly parentheses for grouping), then build an expression tree from that and then generate the relevant output from the expression tree (possibly after running some simplification on it).
So, say, break the string "a & !b" into the token sequence "a" "&" "!" "b", then go through and (eventually) build something like: booland(boolvar("a"), boolnot(boolvar("b"))) and you then have a suitable data structure to run your (custom, hopefully injection-free) evaluator over.
I ended up with a regular expression:
if(!/^[a-zA-Z\|\&\!\(\)\ ]+$/.test(str)) {
throw "The function is not a combination of Boolean operators.";
return;
}