Does JSON always need curly braces at the top level? - javascript

I've been learning a bit about JSON lately and was trying to understand if it always needs curly braces at the top level or if it can also be an array? Or would the array have to be wrapped in curly braces with a key name and then the array as a value?
For instance, does it have to be this:
{"title":"title 1"}
or could it be this as well:
[1,2,3]
I'm asking in the context of what the spec allows and consumers of the json file might expect, as typically from examples I've seen it, it's always curly braces with key-value pairs inside

The original specification said:
A JSON text is a serialized object or array.
… meaning that the top level needed to be either {} or [].
Many implementations ignored that restriction and allowed any JSON data type (object, array, number, string, boolean, null) to be used at the top level.
The updated specification says:
A JSON text is a serialized value. Note that certain previous
specifications of JSON constrained a JSON text to be an object or an
array. Implementations that generate only objects or arrays where a
JSON text is called for will be interoperable in the sense that all
implementations will accept these as conforming JSON texts.
So now any JSON data type is allowed at the top level, but you need to be aware that some older software might not support anything except objects and arrays at the top level.

It can be array, need not to be in curly braces
console.log(JSON.stringify([1,2,3]));
Here's more

it can be of the following:
null
boolean
number
array
object
String: only if its enclosed in quotes
Examples:
JSON.parse('{}'); // {}
JSON.parse('true'); // true
JSON.parse('"foo"'); // "foo"
JSON.parse('[1, 5, "false"]'); // [1, 5, "false"]
JSON.parse('null'); // null

Related

What is happening under the hood in javascript when using the Array brackets notation

I have generally found javascript to be transparent, in that there are very few black boxes where "magic" just happens and you should just accept and look the other way, however I have not found any answer to how the Array brackets [] notation actually works under the hood.
let arr = [4, 5, 6, 7]
console.log(arr[3]) // <- How does this work?
What is javascript doing to access the item at index 3. Does it internally call some method on the Array.prototype?
With an object, the [] is a shortcut for a property accessor.
let obj = {
a: 'hello',
b: 'world'
}
obj['a'] === obj.a // true
Is an array then just an object with a long list of integer based properties?
let objArray = {
0: 'hello',
1: 'world'
}
let realArray = ['hello', 'world']
objArray[0] === 'hello' // true
realArray[0] === 'hello' // true
objArray.0 // SyntaxError: Unexpected number
realArray.0 // SyntaxError: Unexpected number
I have seen many many online discussions that all come to the conclusion that you cannot overload the brackets notation to truly subclass an Array but I have never seen an explanation on what magic is happening under the hood that allows the Array to work the way it does.
The obvious follow up question is whether there is any way to intercept the bracket notation access to define your own behavior, but I think I already know the answer to that.
You'd probably have to look at the implementation code to know precisely what's going on, but the basic idea is that arrays are actually layered atop objects.
This is backwards:
With an object, the [] is a shortcut for a property accessor.
The bracket notation is more fundamental. Thus, obj['foo'] and obj.foo work the same, but there is no equivalent for obj['foo & bar'], which is perfectly legitimate, and will respond with a value if obj has a key named "foo & bar".
Is an array then just an object with a long list of integer based properties?
Not quite, but you're not far off. Arrays are objects with the Array prototype, and with a little bit of additional magic to set the length property when new keys are added, or remove keys when that length is set.
And no, you cannot override the [] operator for your own purposes.
Is an array then just an object with a long list of integer based properties?
Yes, in it's simplest form, an Array is an Object with a list of integer base properties that is based on the Array prototype (which gives access to all the array methods like map, forEach, etc.)
As for intercepting the bracket notation, no, I have not seen anything that would allow that besides creating your own Object that has the methods you need (and then only access that object via the appropriate methods).
More info from MDN:
Arrays are list-like objects whose prototype has methods to perform traversal and mutation operations. Neither the length of a JavaScript array nor the types of its elements are fixed. Since an array's length can change at any time, and data can be stored at non-contiguous locations in the array, JavaScript arrays are not guaranteed to be dense; this depends on how the programmer chooses to use them. In general, these are convenient characteristics; but if these features are not desirable for your particular use, you might consider using typed arrays.
Arrays cannot use strings as element indexes (as in an associative array) but must use integers. Setting or accessing via non-integers using bracket notation (or dot notation) will not set or retrieve an element from the array list itself, but will set or access a variable associated with that array's object property collection. The array's object properties and list of array elements are separate, and the array's traversal and mutation operations cannot be applied to these named properties.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Indexed_collections#Array_object

Valid property names, property assignment and access in JavaScript

Updated Question
What, exactly, qualifies as a valid property name in Javascript? How do various methods of property assignment differ? And how does the property name affect property access?
Note
The answers to my original question (seen below) helped to clear some things up, but also opened a new can of worms. Now that I've had a chance to become a bit more familiar with JavaScript, I believe I've been able to figure a lot of it out.
Since I had a hard time finding this information consolidated into one explanation, I thought it might be helpful to expand my original question, and attempt to answer it.
Original Question
Originally, there was some confusion with the MDN JavaScript guide (object literals). Specifically, I wondered why they claimed that if a property name was not a valid JavaScript identifier, then it would have to be enclosed in quotes. Yet, they offered example code that showed that the number 7 could be used — without quotes — as a property name.
As it turns out, the guide simply left off one important part, and Pointy updated it (changes in bold):
If the property name would not be a valid JavaScript identifier or number, it must be enclosed in quotes.
I also wondered why property names were allowed to deviate away from the "may not start with a digit" rule, that applies to identifiers. That question actually reveals the complete misunderstanding that I had of property names, and is what lead me to do some more research.
Answer for 1st question:
Yes, the statement given in the MDN guide is not 100% accurate, but in your daily work it'd be better to follow it as rule. You really don't need to create properties names which are numbers.
Answer for 2nd question:
A property name may not start with a digit but a property name that is a number without any other characters in its name is fine.
This exception exists because the properties with number for name as the same as indexes.
Let's try this:
var obj = {7: "abc"};
obj[7]; // works fine
obj.7; // gives an error (SyntaxError)
Now try to call Array.push on the object and observe what happens:
Array.prototype.push.call(obj, "xyz");
console.log(obj);
console.log(obj[0]);
// Prints
Object {0: "xyz", 7: "abc", length: 1}
"xyz"
You can see that few new properties (one with name 0 and another with name length) have been added to the object. Moreover, you can use the object as an array:
var obj = { "0": "abc", "1": "xyz", length: 2 };
Array.prototype.pop.call(obj); // Returns: "xyz"
Array.prototype.pop.call(obj); // Returns: "abc"
You can use array's methods on objects and this is called Duck Typing.
Arrays are nothing more than objects with some predefined methods.
From MDN:
Array elements are object properties in the same way that length is a property, but trying to access an element of an array with dot notation throws a syntax error, because the property name is not valid. There is nothing special about JavaScript arrays and the properties that cause this. JavaScript properties that begin with a digit cannot be referenced with dot notation and must be accessed using bracket notation.
Now you can understand why a number for property name is valid. These are called just indexes and they are used in JavaScript arrays. And since JavaScript needs to be consistent with other languages, numbers are valid for indexes/properties names.
Hope this makes it clear.
Here are some interesting articles:
JavaScript identifiers (in ECMAScript 5)
JavaScript identifiers (in ECMAScript 6)
Short Answer
Object property names can be any valid identifier, numeric literal, or string literal (including the empty string).
With that said, there are some potentially confusing intricacies to keep in mind about JavaScript property names, as described below.
And unless you're working with valid (non-negative integer) array indexes, it's a good idea to explicitly assign all numerical property names as strings.
Negative Numbers
What might look like a negative number is actually an expression — something property names do not support.
// SyntaxError
const obj = { -12: 'nope' };
Fortunately, bracket notation handles expressions for us.
// Successful property assignment.
const obj = {};
obj[-12] = 'yup';
Typecasting
All property names are typecasted into strings before being stored.
const obj = {
12: '12'
};
console.log(typeof Object.keys(obj)[0]); // -> string
Parsing
But even before typecasting occurs, keys are parsed according to the syntax used, and transformed into a decimal literal.
const obj = {
// Valid string literal
'022': '022',
// Interpreted as decimal
6: '6',
// Interpreted as floating-point
.345: '0.345',
// Interpreted as floating-point
1.000: '1',
// Interpreted as floating-point
8.9890: '8.989',
// Interpreted as decimal
000888: '888',
// Interpreted as octal
0777: '511',
// Interpreted as hexadecimal
0x00111: '273',
// Interpreted as binary
0b0011: '3',
};
/* Quoted property name */
console.log(obj['022']); // "022"; as expected
console.log(obj[022]); // undefined; 022 is an octal literal that evaluates to 18 before our lookup ever occurs
/* Valid (non-negative integer) array index */
console.log(obj[6]); // "6"; as expected
console.log(obj['6']); // "6"; as expected
/* Non-valid array index */
console.log(obj[0x00111]); // "273"; we're accessing the property name as it was assigned (before it was parsed and typecasted)
console.log(obj['0x00111']); // undefined; after parsing and typecasting, our property name seems to have disappeared
console.log(obj['273']); // "273"; there it is, we found it using the evaluation of our original assignment

array and object confusion in json

what is the different between is
var json = [{
'id':1,
'name':'John'
}]
and
var json = {
'id':1,
'name':'John'
}
my understanding is that in code one json is an array, which means we can have multiple object which contains property of id and name. But for the second one it's an object. Is it?
and how about this one
var json = ['id':1,'name':'John']
compare to code one?
Nothing is valid JSON in your case.
The first one is an array of native javascript objects.
The second one is a javascript object.
The last one isn't valid and will throw error. It is syntactically wrong.
Use JSON.stringify() on javascript arrays or objects to make it a valid JSON.
You understanding about code one and code two are correct.
But however, the json syntax about code one and two is error. Because each json field must use double quotes, not single quotes.
so code one and code two must be written like this:
[
{
"id": 1,
"name": "John"
}
]
and
{
"id": 1,
"name": "John"
}
Now code three's syntax is error! If you want to mean an array, it must be var json = []; json['id']=1; json['name']='John'; or an object var json={'id':1,'name':John'}
JSON is a format, i.e. a way to encode Javascript objects to a sequence of characters.
Once you have a sequence of characters you can store it on disk or send it over a network and later rebuild the objects described in the sequence of characters.
You cannot encode every possible Javascript value in JSON, but only
strings
numbers (excluding NaN and infinity)
null
arrays
other objects (just the fields with values that can be encoded, not the constructor or methods)
Also, the data structure must be a tree. (You get an error if it has loops, and shared sub-trees are not detected and will be duplicated when rebuilding from JSON.)
Moreover JSON doesn't support is the presence of other fields in arrays (something that is possible in Javascript, because arrays are objects). For JSON, you have either an array or an object.
The values in your first two examples can be converted to JSON, but there are additional requirements in the format specifications. (E.g. object field names must be double quoted.)
Your last example instead is not a valid JSON string.
When you see "JSON object" or "JSON value" you must read it as "object encoded in JSON". JSON is a format, more or less like XML.

Javascript object Vs JSON

I want to understand the basic differences clearly between Javascript object and JSON string.
Let's say I create the following JS variable:
var testObject = {one: 1,"two":2,"three":3};
Q1. Is the key/property name valid both with/without quotes? (e.g. "one" : 1)
If yes, what is the difference?
Q2: If I convert the above object using JSON.stringify(testObject), what’s the difference between the original JS object and the JSON?
I feel they are almost the same. Please elaborate on this.
Q3: For parsing a JSON string, is the method below recommended?
var javascriptObj = JSON.parse(jSonString);
Is the key/property name valid both with/without quotes ?
The only time you need to enclose a key in quotes when using Object Literal notation is where the key is a reserved word or contains a special character (if, :, - etc). It is worth noting that a key in JSON must be enclosed in double quotes.
If I convert the above object to JSON using var jSonString = JSON.stringify(testObject);, what is the difference between the 2 (JS obj and JSON)?
JSON is a data interchange format. It's a standard which describes how ordered lists and unordered maps, strings, booleans and numbers can be represented in a string. Just like XML and YAML is a way to pass structured information between languages, JSON is the same. A JavaScript object on the other hand is a physical type. Just like a PHP array, a C++ class/ struct, a JavaScript object is a type internal to JavaScript.
Here's a story. Let's imagine you've purchased some furniture from a store, and you want it delivered. However the only one left in stock is the display model, but you agree to buy it.
In the shop, the chest-of-drawers you've purchased is a living object:
var chestOfDrawers = {
color: "red",
numberOfDrawers: 4
}
However, you can't send a chest-of-drawers in the post, so you dismantle it (read, stringify it). It's now useless in terms of furniture. It is now JSON. Its in flat pack form.
{"color":"red","numberOfDrawers":4}
When you receive it, you then rebuild the chest-of-drawers (read, parse it). Its now back in object form.
The reason behind JSON, XML and YAML is to enable data to be transferred between programming languages in a format both participating languages can understand; you can't give PHP or C++ your JavaScript object directly; because each language represents an object differently under-the-hood. However, because we've stringified the object into JSON notation; i.e. a standardised way to represent data, we can transmit the JSON representation of the object to another language (C++, PHP), they can recreate the JavaScript object we had into their own object based on the JSON representation of the object.
It is important to note that JSON cannot represent functions or dates. If you attempt to stringify an object with a function member, the function will be omitted from the JSON representation. A date will be converted to a string;
JSON.stringify({
foo: new Date(),
blah: function () {
alert('hello');
}
}); // returns the string "{"foo":"2011-11-28T10:21:33.939Z"}"
For parsing a JSON string, is the method below recommended? var javascriptObj = JSON.parse(jSonString);
Yes, but older browsers don't support JSON natively (IE <8). To support these, you should include json2.js.
If you're using jQuery, you can call jQuery.parseJSON(), which will use JSON.parse() under the hood if it's supported and will otherwise fallback to a custom implementation to parse the input.
Q1: When defining object literals in javascript, the keys may include quotes or not. There is no difference except that quotes allow you to specify certain keys that would cause the interpreter to fail to parse if you tried them bare. For example, if you wanted a key that was just an exclamation point, you would need quotes:
a = { "!": 1234 } // Valid
a = { !: 1234 } // Syntax error
In most cases though, you can omit the quotes around keys on object literals.
Q2: JSON is literally a string representation. It is just a string. So, consider this:
var testObject = { hello: "world" }
var jSonString = JSON.stringify(testObject);
Since testObject is a real object, you can call properties on it and do anything else you can do with objects:
testObject.hello => "world"
On the other hand, jsonString is just a string:
jsonString.hello => undefined
Note one other difference: In JSON, all keys must be quoted. That contrasts with object literals, where the quotes can usually be omitted as per my explanation in Q1.
Q3. You can parse a JSON string by using JSON.parse, and this is generally the best way to do it (if the browser or a framework provides it). You can also just use eval since JSON is valid javascript code, but the former method is recommended for a number of reasons (eval has a lot of nasty problems associated with it).
Problems solved by JSON
Let's say you want to exchange regular JavaScript objects between two computers, and you set two rules:
The transmitted data must be a regular string.
Only attributes can be exchanged, methods are not transmitted.
Now you create two objects on the first host:
var obj1 = { one: 1,"two":2,"three":3 }; // your example
var obj2 = { one: obj1.one, two: 2, three: obj1.one + obj1.two };
How can you convert those objects into strings for transmission to the second host?
For the first object, you could send this string obtained form the literal definition '{ one: 1,"two":2,"three":3 }', but actually you can't read the literal in the script portion of the document (at least not easily). So obj1 and obj2 must actually be processed the same way.
You need to enumerate all attributes and their value, and build a string similar to the object literal.
JSON has been created as a solution to the needs just discussed: It is a set of rules to create a string equivalent to an object by listing all attributes and values (methods are ignored).
JSON normalizes the use of double-quotes for attribute names and values.
Remember that JSON is a set of rules only (a standard).
How many JSON objects are created?
Only one, it is automatically created by the JS engine.
Modern JavaScript engines found in browsers have a native object, also named JSON. This JSON object is able to:
Decode a string built using JSON standard, using JSON.parse(string). The result is a regular JS object with attributes and values found in the JSON string.
Encode attributes / values of a regular JS object using JSON.stringify(). The result is a string compliant with the JSON set of rules.
The (single) JSON object is similar to a codec, it's function is to encode and decode.
Note that:
JSON.parse() doesn't create a JSON object, it creates a regular JS object, there is no difference between an object created using an object literal and an object created by JSON.parse() from a JSON-compliant string.
There is only one JSON object, which is used for all conversions.
Going back to the questions:
Q1: The use of single of double quotes is allowed for object literals. Note that the quotes are used optionally for attributes names, and are mandatory for string values. The object literal itself is not surrounded by quotes.
Q2: Objects created from literals and using JSON.parse() are strictly the same. These two objects are equivalent after creation:
var obj1 = { one: 1, "two": 2, "three": 3 };
var obj2 = JSON.parse('{ "one": "1", "two": "2", "three": "3" }');
Q3: On modern browsers JSON.parse() is used to create a JS object from a JSON-compliant string. (jQuery has also an equivalent method that can be used for all browsers).
Q1 - in JS you only need to use quotes if the key is a reserved word or if it would otherwise be an illegal token. In JSON you MUST always use double quotes on key names.
Q2 - the jsonString is a serialised version of the input object ...
Q3 - which may be deserialised to an identical looking object using JSON.parse()
Question already has good answers posted, I am adding a small example below, which will make it more easy to understand the explanations given in previous answers.
Copy paste below snippet to your IDE for better understanding and comment the
line containing invalid_javascript_object_no_quotes object declaration to avoid compile time error.
// Valid JSON strings(Observe quotes)
valid_json = '{"key":"value"}'
valid_json_2 = '{"key 1":"value 1"}' // Observe the space(special character) in key - still valid
//Valid Javascript object
valid_javascript_object_no_quotes = {
key: "value" //No special character in key, hence it is valid without quotes for key
}
//Valid Javascript object
valid_javascript_object_quotes = {
key:"value", //No special character in key, hence it is valid without quotes for key
"key 1": "value 1" // Space (special character) present in key, therefore key must be contained in double quotes - Valid
}
console.log(typeof valid_json) // string
console.log(typeof valid_javascript_object_no_quotes) // object
console.log(typeof valid_javascript_object_quotes) // object
//Invalid Javascript object
invalid_javascript_object_no_quotes = {
key 1: "value"//Space (special character) present in key, since key is not enclosed with double quotes "Invalid Javascript Object"
}

Keys in Javascript objects can only be strings?

jshashtable states:
JavaScript's built-in objects do provide hashtable functionality using
the square brackets notation for
properties, provided your keys are
strings or numbers:
From what I know, keys are only strings, (since numbers are coerced into strings anyway). I just want to check and be sure that what is stated above is false (since keys can't be numbers).
Did ECMA standard stated anything about this..
Or is the implementation browser-specific?
JavaScript's built-in objects do provide hashtable functionality using
the square brackets notation for properties, provided your keys are
strings or numbers
That seems to be incorrect - object keys are always strings may be strings or (since ECMAScript 2015, aka ECMA-262 ed 6) symbols. But that is a different topic to square bracket property access.
See ECMA-262 ed 3 § 11.2.1 (Please also see ECMAScript 2017 (draft).):
Properties are accessed by name, using either the dot notation:
MemberExpression . IdentifierName
CallExpression . IdentifierName
or the bracket notation:
MemberExpression [ Expression ]
CallExpression [ Expression ]
The dot notation is explained by the following syntactic conversion:
MemberExpression . IdentifierName
is identical in its behaviour to
MemberExpression [ <identifier-name-string> ]
and similarly
CallExpression . IdentifierName
is identical in its behaviour to
CallExpression [ <identifier-name-string> ]
where <identifier-name-string> is a string literal containing the
same sequence of characters after processing of Unicode escape
sequences as the IdentifierName.
So when using dot notation, the bit after the dot must fit the criteria for an IdentifierName. But when using square brackets, an expression is provided that is evaluated and resolved to a string.
Briefly, square bracket notation is provided so that properties can be accessed using an expression, e.g.
var y = {};
var x = 'foo';
y[x] = 'foo value';
In the above, x is provided in square brackets so it is evaluated, returning the string 'foo'. Since this property doesn't exist on y yet, it is added. The foo property of y is then assigned a value of 'foo value'.
In general terms, the expression in the square brackets is evaluated and its toString() method called. It is that value that is used as the property name.
In the dot property access method, the identifier is not evaluated, so:
y.bar = 'bar value';
creates a property bar with a value bar value.
If you want to create a numeric property, then:
y[5] = 5;
will evaluate 5, see it's not a string, call (more or less) Number(5).toString() which returns the string 5, which is used for the property name. It is then assigned the value 5, which is a number.
Edit
This answer was written when ECMAScript ed3 was current, however things have moved on. Please see later references and MDN.
You're right keys can only be strings, and numeric keys such as those used in Arrays are coerced and stored as strings.
var arr = [true];
arr[0] === true;
arr['0'] = false;
arr[0] === false;
ECMAScript spec, page 42: ECMA-262 Script 3rd Edition.
The production PropertyName : NumericLiteral is evaluated as follows:
Form the value of the NumericLiteral.
Return ToString(Result(1)).
Well, here is my answer -- mostly because I was not satisfied with the references in the other (correct) answers -- expressions for property names in [ ] are always coereced to strings and this behavior is well defined in the specification. Thus, depending upon interpretation of the quote in question, it can be taken as misleading and/or incorrect.
However, the quote does not presume that x[42] and x["42"] are different; it states -- with the misleading exclusion of other primitives and details -- that only strings and numbers are usable as "hash keys" (really property names) under normal property resolution and, in this sense, the quote is arguably correct.
These rules are from Standard ECMA-262 ECMAScript Language Specification 5th edition (December 2009)
From section "11.2.1 Property Accessors" (production rules omitted):
The production MemberExpression : MemberExpression [ Expression ] is evaluated as follows:
Let baseReference be the result of evaluating MemberExpression.
Let baseValue be GetValue(baseReference).
Let propertyNameReference be the result of evaluating Expression.
Let propertyNameValue be GetValue(propertyNameReference).
Call CheckObjectCoercible(baseValue).
Let propertyNameString be ToString(propertyNameValue).
If the syntactic production that is being evaluated is contained in strict mode code, let strict be true, else let
strict be false.
Return a value of type Reference whose base value is baseValue and whose referenced name is
propertyNameString, and whose strict mode flag is strict.
Happy coding.
The keys are always strings. This means you can't use an object instance's identity as a key.
In Flash's ActionScript 3 (uses strong run-time types unlike AS2) there is a Dictionary object which uses strict equality comparison for keys, so that you can use object instances themselves as keys (as well as numbers, strings, etc.).
If you wanted to do the same thing in JavaScript, it would be difficult, because you'd have to generate your own unique object ids and attach them to every object you wanted to track. Some have suggested adding a prototype function to the Object class, but that would add overhead to every object unnecessarily. In any case, you'd want to give an object a trackable ID via a function call that assigns an incrementing static number to a unique property such as "__objectid__".
It would then be conceivable to create a Dictionary-like class with methods like Add(key,value), but it would have to store strings, numbers, and objects in three separate internal hashes to ensure "3" doesn't collide with the number 3 or the object with id 3. The add method would have to automatically assigned an __objectid__ to any key of type object that didn't already have an id assigned. Even after all that, you wouldn't be able to access the dictionary using brackets, unless there are some hooks for property assignments that I'm not aware of in JavaScript.
Here is a functor Array. It is useful when using a Functional Programming paradigm.
javascript:
alert(["Using ",window.navigator.userAgent] );
FunctorRA=[]; f=function(){return f}; g=function(x){return x};
FunctorRA[f]=43;
FunctorRA[g(function(){})]="generic";
FunctorRA[g(g)]="idempotent";
alert(FunctorRA);
for (i in FunctorRA)
alert([ "Functor[ ", i,
"]'s\n\n value is \n\n", FunctorRA[i]].join(""));
displays:
Using ,Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.3) Gecko/20100423
Ubuntu/10.04 (lucid) Firefox/3.6.3
an empty alert and then:
Functor[ function () {
return f;
}]'s
value is
43
etc.
Note Bene:
alert( FunctorRA ) shows .toString() does not enumerate non-numeric indexes
FunctorRA is a generic object in array's "clothing"
there is no direct . syntactic equivalent ( even with string eval coercion )
see Dynamic function name in javascript? for details on how :, a colon, can be embedded in a function name even though it is usually a delimiter to syntactically delineate initializer properties, labels, ?: (conditional expressions) etc. An analogous problem exists with . requiring the escaping of all syntactically significant JavaScript character codes such as (){}\n ., ... . The [] construct effectively does this for the parenthetically contained expression, as a whole, presumably by deferring the evaluation of the string to be an object of type String. This is similar to the fact 43.x=2 is verboten but not if 43 is represented as an object of type Number by (43).x=2 or 43["x"]=2.
(proof: javascript:alert( [ (43).x=2, 43["x"]=2 ] ) displays 2,2 but javascript:alert(43.x=2) generates an error).
Yes, keys can be numbers. In fact, the specification utilizes the same generic mapping functions for both Objects and Arrays.
Well everything that you use for the key is converted to string because of hashing function that hashes strings to a nearly unique short set of bytes that can be interpreted as an integer, cause integer comparison during the linear search is low level and fast.(JavaScript objects are hash tables). You stringify objects and arrays to use them as a key. Keys can be unlimited in size. But beware, cause javascript objects are unordered.
Yesterday and today, I've tried to wrap my head around the problems appearing in this domain and I've written these solutions.
First one is a custom implementation of a hash table, http://stamat.wordpress.com/javascript-quickly-find-very-large-objects-in-a-large-array/
And there everything is explained in laymans terms...
other one is an upgrade to the first one, and it is a deterministic JSON stringify, that stringifies objects with alphabetically ordered properties: http://stamat.wordpress.com/2013/07/03/javascript-object-ordered-property-stringify/
Check it out :)
JavaScript's built-in objects do provide hashtable functionality ...
Yes, kind of. Objects are by definition just a collection of key-value pairs (whereas keys are strings or Symbols). However as they are used like lookup tables by a lot of people, most engines will choose a hashtable like datastructure for implementing objects internally (in some cases). So yes, you can use objects as a hashtable (but it is not guaranteed that the engine will actually use a hashtable under the hood).
your keys are strings or numbers ...
No. Numbers will be casted to string when used as object keys, just as any other value. Therefore you can use Objects as a hashtable for numbers, and for strings, but not for both at the same time:
{ "1": true }[1] // true
If you need a Hashtable for arbitrary / mixed values, a Map or a Set will be the better choice, especially because they guarantee O(1) lookup time.

Categories