If you actually throw and catch an exception, it might be slower but since most of the time there are no exceptions, the overall result is faster with exceptions. This is because there are no branches in control flow that would slow things down.
The micro benchmark in the original article is meaningless. This should be measured in a real-world situation where the catch is 5-10 levels up from the throw, and there are a lot more throws than catches.
Your "not surprising" result is only valid in Chrome and Opera. Other browsers are faster at try/catch.
On the other hand, try/catch requires traversing some kind of structure to find the catch handler, and exceptions are often allocated somehow. This kind of action will need to inspect the stack, possibly look at the heap, and probably do many branches.
Plus, try/catch is not typically optimized for speed of catching exceptions. Exception handling is typically optimized so that the code path that doesn't throw an exception is almost as fast as it would be if the exception handling weren't there. You want people to use your exception handling so they can write more error-tolerant programs, but they might throw it out if it slows down their correct code. If you make sure you aren't slowing down the non-exception path, you may have to make tradeoffs that slow down the exception path.
The programming language shootout had a test of try/catch performance across languages. I remember Lisp was at the top, but not as if anyone cares -- try/catch performance isn't relevant to most programs.
OTOH, you may find it interesting that the reverse is true in Python. In Python, it is almost always faster to catch an exception rather than to check first. The way CPython checks for errors is by checking the return value of functions against NULL, after all, which is very fast. Checking ahead of time requires more Python code, and the Python code is going to be the slow part, at least on CPython.
- Edit -
Just tried it, it's not even close (on FF4):
tryCatch with undef - ~55,000
ifCheck with undef - ~2,000,000
tryCatch with Object - ~100,000,000
ifCheck with Object - ~2,000,000
So if an error is not thrown the try/catch expression is WAY faster.
Try/catch is also a very complicated flow control mechanism (think about how try/catch/finally/return all mesh together) such that a lot of VMs simply don't even attempt to apply any of their fancy optimizations to any function that contains a try/catch.
It seems they are doing a good work.
The latest revision (35, as of this comment) is basically equivalent from most JS engines' perspective, and shows pretty much identical results.
undefined = 1;
>>> 1
null = 1;
>>> ReferenceError: invalid assignment left-hand side
It looks like Chrome and Firefox no longer let you assign to window.undefined any, but I'm not sure is IE has the same restrictions. The correct way to check for undefined is via `typeof`.