Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is Javascript's "in" operator consistently slower than strict member comparison to undefined?

Tags:

javascript

See http://jsperf.com/in-vs-member-object-access

Essentially, why is checking if ('bar' in foo) {} significantly slower than if (foo.bar !== undefined) {}?

like image 876
Brian Cray Avatar asked Dec 13 '12 18:12

Brian Cray


People also ask

Why === is faster than ==?

So === faster than == in Javascript=== compares if the values and the types are the same. == compares if the values are the same, but it also does type conversions in the comparison. Those type conversions make == slower than ===.

When using the strict equality operator to compare objects How do they compare?

The strict equality operator ( === ) checks whether its two operands are equal, returning a Boolean result. Unlike the equality operator, the strict equality operator always considers operands of different types to be different.

Why do we prefer === and !== Over == and != In JavaScript?

This is because the equality operator == does type coercion, meaning that the interpreter implicitly tries to convert the values before comparing. On the other hand, the identity operator === does not do type coercion, and thus does not convert the values when comparing.

Is undefined === undefined true?

undefined == undefined is true.


2 Answers

foo.bar !== undefined checks just those 2 values to see if they match.

While 'bar' in foo will have to use some mechanism to loop through the properties of foo to see if bar is in it.

Here is an interesting Read from Ecma-script

The in operator

The production RelationalExpression : RelationalExpression in ShiftExpression is evaluated as follows:
1. Evaluate RelationalExpression.
2. Call GetValue(Result(1)).
3. Evaluate ShiftExpression.
4. Call GetValue(Result(3)).
5. If Result(4) is not an object, throw a TypeError exception.
6. Call ToString(Result(2)).
7. Call the [[HasProperty]] method of Result(4) with parameter Result(6).
8. Return Result(7).

The Strict Does-not-equal Operator ( !== )

The production EqualityExpression : EqualityExpression !== RelationalExpression is evaluated as follows:
1. Evaluate EqualityExpression.
2. Call GetValue(Result(1)).
3. Evaluate RelationalExpression.
4. Call GetValue(Result(3)).
5. Perform the comparison Result(4) === Result(2). (See below.)
6. If Result(5) is true, return false. Otherwise, return true.

like image 129
Ibu Avatar answered Oct 01 '22 11:10

Ibu


You're right. It makes no sense for "bar" in foo to be slower than foo.bar.

The only reason in isn't just as fast is that it hasn't received as much attention from JIT engineers as the much more common foo.bar syntax.

Especially in the case in your jsperf test, where the property does exist as a direct property on foo itself (not a prototype), it stands to reason that 'bar' in foo shouldn't be any slower than foo.bar !== undefined. If anything, it should be faster. The main difference between the two is that in can be answered without even checking the value of the property!

In the foo.bar case, I expect both the V8 engine and the SpiderMonkey engine will detect that the code isn't doing anything useful (that is, it has no observable effects) and optimize it away entirely. The benchmark isn't measuring any actual work.

Apparently engines are not yet smart enough to optimize away "bar" in foo, but it's only a matter of time. And priorities.

like image 20
Jason Orendorff Avatar answered Oct 01 '22 11:10

Jason Orendorff