On the official documentation of JSON
An object is an unordered set of name/value pairs. An object begins
with { (left brace) and ends with } (right brace). Each name is
followed by : (colon) and the name/value pairs are separated by ,
(comma).
Note
I am Javascript newbie, and from the name JSON (Javascript object notation) itself, I am assuming objects in Javascript are same as JSON. Please correct me in case I have got it wrong.
From the above definition it seems the Javascript objects are most probably implemented by either a hashmap or a BST or some similar data-structure.
But when I insert key value pairs in Node shell, they are inserted in serialised manner. This is what I tried in node shell
> var a = {}
undefined
> a['k1'] = 'a1'
'a1'
> a['k3'] = 'a3'
'a3'
> a['k2'] = 'a2'
'a2'
> a['k4'] = 'a4'
'a4'
> a['k5'] = 'a5'
'a5'
> a
{ k1: 'a1',
k3: 'a3',
k2: 'a2',
k4: 'a4',
k5: 'a5' }
Now, on printing a the key value pairs are returned in the same order as that of insertion. So my questions are:
Do I get fast lookups for a key? I mean complexity of O(log(n)) or better.
In case JSON is not using a data-structure like a BST, hashmap or some similar DS, then how exactly are JSON objects layed under the memory?
Update
Ok, so what about Javascript objects. Can someone comment on the underlying implementation of Javascript objects.
You're confusing JSON, which is only a text-based serialization format enabling simple data exchange, and plain javascript objects, which are unordered lists of properties.
As said by the MDN :
An object is a collection of properties, and a property is association
between a name and a value. A value of property can be a function,
which is then known as the object's method.
Objects properties can be seen as hash maps, as they're not ordered. But it's often a little more complicated : when objects are prototype based, properties not found on an object are searched upward the prototypes it's based on.
With javascript objects you get a guaranteed fast look-up, as this is an essential part of the implementation. But the implementation isn't defined by the norm and each engine can have its own.
Update
Starting from ES6, which you have in almost all browsers and JS servers in 2021, the order of non integer keys in object is the insertion order.
Related
Basically I'm doing practice exercises where I need to list the properties of an object, and I've done this:
/* Write a JS program to list the properties of a JS object*/
console.log("EX 1");
let student = {
name: "Dollar",
job: "Unemployed",
age: 18
};
let listing = Object.getOwnPropertyNames(student); // lists the properties of a JS object
console.log(listing.toString());
The output seems correct, but when I go to the resolution, it uses functions and if statements(if needed I'll provide them).
Is anything wrong with my code?
In your example code, listing is already a list of the properties of the object, meaning the names of the keys of all key-value pairs in the dict-like structure.
There doesn't seem to be a good reason to use .toString() to convert the list itself into a string.
The goal of the comment "Write a JS program..." is probably simply to get you to write a for-loop to loop through the object, which is iterable.
for (let item of obj1) {
console.log(item);
}
I'm reading this article about V8 on HTML5Rocks. The article is old but I understand almost none of it and it bothers me. I'm taking this 1 step at a time but could someone help me with the Arrays section?
The article states:
Arrays
In order to handle large and sparse arrays, there are two types of
array storage internally:
Fast Elements: linear storage for compact key sets
Dictionary Elements: hash table storage otherwise
It's best not to cause the array storage to flip from one type to
another.
Question:
What would a Fast Elements linear storage array look like?
What would a Dictionary Elements hash table array look like?
For prevention purposes, how would I "flip from one type to another"?
I will go a little other way round.
2) What would Dictionary Elements hash table Array look like?
A JavaScript object is a map from string to values. e.g.
var obj = {
"name": "Sherlock Holmes",
"address": "221B Baker Street"
}
V8 uses hash tables to represent objects unless using an optimized representation for special cases. This is much like a dictionary uses (words, meaning) pair.
Now, this hash table access is slow because initially all the keys and values in a hash table are undefined. On inserting a new pair, a hash is computed and the pair inserted at the insertion index. If there's already a key at that index, attempt to insert at next one and so on.
1) What would Fast Elements Linear storage Array look like?
In V8, an element is a property whose key is a non-negative integer (0, 1, 2, ...) i.e. a simple linear array whose properties can be accessed via a numerical index.
Fast elements are stored in a contiguous array. e.g.
var arr = [1, 2, 3];
They are a special case that is optimised for faster access as the index is already known and not to be computed.
3) For prevention purposes, How would I flip from one type to another?
For fast element, if you assign an index that's way past the end of the elements array, V8 may downgrade the elements to dictionary mode.
Reference: http://jayconrod.com/posts/52/a-tour-of-v8-object-representation
sir i can be wrong but according to your question what i have observed is explained
when we initialise an array it internally gets key as 0,1,2....etc as i pushed element with value its into array but array does not consider it
ex :
var arr = new Array()
arr[0] = 1
arr[1] = 2
arr[2] = "myname";
arr['myname'] = nick;
but when i do arr.length i get 3 so it does not consider the key apart from numeric but if i write arr[3] = {myname:'nick'} then it consider it as elements.
internally i think to keep the linear array different it looks for '{}'
I have an application in PHP and JS. When I EVAL the json encoded PHP array the array sort changes. For example, if I have an array in PHP like this:
<?php
$array = [148 => 'Plane', 149 => 'Car'];
?>
<script>
var array = eval(<?php echo json_encode($array)?>);
</script>
When I print the array in console, the elements doesn't have the same position. Do you know how can this happens?
UPDATE
Thanks for the answers but I want to keep the exactly same order in a JS structure, so I don't want to order the array by a specific field. Maybe the order get from the DB is like:
[148 => object, 155 => object, 133 => object]
I want to create an array like this in JS with the order that it has (the position come from DB and it has to be that order). Is it possible?
<?php echo json_encode($array)?>
Since the array is sparse, this resolves to
{"148":"Plane","149":"Car"}
which is an object and object property order is not guaranteed in JS.
http://php.net/manual/en/function.json-encode.php
Note:
When encoding an array, if the keys are not a continuous numeric sequence starting from 0, all keys are encoded as strings, and specified explicitly for each key-value pair.
You can solve this by creating an array from the object, like this:
var obj = <?php echo json_encode($array)?>; // note, eval not needed
var arr = [];
Object.keys(obj).forEach(function(key) {
arr[key] = obj[key];
});
Concerning the update:
You need to save the order of the keys separately.
var order = <?php echo json_encode(array_keys($array))?>;
var obj = <?php echo json_encode($array)?>;
order.forEach(function(key) {
console.log(key, obj[key]); // or whatever you need
});
You can even construct an ordered map (which PHP's arrays actually are, unlike the arrays in JS) if you use ES6 or a polyfill.
The earlier posters have already answered the question. Just to add to it:
Many people get confused because they think of Javascript Objects as associative arrays in PHP. However that is quite not the case. While its true that we can (sort of) simulate a data structure close to a PHP associative array by using objects in Javascript, they are totally different data structures and do not work quite the same way as arrays do.
In arrays the integrity of index position is important from a data structure and index relation perspective, which is why their order is maintained. However the same rule does not matter to objects since their "pseudo-named-index" (which really is just the property name), is not place-dependent. It can exist in any order as long as that property still has the same value assigned to it.
Hope this helps.
There are two types of JSON data structures you should distinguish here. Make sure the JSON parser is putting your data into the structure you want. I'd suggest it's probably putting it into an object, not an array.
Plagiarizing directly from this answer: From RFC 7159 -The JavaScript Object Notation (JSON) Data Interchange Format (emphasis mine):
An object is an unordered collection of zero or more name/value pairs, where a name is a string and a value is a string, number, boolean, null, object, or array.
An array is an ordered sequence of zero or more values.
The terms "object" and "array" come from the conventions of JavaScript.
And further quoting from this answer:
The order of elements in an array ([]) is maintained. The order of elements (name:value pairs) in an "object" ({}) is not, and it's usual for them to be "jumbled", if not by the JSON formatter/parser itself then by the language-specific objects (Dictionary, NSDictionary, Hashtable, etc) that are used as an internal representation.
I'm serializing a bunch of objects user Django Rest Framework and retrieving the information with angularjs on the frontend. When I check the response in the browser, my array of objects that get returned have all their fields in alphabetical order rather then the ordering instructions I gave in the backend.
What is forcing this alphabetical ordering? Django Rest Framework or angularjs? This ordering is messing up my table I'm trying to create.
data['objects'] = serializer.data
print data['objects'][0]
return Response(data)
Print output from django
{'hard_weight': 0L, 'current_count': 8020L, 'mileage': 0L, 'route_type': None, 'route': u'NO SCHEDULE', 'destination': None, 'pickup_id
': 657L, 'specials': 900000L, 'soft_weight': 0L, 'misses': 0L, 'date': datetime.date(2030, 12, 31), 'estimated_hours': Decimal('0.00'),
'estimated_hours_unload': Decimal('0.00'), 'cancel': False}
console.log of returned data:
cancel: false
current_count: 8020
date: "2030-12-31"
destination: null
estimated_hours: "0.00"
estimated_hours_unload: "0.00"
hard_weight: 0
mileage: 0
misses: 0
pickup_id: 657
route: "NO SCHEDULE"
route_type: null
soft_weight: 0
specials: 900000
Update/Solution
I ended up writing this function to take in each one of my objects and put them in an array in order of a given list.
function convertObjects(objects, list){
blank = []
for(var i=0; i <objects.length; i++)
{
obj = []
object = objects[i]
for (var j=0; j<=list.length; j ++)
{
obj.push(object[list[j]])
};
blank.push(obj)
};
return blank
}
Ordinarily, the dictionary / map / key-value data structure doesn't store or care about the order of the keys. Two dictionary with the same key-values, but in different orders, are considered identical. You might even say there's no such thing as key order in a dictionary (There are implementation of dictionaries that preserve order though)
If the order in which you display them to the end user is important, e.g. in a UI table, you'll have to get the keys of your object, order them, and then go through your object with each key to get the value you want, http://underscorejs.org/ library has keys and sort utils for you to use
The ordering is not do to either Django or AngularJS, it is happening in the browser due to the fact that JavaScript objects have no specified order. See the ECMAScript specification, particularly section 4.3.3:
4.3.3 object
member of the type Object
NOTE An object is a collection of properties and has a single
prototype object. The prototype may be the null value.
Note that it does not specify an order for the collection of properties.
Also relevant is the specification defining object property enumeration in section 12.6.4
The mechanics and order of enumerating the properties (step 6.a in the
first algorithm, step 7.a in the second) is not specified.
You will have to customize the order on the client side in AngularJS. However, note that the orderBy filter only works on Arrays. See this answer for creating a custom directive to order object properties:
https://stackoverflow.com/a/18186947/1870541
I've noticed the order of elements in a JSON object not being the original order.
What about the elements of JSON lists? Is their order maintained?
Yes, the order of elements in JSON arrays is preserved. From RFC 7159 -The JavaScript Object Notation (JSON) Data Interchange Format
(emphasis mine):
An object is an unordered collection of zero or more name/value
pairs, where a name is a string and a value is a string, number,
boolean, null, object, or array.
An array is an ordered sequence of zero or more values.
The terms "object" and "array" come from the conventions of
JavaScript.
Some implementations do also preserve the order of JSON objects as well, but this is not guaranteed.
The order of elements in an array ([]) is maintained. The order of elements (name:value pairs) in an "object" ({}) is not, and it's usual for them to be "jumbled", if not by the JSON formatter/parser itself then by the language-specific objects (Dictionary, NSDictionary, Hashtable, etc) that are used as an internal representation.
Practically speaking, if the keys were of type NaN, the browser will not change the order.
The following script will output "One", "Two", "Three":
var foo={"3":"Three", "1":"One", "2":"Two"};
for(bar in foo) {
alert(foo[bar]);
}
Whereas the following script will output "Three", "One", "Two":
var foo={"#3":"Three", "#1":"One", "#2":"Two"};
for(bar in foo) {
alert(foo[bar]);
}
Some JavaScript engines keep keys in insertion order. V8, for instance, keeps all keys in insertion order except for keys that can be parsed as unsigned 32-bit integers.
This means that if you run either of the following:
var animals = {};
animals['dog'] = true;
animals['bear'] = true;
animals['monkey'] = true;
for (var animal in animals) {
if (animals.hasOwnProperty(animal)) {
$('<li>').text(animal).appendTo('#animals');
}
}
var animals = JSON.parse('{ "dog": true, "bear": true, "monkey": true }');
for (var animal in animals) {
$('<li>').text(animal).appendTo('#animals');
}
You'll consistently get dog, bear, and monkey in that order, on Chrome, which uses V8. Node.js also uses V8. This will hold true even if you have thousands of items. YMMV with other JavaScript engines.
Demo here and here.
"Is the order of elements in a JSON list maintained?" is not a good question. You need to ask "Is the order of elements in a JSON list maintained when doing [...] ?"
As Felix King pointed out, JSON is a textual data format. It doesn't mutate without a reason. Do not confuse a JSON string with a (JavaScript) object.
You're probably talking about operations like JSON.stringify(JSON.parse(...)). Now the answer is: It depends on the implementation. 99%* of JSON parsers do not maintain the order of objects, and do maintain the order of arrays, but you might as well use JSON to store something like
{
"son": "David",
"daughter": "Julia",
"son": "Tom",
"daughter": "Clara"
}
and use a parser that maintains order of objects.
*probably even more :)