4 ms·
Silly Javascript
- palsecam 17y agoNo way to avoid it, I think. Javascript calls Object.toString() to determinate the key. But yes, kind of silly... See http://news.ycombinator.com/item?id=602004 http://news.ycombinator.com/item?id=602004 Actually there may be a way to avoid it: redefine the toString() method of the String prototype or something like that (just an idea in the wild, haven't tried it)...
- eel 17y agoYes, JavaScript arrays are not true arrays. Yes, all property names are strings. If you use an integer as an index, it'll be converted to a string. I suppose it's silly at first, but hopefully at some point, you grow used to it. Crockford's book JavaScript: The Good Parts is a good book that explains many of the oddities in JS.
- mustpax 17y agoFirst of all, I would strongly recommend you read Doug Crockford’s, JavaScript: the Good Parts. JavaScript has a lot of quirks and rough edges, but please do not try to use a language in a professional capacity without learning it first. To be fair, JavaScript pretends to be Java just enough to invite all this ill-advised behavior. To answer the question fully: JavaScript arrays are really just plain objects. All objects in JavaScript are simply associative arrays, and all associative arrays are string indexed. So, subscripting always causes a string conversion. The Array class provides some convenience methods with .push() .pop() to gloss over this fact, but arrays are really no different than other objects.
- boucher 17y agoI'm not a huge fan of Doug's book, but I think this is an excellent read: https://developer.mozilla.org/en/A_re-introduction_to_JavaScript https://developer.mozilla.org/en/A_re-introduction_to_JavaSc...
- axod 17y agoI'd recommend "Javascript: The definitive guide" O'Reily far more. "The good parts" isn't really a full language spec. It's an interesting read, but not as useful IMHO
- skwaddar 17y agoArrays are not hashes
- tlrobinson 17y agoYeah I don't know why the author expected any reasonable behavior from using a string as an array index. However, the same behavior is true of plain Objects.
- s3graham 17y agoI used [] because I hoped it would correctly handle number indices. But, I originally used {}. The auto-stringification of the keys was my complaint.
- axod 17y agoAll keys are strings :/ What you're complaining about is similar to complaining that "hello " + 3 + " world" == "hello " + "3" + " world"
- invisible 17y agoWhen assigning a String with a numeric value I think JavaScript treats it as a numeric for an Array and a String for regular Objects. This doesn't really change the difference, just that an Array should hold numerical index values (vs an Object key, but they CAN hold regular keys since they are an Object). A bit confusing I guess...
- tolmasky 17y agoIt is reasonable to expect to be able to set arbitrary properties on an Array and have them behave differently than it's indexes, despite the fact that this is not how it works. The language even suggests this is possible by providing certain properties that are not enumerated (such as "length"). What's worse is that the true answer to why this behaves the way it does is that in JS arrays are (kind of) hashes.
- halo 17y agoThis functionality makes perfect sense as soon as you realise that at its core JavaScript only has a single data structure, and that is objects (aka dictionaries, associative arrays or hashmaps), and arrays are simply a special case with some syntactic sugar built on top of it I actually think that it's one of JavaScript's better ideas, it's just a shame that the JavaScript doesn't have very strong getter/setter/subscripting functionality so you could implement data structures like JavaScript arrays completely in native JavaScript.
- polos 17y agoTry to use additional single quotes: var x = []; x['3'] = 3; x['"3"'] = "three"; alert(x);
- invisible 17y agox is an Array (which should only accept numerics for keys). E.g. you cannot have a String be a "key" in an Array. However, for an Object (if they used {} instead of []), the property gets converted using String() before being assigned, so you cannot have duplicate values with the same String value. This actually makes sense when you consider that JavaScript isn't a hard typed language and you often don't need to type cast (which comes in handy more often than it fails a programmer). My opinion: this guy is complaining just to complain, he could throw a _ before that 1 String and it solves his type problem completely.
- s3graham 17y agoI get the impression you don't know JS any better than I do. [] and {} seem to be identical, except that [] one auto-increments a key-as-string in its initialization syntax. Yes, an _ before the string would fix that particular interactive session, but it's not going to work in general.
- invisible 17y ago[] creates an Array (a special instance of an Object which has a completely different prototype). {} creates an Object with no special methods except ones that apply to all types in JavaScript. I'm pretty good at JS - I swear. In general, most don't use the same String value for a key/index to store different values. Just my opinion on that one, though. Oh, and: you can use Firebug to effectively see the difference between the two. >>> x = ["1"]; ["1"] >>> x = {"1": "1"}; Object 1=1
- s3graham 17y ago> I'm pretty good at JS - I swear. Sorry, didn't mean to be a dick. :) This particular wart apparently got my nerd rage going. > In general, most don't use the same String value for a key/index to store different values Agreed, it'd generally be pretty sketchy. My current puttering around project is a "Python-in-JS" in the vein of http://objective-j.org/ http://objective-j.org/ which is where the desire for a "map" rather than an "object" comes from.
- jrockway 17y agoThis is the danger of syntax minimalism; using the same operator to refer to elements of both arrays and dictionaries. Perl has implicit type conversions similar to those of JavaScript, but the syntax of the dereference operation makes it clear what's going on: $array[$number] $array[0] $array['0'] $hash{$key} $hash{'42'} $hash{42} Even without the obvious variable names, you can tell from the syntax what is going to be converted to a number and what is going to be converted to a string; [] means number and {} means string. Javascript is stuck with the same syntax for both: array[number] array[42] array["42"] hash[key] hash[42] hash["42"] which is apparently somewhat confusing. I know what is going to happen, but the language doesn't help me; it's easy to write code that's misleading.
- axod 17y agoSorry, but that's wrong. I don't think there's any ambiguity at all. JS only has string keys, and only has objects. An array in js is just an object/dictionary, with a special 'length' property, and a few convenience methods. Further, the 'length' property can also be confusing to newcomers, since it doesn't relate to the number of elements in the array, rather the maximum key that can be converted to an integer +1. For example, var arr = []; arr.foo = "hello"; arr[4] = 56; // arr.length = 5 It's much easier when you understand that arrays in javascript don't really exist as a separate data type. They are, as I say, just objects with a couple of convenience methods+length property.
- s3graham 17y agoI think I agree with jrockway. I understand (now) that there's only string keys in objects, but that's the random part. Why have [] syntax for "arrays" then? It's the hashing behaviour that's the 'gotcha'. Sure, x.a should stringize 'a' to make property access work cleanly, but why when using the indexing syntax? For example: sgraham@gerard:~$ lua Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio > a = {} > a[0] = "wee" > a[1] = "waa" > a["1"] = "str" > print(a[0]) wee > print(a[1]) waa > print(a["1"]) str > > a["x"] = "wee" > a.x = "waa" > print(a["x"]) waa > print(a.x) waa > which seems wholly more reasonable.
- axod 17y agoRead a book on javascript. "Javascript: The definitive guide" by O'Reily is the best. This is not a quirk, Arrays are just objects with a special property 'length' which is set to the highest key that can be converted to an integer, plus one, and the array functions. All keys are however, strings, as with all objects. For example, var arr = []; arr.foo = "hello"; arr["hello"] = function() {}; arr[40] = 56; // arr.length = 41 It's much easier when you understand that arrays in javascript don't exist as a separate data type. They are, as I say, just objects with a couple of convenience methods+length property.
- deleted 17y ago[deleted]