5 ms·
Fun with JavaScript Arrays
- hcarvalhoalves 13y agoYou don't have to stretch it beyond normal tasks to get some big WTFs: https://gist.github.com/hcarvalhoalves/4471029 https://gist.github.com/hcarvalhoalves/4471029
- switch33 13y agoLol, why isn't that fixed for javascript? That's beyond screwy.
- shinuza 13y agoIf var a = [1, 2, 3] a == a Returned false, it would by screwy. In this case the == operator behaves like the `is` operator in Python when comparing lists.
- drostie 13y agoThose are only little WTFs. The fact that object-equality is being tested for, for example, is not a WTF on its own; it's a valid concern in any non-functional language (answering the important question, "will editing X affect Y?"). The fact that everything has a string representation which gives everything a natural lexicographical ordering (which is inconsistent with the value-ordering of numbers) is also not a WTF, especially because `array.sort(function (x, y) { return x - y; })` does precisely what you want extensibly. Maybe the fact that there is no `<>` operator to represent `x >= y && x <= y` (which would basically test if x.toString() == y.toString() for the general ordering) might be a WTF, if you're expecting == to be consistent with <=. But the general idea of "we're not going to try to be smart, we'll just use strings" is actually very Unix-y. The alternative is to throw errors whenever you try to sort arrays which have incompatible types -- but JS doesn't have a strong notion of types. Don't get me wrong, I'd love it if JS were different in many ways -- especially if it were more functional, because so much of the core language is built around functional concepts. There are also now type systems which are being developed which allow for the 'duck typing' style that JS uses for everything; it would have been nice if Eich had been able to magically foresee it back when it was LiveScript. But for a language which was a little haphazardly thrown together at first and then was haphazardly canonized by two competing companies during the Browser Wars, it's actually done remarkably well.
- deleted 13y ago[deleted]
- Wilya 13y agosort() is a bit weird, I have to agree, but the '==' thing is a common problem to a lot of languages, not exactly a js-specific WTF. Off the top of my mind: In Python, '==' on arrays compares elements. In Java, '==' on arrays compares the objects themselves. You have to use equals() to compare the elements. In C(++) arrays, '==' compares the objects. But for std::vector, it compares the elements. One could argue it's a language choice more than a screwup.
- arethuza 13y agoCommon Lisp has quite a few equality functions: eq, eql, equal, equalp http://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node74.html http://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node74.html
- hcarvalhoalves 13y agoThe point is not what "==" should do. The point is you have even two equality operators - with subtle differences - and still no way to compare two arrays by value without boilerplate, which should be trivial.
- clux 13y agoThe default lexicographical sort order on an array of integers is unexpected, yes.
- hcarvalhoalves 13y agoSpecially given the fact value-ordering is also lexicographical for the ASCII set, and for Unicode it gets it wrong anyway.
- the_gipsy 13y agoThat is not a WTF. A real WTF would be the opposite, two arrays comparing as equal because their values match. Like the brain-dead PHP comparison.
- hcarvalhoalves 13y agoYou want operators for both: test if it´s the same object (identity) and test if they are equivalent (equality).
- SEJeff 13y agoI can't believe no one has posted the (in)famous WAT ruby/javascript presentation: https://www.destroyallsoftware.com/talks/wat https://www.destroyallsoftware.com/talks/wat It describes many ridiculous things in javascript such as empty array + empty array == empty string, etc. It is also great for a good laugh to anyone who has ever written javascript or ruby.
- nandhp 13y agoMany of those examples also make sense when you consider what you're actually asking for. For example, Arrays have no + operator. So []+[] requires that [] be converted to a string first. The string representation of [] is "" (although some interpreters use "[]" or "[Array]" for clarity), so []+[]==""+""=="". Similarly, he used the example []+{}, and claimed it was [object Object]. This actually wrong (at least in Chrome); it's actually "[object Object]", a string. The reason for this is the same as the previous example. However, there is a different reason why {}+[]==0, given that "[object Object]"+[] == "[object Object]". There turns out to be something special about {} at the beginning of a statement (It's a block, or something). Thus, {}+[] is like {};+[], where +[] causes [] to be converted to a number: 0. Compare: {}=={} (syntax error, unexpected token ==). Yes, this one is actually confusing. (However, expressions are not usually evaluated in void context.) He also observes that ",,,,,,,,,,,,,,," is a bad representation of Array(16). It is, since the undefined in each element is important, but again, that can be solved by using an interpreter with better string generation. (Or a version of IE that doesn't attempt to be clever and just returns "[Object]" all the time). So perhaps the moral of the story is: Yes, it's an entertaining talk, but a several of the examples break down because his interpreter is vague.
- residualmind 13y agoTBH, all those pose nothing really unexpected. It all makes sense. I was a real JS hater, too - just because I didn't understand the language and I would have laughed at those examples - until I watched "Crockford on JavaScript." It's an interesting, entertaining, educating, (quite longish) series you should treat yourself to. And just as drostie said, given the way the language was born, it's really an amazing thing. And yes, it does have ugly parts.
- lucian1900 13y agoI think I understand the language quite well and I still think it's terrible. Knowledge does not preclude disapproval.
- SandB0x 13y agoBear in mind that I know very little JavaScript so I may be completely wrong or this may be a very simple observation, but isn't the confusion in the first part simply due to the printed representation of the Array prototype/object? I seem to remember that arrays in JavaScript are in theory just objects/dicts such that: var a = [1, 2, 3]; is equivalent to var a = {0 : 1, 1: 2, 2: 3}; and whatever function is invoked by evaluating `a` in the console must just iterate over the sorted keys of the object, starting at key = 0 and attempting to print key + 1 until the key does not exist. So he may be setting `a[-1]` and it happily exists, but the confusion is just down to the whatever the equivalent of the `__repr__` function is for JavaScript arrays.
- jdlshore 13y agoYes, most of the confusion is the author's misunderstanding of how arrays work in JS, combined with his tool not showing everything he put into the array. You're correct that arrays are objects, which means they consist key/value pairs. Keys must be strings; values can be anything. So when you say `a[0] = 3;`, JS converts that to `a["0"] = 3;` and stores `{ "0": 3 }`. So all those "funny" examples the author provides are just variants on converting an expression to a string. For example, `a[typeof a] = 4` is equivalent to `a["object"] = 4` (or `a.object = 4`) because `typeof a` is "object". There's one wrinkle on this, though: objects and arrays aren't exactly the same thing. Arrays are a special kind of object, as far as JS is concerned. JS maintains a special "length" property for arrays. It doesn't do that for other objects. (The same applies to JS functions and Regexes. They're objects, but they're special kinds of objects that can do things regular objects can't.)
- ludwigvan 13y ago> JS maintains a special "length" property for arrays. It doesn't do that for other objects. (The same applies to JS functions and Regexes. They're objects, but they're special kinds of objects that can do things regular objects can't.) Indeed JS functions have a special `length' property too, where one can check the # of arguments specified in the function definition.
- cema 13y ago
- jhaglund 13y agoAssignment within the brackets, that kinda surprised me > a = [] > a[a[typeof a]='huh', void a] = 'puh' > console.log(a) [object: "huh", undefined: "puh"] huh... you can do this too > a = [] > a[a[a[typeof a]='huh'] = 'puh'] = 'woh' > console.log(a) [object: "huh", huh: "puh", puh: "woh"]
- Tloewald 13y agoThe comma operator in Javascript is a major WTF. The entire post basically comes down to a, b evaluates to b, [] coerces to string, and arrays are objects. The only thing to really look bad is chrome, which is surprisingly easy to kill.
- shinuza 13y ago> a.length 0 Same as the article, you are adding properties to a. A is an array, not an hashmap. Any index that is not a number will create a property, not a new index.
- Kiro 13y agoOnce you realize that there are no associative arrays in JavaScript these things become less of a WTF.
- shinuza 13y agovar a = {}; PHP != Javascript
- dkroy 13y agoCouldn't some JavaScript Objects be called associative arrays?
- Skinney 13y agoNot really no. Every object has it's prototype set to the object prototype. Which means that even if you create a new empty object, it inherits functions and values from the object protype. var a = {}; typeof(a.hasOwnProperty) === "function" Objects are very often used as associative arrays, quite simply becouse objects and arrays are all js has to offer. Javascript Harmony will change that though, with it's own Map type.