So I'm profiling along, and I find an anonymous function that is being called a number of times. It doesn't cost a lot, but I'm curious why it is anonymous. It's not really anonymous, because our compiler assigns a debugging name to anonymous functions that you can use to find them in the source. Here's the anonymous function:

  static var _ignoreAttribute = {toString: function () {
      return '_ignoreAttribute'}};

_ignoreAttribute is just a unique sentinel object that we use as a way to indicate that an attribute has already been processed, deep in the inner workings of LZX. Someone (probably me) graciously gave it a `toString` method, so that when you are debugging and trip across it, you will realize that it is not just any old empty object.

But I'm not debugging. I'm profiling. I'm not calling `_ignoreAttribute.toString()`. It's nowhere in the source code that I can see. What is going on? Well, here's a problem:

    if (null != this.datapath && dp != LzNode._ignoreAttribute) {
      this.datapath.setXPath(dp);
    } else {

Can you spot it? When `dp != LzNode._ignoreAttribute` runs, `dp` is normally a string, and read the fine print for how equality is computed in Javascript (from p. 64 of "ECMAScript Language Specification Edition 3"):

1. If Type(x) is different from Type(y), go to step 14.
[...]
20. If Type(x) is either String or Number and Type(y) is Object,
return the result of the comparison x == ToPrimitive(y).

Well, I won't bore you with more gory details, but the bottom line is, every time we compare `_ignoreAttribute` to a String, the runtime has to call its `toString` method to see if it is "equal".

The storal of the morey is, when you want to compare for "identity", use the "strict equals operator" (`===` or `!==`), not the "equals operator". [For my money, the former should have just been called the "identity" operator, but unfortunately it isn't quite. There are some odd edge cases that make it not a _true_ identity operator.]

Reply via email to