Silly Coding Tricks: “Inverted” String Match

First things first: Never actually do this. This is just a fun curiosity, for amusement value only.

Because of the way JavaScript’s search() method works, you can do:

var my_url = '';
if (!\/\/ {
    alert("Your URL is");
} else {
    alert("Nope, your URL isn't");

Try running this, and it will correctly claim that “Your URL is” — even though there’s a ! at the beginning of the test. What gives?

That exclamation point looks like it’s saying: “If the search for within the given string fails…” But what that test is really saying is: “If the search for returns Boolean false — or anything that evaluates as Boolean false…”

What that search() call actually returns is the character index at which the needle is found, or -1 if it isn’t found. Since the needle is found at the very beginning of the haystack — at character index 0 — search() returns zero. Which evaluates to false in a Boolean context.

If the needle isn’t found, the search will return -1 — which evaluates as true in a Boolean context!

Effectively, the ! operator is reconciling the disagreement between search()’s idea of falsehood and if()’s idea of falsehood: search() returns -1 for a false result (a failed match), but if() considers -1 to be true, not false.

This trick only works with needles that you are sure will only occur at the beginning of the haystack.

Once again, you should never, ever actually write code like this for any serious purpose or in anything you intend to deploy in the real world. The maintainability problems are not worth the amusement of confusing all your co-workers with a test that looks reversed. Instead, use a positional anchor in your regex, and explicitly test against -1…

if (^http:\/\/ != -1)

…like any sensible JavaScript coder. (Yes, that last bit is intended to be ironic. I wrote something once about the silliness of having to add that extra test; I’ll have to see if I can find it and republish it here. )

Post a Comment

Your email is never shared. Required fields are marked *