Showing posts with label ecmascript. Show all posts
Showing posts with label ecmascript. Show all posts

Saturday, October 13, 2007

Type-Converting Operator Considered Ridiculous

I have come to question the wisdom of the type-converting == operator in JavaScript. The algorithm (defined in §11.9.3 of the ECMA-262 v3 spec) requires no fewer than 22 steps to execute, and produces such amazing intrasitivities as:

>>> '0' == 0
true

>>> 0 == ''
true

>>> '' == '0'
false

and random quirkiness such as:

>>> ' \t\r\n' == 0
true

but:

>>> null == 0
false

>>> null == false
false

>>> null == ''
false

>>> null == undefined
true

Do these behaviors strike anyone else as, well, a bit off? In the first example (discussed elsewhere) the intransitivity of the equality operator is a result of wanting an equality operator to play well within a weakly-typed language. If you want to be able to compare numbers to their string representations as though they were of the same type, while still preserving string comparison, this is the logical result. The second example is a result of the ToNumber algorithm, described in §9.3ff. The whitespace conversion to number value 0 is strange, but defined in the spec (in fact, it's a result of the same algorithm that dictates Number(' ') => 0). The third example seems bizarre as well; I'm not sure why null would be treated differently than 0 or false, but the same as undefined, in such expressions. Many articles from otherwise reputable sources often describe all of these values in terms of "truthiness" and "falsiness", but these articles sometimes gloss over these distinctions.

I don't condone transitioning JS into a strongly-typed system, but some of these behaviors are quite subtle. Given the fact that the vast majority of JavaScript programmers seem to be unaware of the strict-equality operator === (and its negative counterpart, !==), it's no wonder behaviors such as these can cause confusion. See also this article for even more pitfalls, this time simply with math operators combining string and numeric types.

So as Crockford says, use the strict comparison operator === unless you know what you're doing.

Saturday, June 23, 2007

Crockford's revisions to ECMAScript

The ECMAScript standard is undergoing growing pains right now, and for the first time since 1999, it looks like major revisions to the language may take effect soon. Douglas Crockford has recommendations of his own. While I don't have any strong feelings about the new features he requests (they can mostly be implemented in the JavaScript we already have), his Corrections are mostly sane things that will remove a lot of the suckiness from the current standard:

  1. Reserved words
  2. Standardize implementation of trailing commas in object literals and arrays
  3. Make arguments object a true array
  4. Tail recursion optimization
  5. Deprecate primitive type wrappers, the with statement, semicolon insertion, arguments.callee, typeof, and eval.

It looks like Brendan Eich is well aware of Crockford's longstanding laments, particularly against the with statement and the reserved words restrictions, and has addressed them in the draft spec for ECMA-262 v4.

Crockford objects to restricting the use of reserved keywords in object definitions as unnecessary. According to his argument, usage such as:

var o = {
    class: 'style', 
    with: function (n) { return n+'a top hat'; }
};

will preserve the original use of these names, as the names are merely being used for scoped member properties; they cannot be confused in this context, syntactically, with the "official" uses of these keywords. (This is, apparently, why the JSON spec requires double-quoted property names.) However, it seems this restriction is in place mainly to make possible the use of the with keyword; consider:

with (o) {
   class = 'none';
   with(class);
}

If using these keywords were legal above, their use with the with statement here invites syntax hell.

I for one would be happy to see the demise of the with keyword. It breaks with JavaScript's function-level scoping, and creates more problems than it's meant to solve. It "feels" uncharacteristic of the language, since it promotes an object's properties from "property" status into "variable" status, blending them indiscriminately into the surrounding scope. JavaScript has enough trouble affording decent namespacing as it is; this "feature" smacks of bad practice.

More than adding new features, we could use a "trimming-down" phase to the language. While Mozilla toils at turning JavaScript into Python and other power-players at ECMA (presumably MS?) seek to remake the spec in the image of Java or C#, I'm mostly happy with the way it is - just please, for God's sake, fix the problems that are currently there before bounding into a new round of ill-conceived feature bloat.

We front-end developers are lucky to be enjoying a golden age of JavaScript. But the clouds of confusion and incompatibility are on the horizon. I don't see a compelling reason to add Java-style classical inheritance to the language, and I see even less a possibility of the vendors agreeing to ship timely implementations of this new spec.

Surely wiser heads than mine are laboring on this problem. But I guess I'm just not seeing that JavaScript falls short in ways that warrant changing it beyond recognition.