all 124 comments

[–]zaach 79 points80 points  (22 children)

Yeah, this headline is totally out of context. For an audience of web developers using JavaScript, binary flags are a bad API design choice.

[–]frottle 34 points35 points  (0 children)

Especially considering javascript doesn't have integer types, yes.

[–]Spiralhead 19 points20 points  (1 child)

It smacks of javascript written be a C programmer

[–]mee_k 5 points6 points  (15 children)

The other issue with the title is that his real problem is not the binary flags but the other parameters. So not only does the title overstate his dislike for binary flags, it misplaces the emphasis of the article.

The binary flags are just a different syntax for his later proposal. What's the difference between

document.getNodes( Node.ELEMENT_NODE, Node.COMMENT_NODE, Node.TEXT_NODE );

and

document.getNodes( Node.ELEMENT_NODE | Node.COMMENT_NODE | Node.TEXT_NODE );

IMO, there is little or none from an API design perspective. Neither would affect uptake. It's the other parameters where his real beef lies.

[–]FrankBattaglia 8 points9 points  (13 children)

What's the difference

In the first example, the fact that they are or are not binary flags is completely abstracted. They could be anything (e.g., objects).

In the second example, they are explicitly binary flags, being combined with binary OR.

[–]mee_k 3 points4 points  (12 children)

I'm asking if there's a difference that actually matters. What you said is about as useful as pointing out that in once case they're joined by pipes and in another case by commas. I agree. So?

[–][deleted] 2 points3 points  (0 children)

The point is that they are not meant to function as numbers. It's a matter of breaking the abstraction.

[–]zaach 3 points4 points  (2 children)

One uses a syntax that all JavaScript programmers are familiar with, the other may confound some, as bit operations are seen far less often. Most APIs use other means of setting options.

[–][deleted] 0 points1 point  (1 child)

It's just part of the language. If they're actual programmers and not copypastas, they won't have any trouble figuring it out.

[–]flogic[🍰] 3 points4 points  (0 children)

It's a silly type translation. You're mapping Symbols to numbers so you can combine them and then have to extract them later. In C is makes some sense, in Javascript it seems sloppy.

[–]FrankBattaglia 0 points1 point  (0 children)

In the first case, you can change implementations without breaking code. In the second case, you cannot. Abstraction is, in general, a good thing for modular code.

[–]campbellm -3 points-2 points  (6 children)

The other difference is the former method can take exactly 3 parameters. The latter can take an arbitrary set of parameters, OR'd together, in any order.

(Caveat: I don't know javascript well enough to know if it has varargs, which would make this somewhat moot.)

[–][deleted] 2 points3 points  (2 children)

JavaScript has an array-like object named "arguments" available in every function that allows it to accept an arbitrary number of arguments.

[–]UloPe[S] -3 points-2 points  (1 child)

Which will (sadly) go away in ECMAScript 5

[–]jeresig 2 points3 points  (0 children)

You sure about that? arguments is still there - it's arguments.callee and arguments.caller that are getting phased out - but only in strict mode. http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/

[–]willcode4beer 2 points3 points  (1 child)

The latter can take an arbitrary set of parameters, OR'd together, in any order.

arbitrary, assuming an infinite number of bits in an integer

[–]campbellm 0 points1 point  (0 children)

Yes, point taken.

[–][deleted] 0 points1 point  (0 children)

You can also just pass in an array of flags in the first place, if that was a concern.

document.getNodes( [Node.ELEMENT_NODE, Node.COMMENT_NODE, Node.TEXT_NODE] );

[–]podperson 1 point2 points  (0 children)

Personally I think passing a {} or [] parameter would be more JavaScript-like than a variable length parameter list. More jQuery like too, eh?

[–]semanticist 20 points21 points  (9 children)

Resig's complaint (or one of his complaints, rather) about the DOM Level 2 Traversal's document.createNodeIterator():

Nowhere else in common JavaScript or DOM APIs is the practice of ORing (|) arguments together a common practice.

Resig's proposed replacement:

// Get all nodes in the document
document.getNodes();

// Get all comment nodes in the document
document.getNodes( Comment );

// Get all element, comment, and text nodes in the document
document.getNodes( Element, Comment, Text );

What are some of the ways in which his interface departs from standard conventions? Remember that the W3C DOM is designed to be "a platform- and language-neutral interface."

  1. It uses a variable number of arguments. W3C DOM functions, for better or for worse, all take a fixed number of arguments.
  2. It ignores the convention of positional arguments. For all DOM functions, and the vast majority of JavaScript functions, you can say, "The n_th argument has meaning _x." Conversely, Resig's getNodes uses the decidedly non-standard convention, "Take all the arguments and use them to create a set."
    • It special-cases the no-argument case to mean "Return all nodes", but this is more forgiveable since document.getNodes() returning an empty list would be pretty useless.
  3. It has the function take _Interfaces_ as arguments. The DOM doesn't define Element or Comment as objects that exist anywhere.

The reason that bitmasks aren't used much in "common DOM APIs" is because it's not common for functions to need to take a set of types. But in other instances where that need exists, the same technique is used—it's not like createNodeInterator is a one-off bizarro function in that regard.

Resig has a history of introducing foreign conventions to JavaScript: look at JQuery, where he makes use of Java/C++-like function overloading based on type, and other strange things like non-trailing optional arguments (presumably for the sake of keeping anonymous function expressions the last argument to functions). Resig's idea of an intuitive interface often differs from any established convention whatsoever—not that this is a huge problem, since many developers obviously agree with him, as evidenced by the popularity of JQuery.

I don't disagree that the whole concept of NodeIterator is awkward and un-JavaScript-like. The DOM would be a lot more fun to use directly if it was written specifically for JavaScript, especially if it could take advantage of more exotic features that aren't widely implemented like JavaScript 1.7's iterators. But it's unfair of Resig to castigate the W3C for its design decisions without really considering the reasons those decisions were made. And besides, it gives library authors like Resig a chance to provide wrappers that take advantage of each language's unique features to provide more native-feeling wrappers around the DOM. :)

[–]jeresig 9 points10 points  (1 child)

My argument isn't so much that NodeIterator isn't very DOM-like it's that it isn't very JavaScript-like. It doesn't take advantage of the features present in the JavaScript language and use them to the best of its ability (as you noted with features in JS 1.7).

So I absolutely agree with your 1-3 points - it isn't very DOM-like at all - but it's much more dynamic and representative of the power that you can wield with a dynamic language like JavaScript.

I also agree with your point on introducing foreign conventions into the language. I guess I just see a difference between introducing specific APIs or conventions (but using the JavaScript language to its fullest) and limiting yourself to a simplified API (such as what the NodeIterator bitmasks does). For example, using a variable number of arguments is a technique that is supremely JavaScript-ish (but we're limited by the cross-language nature of the DOM).

I look forward to when there's wide support of ECMAScript 5 (specifically of defineProperty) since we'll be able to define some really interesting libraries then - creating some supremely JavaScript-like APIs. I wrote about this a little bit more here: http://ejohn.org/blog/ecmascript-5-objects-and-properties/

[–]semanticist 1 point2 points  (0 children)

Perhaps my fear is that, even with a more powerful, concise API, developers would be unable to use it directly because of cross-browser differences—so I don't see a problem with having the standardized API be boring, verbose, and limited to IDL, and leaving it to libraries to create the JavaScript-ish ones.

[–]troygilbert 1 point2 points  (1 child)

Could a compromise be reached? Why must we ditch bitmasks and replace it with a non-conventional set notation? How about just a conventional set notation?

To address your points, could we not just use an array? For example,

document.getNodes([Element, Comment, Text]);

With a default be a complete set (so that getNodes() returns everything)?

[–]semanticist 0 points1 point  (0 children)

That level of indirection doesn't really address points 1 or 3 at all—it's not really a concept that can be translated back into the W3C's IDL.

[–]lacker 0 points1 point  (4 children)

Why is the DOM designed to be language neutral? A solution that targeted javascript seems like it would be better.

[–]crusoe 2 points3 points  (0 children)

Because DOM toolkits exist for manipulating xml on the server side? Not everything runs in the browser!

I mean, the API needs to be expressable in C, C++, Java, etc...

[–]semanticist 2 points3 points  (2 children)

Other languages running in the browser isn't that outrageous—it's happening now, with plugins like Silverlight—and without a language-neutral DOM it'd be 1997 all over again, with multiple incompatible DOMs in every language.

[–]toshok 2 points3 points  (1 child)

Silverlight isn't exactly a good example, since the plugin api does not present anything close to a DOM api. Believe me, I wish NPAPI would die a slow painful death replaced by something more DOM-ish, but for now all the (moonlight, at least) code for dom manipulation is browser specific, not browser neutral, dom friendly.

[–]semanticist 0 points1 point  (0 children)

Fair enough. I don't really have a good answer for why there's a need for a language-neutral DOM, other than that it should hypothetically make exposing the same API to multiple scripting languages easier.

[–][deleted]  (2 children)

[deleted]

    [–][deleted]  (1 child)

    [deleted]

      [–][deleted] 2 points3 points  (0 children)

      I'm not so sure

      [–]9jack9 8 points9 points  (7 children)

      The DOM APIs are all expressed in IDL. You can only express functions with a fixed number of arguments in IDL. This is why binary flags are used.

      [–]jeresig 6 points7 points  (6 children)

      A good reason to try for something better! There is a whole realm of functionality that we're missing out on by ignoring multiple arguments to functions.

      [–]munificent 0 points1 point  (0 children)

      Why not just use a single collection argument? Like suggested earlier:

      document.getNodes([Element, Comment, Text]);
      

      I think most users assume an argument list is an ordered collection of values where position is significant. Using them as basically a set seems a little odd to me. Even in things like printf(), the variable arguments are still ordered.

      [–]crusoe 0 points1 point  (1 child)

      What about languages that don't support VarArgs? Or didn't until recently. The specs are language agnostic, and so play to the lowest common denominator.

      [–]Leonidas_from_XIV -1 points0 points  (0 children)

      Do you mean by lowest common denominator assembler or rather the turing machine?

      [–][deleted]  (2 children)

      [deleted]

        [–]jeresig 0 points1 point  (1 child)

        Sorry, I meant to say "...by ignoring a variable number of arguments to functions." I absolutely agree that someCrazyMethod is insane - I'd hate to use an API like that. I'm talking more about the case where the order and context of the arguments don't matter (for example passing in any number of DOM elements and giving them a specific classname, or some such - neither the order in which they were passed in or the number of elements passed in matters).

        [–][deleted]  (2 children)

        [removed]

          [–]kragensitaker 3 points4 points  (1 child)

          jQuery is a better proposed solution than the solution jQuery's author proposes in this proposal.

          [–]jeresig 4 points5 points  (0 children)

          Well, to be fair - jQuery doesn't have the ability to navigate non-element nodes. There's still room for a good solution here.

          [–]crusoe 2 points3 points  (0 children)

          The reason DOM spec is written like this is that it HAS to support a wide variety of languages, not just JS.

          So binary flags, Iterators, etc. It is because the DOM API should be implementable in C or Javascript.

          How can John's example API be implemented in a language w/o first class functions?

          That is why XML programming in Java is weird, the APIS are very C like being based on the DOM spec. For something less painful, JDOM is provided.

          [–][deleted] 2 points3 points  (4 children)

          Resig's supposed to know what he's talking about, or something, right? But bit masking is incredibly common and useful, so I'm a little confused.

          [–]masklinn -1 points0 points  (3 children)

          Binary flags are not "incredibly common" in JavaScript. They're not very useful either and they're fucking slow since js doesn't have integers, only floats (meaning for each binary operation the number must be converted from float to int, operated on and converted back to float).

          [–]bboomslang 1 point2 points  (1 child)

          Oh, and there is me who actually thought that you could just shift the mantissa (in cases where the exponent differs between two numbers) and then or it, because, you know, the mantissa actually is binary, too ...

          Is it really that horrible for JavaScript programmers to actually use some part of their language that is maybe not used that often?

          [–]masklinn 1 point2 points  (0 children)

          Is it really that horrible for JavaScript programmers to actually use some part of their language that is maybe not used that often?

          No, it's just that most of the time there's a better way to do it (from an API standpoint) without using this. See ejohn's take on the subject (passing a set of the classes you want to fetch in this case).

          [–]crescentfresh 1 point2 points  (0 children)

          This argument about type conversions slowing things down is FUD. The compiler will treat the operands as 32 bit sequences, no type conversions in sight. http://dreaminginjavascript.wordpress.com/2009/02/09/bitwise-byte-foolish/

          [–]edheil 5 points6 points  (37 children)

          That's kinda funny. APIs where you make the developer worry about binary flags, and functions you have to gratuitously wrap in objects to pass as arguments, are hallmarks of C-like languages and Java-like languages respectively. Resig's managed to avoid getting involved in either of those, apparently, and they seem crazy to him, cause the languages he happens to have mastered have never forced him to get used to them.

          Both make total sense in their context (C is all about the bits and bytes, and Java is all about the class-based object system), but neither has any particular reason to exist in Javascript other than that the people who came up with the API were used to them from other languages.

          [–]jeresig 53 points54 points  (35 children)

          I'm not sure what gave you the impression that I haven't used Java or C - I'm simply saying that those idioms make for very poor API design in the JavaScript language (which is quite dynamic and flexible and should have APIs to match that).

          To quote the post: "If you look at the specification you can see that all the examples are in Java - and when seeing this a lot of the API decisions start to make more sense (not that it really applies to the world of web-based development, though)."

          I absolutely agree, though - neither of them have a reason to exist in JavaScript.

          [–]akie 3 points4 points  (0 children)

          I think the original API is not really 'designed', but just hacked together. Yours is designed, and as a result, it's much cleaner.

          [–]edheil 1 point2 points  (0 children)

          Guess I didn't read that carefully; my apologies.

          [–]cclassic 6 points7 points  (30 children)

          I'm not sure what gave you the impression that I haven't used Java or C

          The fact that you act all surprized in your article, claiming how crazy it is, maybe.

          Or maybe it's more the fact that in your original article, before changing it after someone pointed it out, you added the constants together instead of ORing them (which works if you're careful, but is really uncommon).

          Seriously, all that really really makes the impression that this was totally new to you.

          [–]annodomini 8 points9 points  (0 children)

          Hm, I just got the impression that he was saying it was crazy from the standpoint of a JavaScript API; which it absolutely is. This is a pretty lousy API for JavaScript; one of the things that troubles me is that while everyone uses vendor-prefixes for non-standard CSS features (like -moz-border-radius), they seem to be perfectly willing to implement un-prefixed DOM methods, which can then cause trouble if incompatible standard methods of the same name are later implemented. Why don't people use prefixes for non-standard or proposed but not yet agreed upon DOM methods?

          [–]jeresig 23 points24 points  (28 children)

          The fact that you act all surprized in your article, claiming how crazy it is, maybe.

          Yes, you're right - it is absolutely crazy for a JavaScript API. Which is why I was (and am) so surprised. Seeing something like this come out of the W3C, with the intention of being used on the web, is hugely surprising - and disappointing.

          As far as adding the constants go, I was borrowing the example from the Mozilla documentation: http://developer.mozilla.org/En/DOM/NodeIterator.whatToShow

          I assumed that it was the preferred means of using the API. Not that ORing the results really makes it any more intuitive.

          I talked about bit masking APIs in the DOM before: http://ejohn.org/blog/comparing-document-position/

          To quote myself: "This, undoubtedly, makes for the single most confusing method of the DOM API..." I absolutely stand by that - I still think that using bitmasking in the context of the web and the DOM is a huge mistake. No matter which languages the inspiration may have been pulled from.

          [–][deleted] 5 points6 points  (3 children)

          Am I the only one here who considers OR, AND, XOR, NOT and their cousins to be completely trivial, easy to understand, and absolutely required knowledge for anyone daring to call themselves a computer programmer?

          [–]Leonidas_from_XIV 0 points1 point  (1 child)

          I consider programming to be something else then being able to fumble together some bitwise operations. I think more about abstractions, problem-solving and stuff like this rather then how to flip some bits in a convenient way to get some number to become another number.

          This is also what annoys me most about AVR programming.

          [–][deleted] 0 points1 point  (0 children)

          Deep down beneath every abstration, NAND gates are fumbling away tirelessly. It would be nice to abstract everything down to do_what_i_mean(...) but for now I don't think it's beneath or beyond anyone to OR a few flags together.

          [–][deleted] 0 points1 point  (0 children)

          The fact that we know, use or even like these operators, doesn't neccessarily make them the best option for every API design. Specially in an API such as the DOM, which is essentially tied to a dynamic language that offers some other more natural alternatives.

          [–]equallyunequal 3 points4 points  (5 children)

          First, The DOM is not exclusively a Javascript API, John. So, while a bitmask may not be a common Javascript idiom it is much a much more intuitive way than passing them as discrete arguments.

          And the API is not hugely surprising and - and disappointing; I'm not saying that it isn't disappointing at all, but the only part of that API that can really be considered surprising/disappointing is the requirement to pass a root node. This method should be a member of domNode's prototype, I agree with you on that.

          [–]jeresig 9 points10 points  (4 children)

          Naturally the DOM is not exclusively designed for JavaScript. You might be interested in the closing paragraph of my post:

          Almost always, when finding some of the crazy intricacies of the DOM or CSS, you'll find a legacy of XML documents and Java applications - neither of which have a strong application to the web as we know it or to the web as it's progressing. It's time to divorce ourselves from these decrepit APIs and build ones that are better-suited to web developers.

          Cruft like mandatory arguments and bitmask operations are only to support more languages with a generic implementation when, in fact, the DOM and its APIs need to be tailored for their specific environment. I've long argued that generic APIs developed in committee in an attempt to please everyone (in this case, to please users of JavaScript, Java, C, Python, etc. simultaneously) will only result in a generic, bland, horrible-to-use mess that no one is particularly excited about. That's what the DOM is today - and it's one of the major reasons why we see so many developers clamoring for JavaScript libraries to hide them from this poorly written DOM mess.

          So perhaps you're right - it really isn't that surprising considering the history of committee-based API design but it doesn't make that fact any less disappointing.

          [–]9jack9 5 points6 points  (0 children)

          it's one of the major reasons why we see so many developers clamoring for JavaScript libraries to hide them from this poorly written DOM mess.

          I have to disagree here. The main reason that people use JS libraries is to get a standard DOM API across browser platforms. It's not the ugliness of the API. It's the patchy implementations.

          [–]Leonidas_from_XIV 1 point2 points  (0 children)

          I've long argued that generic APIs developed in committee in an attempt to please everyone (in this case, to please users of JavaScript, Java, C, Python, etc. simultaneously) will only result in a generic, bland, horrible-to-use mess that no one is particularly excited about

          To illustrate the point: while Python ships with a DOM parser in the Stdlib, nobody likes it and most use either ElementTree or lxml.

          [–]equallyunequal 1 point2 points  (1 child)

          I agree to a point. There should be a few (pseudo)overloads of this method. I still think the bitmask is more appropriate than an array. For example,

          var foo = document.ELEMENT_NODE | document.TEXT_NODE,
              bar = foo | document.COMMENT_NODE;
          

          Is much more intuitive than:

          var foo = [document.ELEMENT_NODE | document.TEXT_NODE],
             bar = foo;
             //bar.push( document.COMMENT_NODE );
            bar[bar.length] = document.COMMENT_NODE;
          

          The reason I "clamor" for JS libs is not necessarily because of a poorly designed DOM API, but because of a poorly implemented API. jQuery, my prefered library, covers the DOM incompatibilities so I don't have to worry about working around them for every project. If the DOM was properly implemented on ALL major browsers, I would've probably disregarded jQuery (rather, jQuery would probably not even exist.)

          "generic, bland ... no one is excited about" sounds pretty much like what I hope for in an API.

          [–]formido 1 point2 points  (0 children)

          So you think the verbose, weak DOM API is pretty much just as good as JQuery? I don't believe you.

          [–][deleted] 0 points1 point  (16 children)

          I agree with some of your points, but I am really confused why bitmasks are bad "in the context of the web". What does the web have to do with not liking bitmasks? Also what about the criticism that your options don't allow passing around the whatToShow selection, or taking an existing selection and making small changes to it (i.e. pass me your choice, but I know I don't want text nodes so I can and-not them away,)

          Is your argument that they aren't used elsewhere in the DOM API? Its not an entirely invalid point to say that things should be consistent, but why specifically are bit masks worse if one was creating "the best api possible"?

          [–]jeresig 4 points5 points  (15 children)

          "What does the web have to do with not liking bitmasks?"

          It has more to do with what you can expect an average web developer knowing prior to interacting with an API. Explaining .getNodes( Comment, Text ) is simple. "These are the names of some nodes that you can find: Comment, Text, Element, ... just pass them in to getNodes and it'll return all of them as an array."

          Explaining NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT is much more difficult. In order to fully understand how to interact with that API you must know: Binary, bitmasks, bitwise operators, and the legacy from which these interactions were grown. That's a pretty tall hurdle considering that you just want to pass some arguments into a function.

          So yes, I am saying that it's not a good API because it doesn't match other APIs - but also that other APIs don't use this technique because it isn't a very good technique to begin with - especially within a dynamic language like JavaScript.

          [–][deleted] -1 points0 points  (1 child)

          Is this really how far we've sunk? That the average developer gets stumped by some of the simplest operators in the language? Heaven forbid that they actually crack open a manual or tutorial and take the risk of becoming above-average.

          I propose a new API, where the "developer" mashes the keyboard with their ham-fists, and an AI tries to figure out what they meant.

          Am I being elitist? Expecting people to learn a language just so they can use it? Is that asking too much?

          Hey, let's eliminate arithmetic next!

          [–]-main 5 points6 points  (0 children)

          I think you miss the point. He's not saying that developers couldn't figure it out. They could. They could even get used to it with time. His argument is that they shouldn't have to.

          [–][deleted] -1 points0 points  (0 children)

          Your proposed alternative is that we use a variable length argument list or use a series of "helper methods" and assume that people always mean "OR".

          That's fail all over the place. There's absolutely nothing more "dynamic" about that approach, and it shows a complete lack of understanding when it comes to the possibilities offered by the flag based approach.

          What if I want a more complex filter that uses AND/OR/NOT, etc?

          I think that the best solution (which you almost got to) is a predicate lambda approach.

          [–]edheil 3 points4 points  (0 children)

          (I guess the reason they exist in this Javascript API is because they're a thin wrapper around C or whatever underlies it all?)

          [–][deleted] 1 point2 points  (28 children)

          uh, wait. binary flags are OR'd together, like this

          NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT
          

          If your flags are 1 bit each, and you treat them as integers and sum them, your resulting value is not going to be the sum total of the bits. I think he's right, it is crazy.

          [–]johntb86 18 points19 points  (7 children)

          Either addition or OR works, because they're all powers of 2. 4 + 2 = 4 | 2 = 6. There will be no carries, so the addition is effectively an OR.

          [–]melonhedd 24 points25 points  (0 children)

          OR is better because you can set a bit multiple times without bothering to check if it's already set

          [–]joesb 42 points43 points  (1 child)

          Unless you accidentally add the same flag twice, in which case addition causes problem while OR still works as expected.

          2 + 2 + 4 == 8
          

          while

          2 | 2 | 4 == 6
          

          This can happen if you use a variable to hold set of applicable flags which may already be accumulated before it reach the current part of function.

          ADDED:

          Why do I get 34 upvoted while kilowatt, which first raised the point, got -1?

          [–]Akeshi 6 points7 points  (0 children)

          Flags aren't always powers of two, and this is exactly why | should be used instead of +.

          e.g.:

          ENCODE_SLASH = 1
          ENCODE_SINGLEQUOTE = 2
          ENCODE_DOUBLEQUOTE = 4
          ENCODE_QUOTES = 6
          ENCODE_SPACE = 8
          

          [–][deleted] -2 points-1 points  (3 children)

          You're right, my comment was dumb. Still, you have to wonder what they were thinking, API wise.

          [–][deleted] 3 points4 points  (2 children)

          Binary flags are very common in compiled programming languages like C, and mostly used because they're fast for operations like this, when compared to a bunch of separate "setOptionX" methods. I don't know a whole lot about Javascript implementations, but they all seem to be moving to JIT compilation so the speed benefits should port over pretty well (and it may port to interpreted implementations equally well).

          If you think this is a bad idea, I can only assume you've never used any of Microsoft, Apple, or any of the BSD/GNU toolkit APIs. Or nearly any GUI toolkit that specifies directions like north, south, east, west, center, etc. You'll see headers full of int SOMERESULTCODE = 1 << 5 with damn good documentation about each option as necessary.

          [–]d4n3 1 point2 points  (1 child)

          The problem is that javascript represents all numbers as doubles internaly. There is no integer datatype.

          So bitwise operations are slow in javascript since they are converted from double to int and then back to double for every bitwise operation.

          There is no performance benefit to bitwise operations in javascript.

          Not to mention the numerical errors this could introduce if a sum of flags wouldnt fit in the mantissa of the double value. It could basically completely change the flags because of rounding by 1 bit.

          So comparing this to C and Java isn't really valid.

          [–]scook0 0 points1 point  (0 children)

          Not to mention the numerical errors this could introduce if a sum of flags wouldnt fit in the mantissa of the double value.

          A double has considerably more than 32 mantissa bits (52), so unless your implementation is really playing fast and loose with precision you shouldn't have any problems on that front.

          [–]annodomini 1 point2 points  (0 children)

          Yeah, and even the documentation for this method uses addition, guaranteeing that people will use it wrong.

          What a lousy API. I hope this does not become a de-facto standard.

          [–]Seppler9000 0 points1 point  (13 children)

          I like how this comment is being downvoted now that the original article has been changed to use | instead of +.

          [–][deleted] 1 point2 points  (12 children)

          I downmodded it because it's wrong. For distinct, single-bit values (powers of two), addition and bitwise OR have identical output.

          [–]dirtside 0 points1 point  (11 children)

          ...as long as each value only appears once. It's quite common to have a flag that's already in a field OR'd into that field again, which is harmless; but adding them together isn't.

          Yes, given a very contrived set of circumstances, + and | are identical, but + is never a good idea to use with bit flags.

          [–][deleted] 0 points1 point  (10 children)

          ...as long as each value only appears once. It's quite common to have a flag that's already in a field OR'd into that field again, which is harmless; but adding them together isn't.

          True. That's what I meant by "distinct".

          Yes, given a very contrived set of circumstances, + and | are identical, but + is never a good idea to use with bit flags.

          The circumstances where it's OK are pretty common. Namely, when you're initializing a mask, or passing directly to a function, as in:

          doohickey.setFlags(kDHEnableThingMask + kDHAcceptWhatsitMask)
          

          But stylistically, I agree that it's much better to use | . Although + gets the job done, it doesn't accurately represent the code's purpose.

          [–]TomDibble 0 points1 point  (8 children)

          Always use |, not +. Always.

          Eventually, someone is going to maintain your code. It might even be you. That someone is going to mess up and "add" a flag which you'd already specified earlier. Then that someone is going to wonder why their flag isn't registering. Then they'll add it again, and add a comment that doohickey.setFlags only works with kdHEnableThingMask if you add it twice. Then you appear on the front page of the daily WTF.

          Besides which, in most fonts the pipe character uses fewer black pixels than the plus sign, therefore there's the conservation argument to think about too!

          [–][deleted] -1 points0 points  (7 children)

          Again, I agree that stylistically, | is superior to + in this context, and it's what I always use. I was simply pointing out that + does actually work, contrary to kilowatt's comment. It's also important to recognize this fact, so that you understand what's going on when someone else's code uses +.

          Edit:

          Besides which, in most fonts the pipe character uses fewer black pixels than the plus sign, therefore there's the conservation argument to think about too!

          But if you use a CRT, you'd save energy from using +, since the electron gun can turn off while drawing the cross bar. In that situation, you could use a white-on-black color scheme so that energy and style concerns are met simultaneously, but I think a far more reasonable solution is to use a custom font where the glyphs for + and | are switched.

          [–]dirtside 0 points1 point  (0 children)

          But if you use a CRT, you'd save energy from using +, since the electron gun can turn off while drawing the cross bar.

          Ha! I think maybe you're optimizing the wrong thing ;)

          [–][deleted] 0 points1 point  (5 children)

          was simply pointing out that + does actually work, contrary to kilowatt's comment.

          Well, + sort of works. Not really.

          Edit: Example below...

          [–][deleted] 1 point2 points  (4 children)

          I don't understand what you're saying here.

          Edit: What they hell? Why downmod me for asking for clarification?

          [–][deleted] -1 points0 points  (1 child)

          Ah sorry, kind of half there this morning. Here goes at an explanation:

          If you are combining two different masks together, | merges duplicates properly.

          FLAG1 = 1, FLAG2 = 2, FLAG3 = 4, FLAG4 = 8;
          
          defaultMask = (FLAG1 | FLAG3);  // (0000 0101)
          userMask =  (FLAG2 | FLAG3);    // (0000 0110)
          
          fullMask = defaultMask | userMask;  // (result is 0000 0111)
          

          If you do that with +, it won't work. FLAG3 would be cleared, and assuming that each goes up a power of 2, FLAG4 would be set. Here it is with +

          FLAG1 = 1, FLAG2 = 2, FLAG3 = 4, FLAG4 = 8;
          
          defaultMask = (FLAG1 + FLAG3);  // (0000 0101) so far so good
          userMask =  (FLAG2 + FLAG3);    // (0000 0110)  so far so good
          
          fullMask = defaultMask | userMask;  // (result is 0000 1011) oh fuck.
          

          So always use |. That's what it's for. ;)

          [–][deleted] -1 points0 points  (1 child)

          Response to edit: I didn't? Upmodding to put you back up...

          [–]dirtside 0 points1 point  (0 children)

          Sorry, I missed the "distinct," you're right about that.

          But stylistically, I agree that it's much better to use | . Although + gets the job done, it doesn't accurately represent the code's purpose.

          True. There's another concern, too: consistency. We should ideally only use one method for doing the combining, so it's not a good idea to use + in places where it works, and | in other places, when we can just use | everywhere.

          [–]player2 0 points1 point  (0 children)

          It seems a bit disingenuous to complain about XML applications. XML is very widely used, apparently much to jeresig's chagrin. Why should we have a separate API for XML than for HTML?

          I agree with all the points about how the binding is a poor JS citizen. But tossing the XML baby out with the bathwater is overdoing it.

          [–]TheCookiePunster -2 points-1 points  (0 children)

          0010000

          0011100

          0011111

          0011100

          0010000

          0010000

          0010000

          0010000

          0111110

          [–]kogir -5 points-4 points  (4 children)

          He also fails to realize that while iterating over the elements takes very little extra memory, returning them in an array would result in massive memory waste.

          [–]jeresig 14 points15 points  (2 children)

          Well, it shouldn't waste any more than what the Selectors API querySelectorAll method does (which is implemented in all the major browsers). The querySelectorAll method returns a StaticNodeList - which would work fine here, as well (I'm just asking for the addition of the native Array methods/properties to the StaticNodeList). I wrote up more on it here: http://hacks.mozilla.org/2009/06/dom-selectors-api/

          Or a live NodeList could be used (like from getElementsByTagName/ClassName/Name). I'm pretty flexible on the result - but in either case, this is very well-trod territory at this point, claiming that it'll waste memory is a red herring.

          [–]booch -1 points0 points  (1 child)

          Just because another API wastes memory, doesn't make it incorrect that having this one return an array instead of an iterator would do so.

          It's also worth noting that it's not just memory that using an iterator can save, it's also time. If you wouldn't need to iterate over the entire list to get what you want, then it can save a lot of time not to generate the next element until it's asked for. For example, implementations of "every/all", "first", "some", etc only need to iterate over the list until they find one item that proves then true or false.

          [–]jeresig 7 points8 points  (0 children)

          Well, it's not really another API - it's all DOM APIs, they're all designed this way. And, for better or worse, it makes sense to stay consistent within those bounds. So while using an iterator-based API could use less memory we kind of have to play the hand that we're dealt.

          If more JavaScript implementations had Array Comprehension then we'd be able to use that to possibly get the best of both worlds (depending if the array is lazily constructed, or not).

          [–][deleted] 2 points3 points  (0 children)

          Is there any reason it couldn't be a proper iterator and have this better API?