I agree with all the points here except for the part about bit flags. Bit flags are still arguably the best way to store "sets" of non-duplicate information. For example, if I wanted to aggregate the kinds of nodes I'd want with John's API, I'd have to accumulate them in an array, then use apply() because I can't pass that array in. Then there's the problem of duplicates, and also easily being able to check, add, and remove. All these operations are of course possible with an array (even if they contain duplicates), but it seems a bit much to go down a route where all these operations are inherently O(N) when there is an O(1) solution that isn't that hard to learn. Additionally you can easily construct shorthands for often used combinations: ElementsAndText = Element | Text. In the array world, you're going to be having to concat arrays to achieve a similar effect. It's also really nice that you can say "ALL" just with 0xF...FFFF (-1) and be assured that it is future proof, whereas in the array world if new nodes creep in in the future, you have to now go back to every instance where you called this and add a new parameter. I suppose the "easy" fix for this is to just say that if nothing is passed in it means "all", or alternatively have an ALL constant.
We recently tackled a similar issue in Cappuccino and our solution was to create two parallel ways of specifying this information that were transparently convertible: a pure bit flags version and a strings version, such that (Selected | Highlighted) is equivalent to "selected+highlighted". You can pass in either the string form or the bit form to the methods, and you can convert between them as well. All in all, none of the "JS people" using our framework seemed to mind the use of bit flags.