If I define something like following:
var groups={
'group_one': ['red','green','blue'],
'group_two': ['yellow','black'],
'group_three': ['white', 'pink','purple','orange']
}
Is it an normal js object or an hash table? If it is not a hash table, then how does the Javascript hash table look like?
I can access a group by:
my_group=groups['group_two']
It is an object, that's how specification refers to it. An object is a data type in JavaScript.
A hash table [Wikipedia] is a data structure for which you could use objects, but it does not handle duplicate keys well (it just overrides the entry). You can provide your own implementation, for example have a look at the Hash Map implementation from the Google Closure Library.
Your groups variable refers to a perfectly normal object, which like all normal javascript objects are associative arrays that map property names to property values. These are often implemented as hashtables under the hood.
As far as I know, JavaScript does not have hash tables as such. You have good old zero-based numeric arrays:
var a = ["foo", "bar"];
alert(a[0]); // "foo"
... and you have objects:
var b = {
x: "foo",
y: "bar
};
alert(b.x); // "foo"
Arrays are sorted by key and cannot have gaps. Objects are not sorted. And they share the square brackets syntax:
alert(a[0]);
alert(b[x]); // same as b.x
I suppose that JavaScript engines make heavy use of hash tables in their internals but JavaScript engines are not normally written in JavaScript ;-)
If you want the typical capabilities of a hash table, where you provide a key and data and you can then get the data back by providing the key, then a javascript object provides that capability using properties on the object.
Internally to the javascript engine is a property lookup algorithm for objects that likely resembles what is used with a hash table (though the particular implementation is not important as it has the appropriate function).
There is no separate hash table in the language. One could be implemented, but there is rarely a point as an object typically provides what is needed.
In your data:
var groups= {
'group_one': ['red','green','blue'],
'group_two': ['yellow','black'],
'group_three': ['white', 'pink','purple','orange']
}
You can access data in the future with:
groups.group_one
or
groups['group_one']
and both will evaluate to:
['red','green','blue']
Related
Are there any formal proposals, in progress, that address a backwards-compatible evolution to JSON's current treatment of Map objects?
For example, let say you want to convert a Map to JSON and then write it to file:
let map = new Map();
map.set(1, "A");
map.set(2, "B");
map.set(3, "C");
// Convert map to an "array of 2-element arrays":
let arrayFromMap = [... map];
let json = JSON.stringify(arrayFromMap);
writeJSONtoFile(json,"path/to/jsonFile.json");
So now we have a JSON file sitting on the disk. The issue is that, the code that ultimately reads this file has no knowledge that it contains a Map object unless we give that code-file that awareness. There is nothing inherent in JSON to explicitly indicate Map instead of a "array of 2-element arrays". For example, code not having this awareness might do this:
let json = readJSONfromFile("path/to/jsonFile.json");
let parsedJSON = JSON.parse(json);
console.log(parsedJSON); // outputs an "array of 2-element arrays"
However, if the the code writer gives the code awareness (that the original type was a Map) the file can be converted back to a Map:
let json = readJSONfromFile("path/to/jsonFile.json");
let map = new Map(JSON.parse(json));
This same awareness isn't necessary for these built-ins: Objects and Arrays.
In the example above, this "awareness" requirement isn't too burdensome. However, imagine a large hierarchy that contains both Maps and "arrays of 2-element arrays" that are not intended to be Maps. This "awareness burden" has now extended to each nested Map within the hierarchy.
Are there any formal proposals, in progress, that address a backwards-compatible evolution to JSON's current treatment of Map objects?
No, because JSON notation, while it originated with Javascript, is widely used in a very large number of languages, but a Javascript Map only has meaning within the context of Javascript.
Any sort of change to JSON notation to allow for the serialization and deserialization of objects that only have meaning in Javascript would make that JSON format incompatible with most other languages.
This isn't to say that a custom parser based on JSON couldn't be written to properly serialize and deserialize Maps, but such a thing would only be based on JSON, rather than being an addition to the JSON standard.
Like CertainPerformance's answer, it's important that JSON remain as abstract as possible for the sake of portability and compatibility.
Wanted to add that keeping the integrity of the Map objects inside of a JSON object is really simple anyway without having to add a new specification; like adding a flag per Map during serialization.
This is more a general question about the inner workings of the language. I was wondering how javascript gets the value of an index. For example when you write array[index] does it loop through the array till it finds it? or by some other means? the reason I ask is because I have written some code where I am looping through arrays to match values and find points on a grid, I am wondering if performance would be increased by creating and array like array[gridX][gridY] or if it will make a difference. what I am doing now is going through a flat array of objects with gridpoints as properties like this:
var array = [{x:1,y:3}];
then looping through and using those coordinates within the object properties to identify and use the values contained in the object.
my thought is that by implementing a multidimensional grid it would access them more directly as can specify a gridpoint by saying array[1][3] instead of looping through and doing:
for ( var a = 0; a < array.length; a += 1 ){
if( array[a].x === 1 && array[a].y === 3 ){
return array[a];
}
}
or something of the like.
any insight would be appreciated, thanks!
For example when you write array[index] does it loop through the array till it finds it? or by some other means?
This is implementation defined. Javascript can have both numeric and string keys and the very first Javascript implementations did do this slow looping to access things.
However, nowadays most browsers are more efficient and store arrays in two parts, a packed array for numeric indexes and a hash table for the rest. This means that accessing a numeric index (for dense arrays without holes) is O(1) and accessing string keys and sparse arrays is done via hash tables.
I am wondering if performance would be increased by creating and array like array[gridX][gridY] or if it will make a difference. what I am doing now is going through a flat array of objects with gridpoints as properties like this array[{x:1,y:3}]
Go with the 2 dimension array. Its a much simpler solution and is most likely going to be efficient enough for you.
Another reason to do this is that when you use an object as an array index what actually happens is that the object is converted to a string and then that string is used as a hash table key. So array[{x:1,y:3}] is actually array["[object Object]"]. If you really wanted, you could override the toString method so not all grid points serialize to the same value, but I don't think its worth the trouble.
Whether it's an array or an object, the underlying structure in any modern javascript engine is a hashtable. Need to prove it? Allocate an array of 1000000000 elements and notice the speed and lack of memory growth. Javascript arrays are a special case of Object that provides a length method and restricts the keys to integers, but it's sparse.
So, you are really chaining hashtables together. When you nest tables, as in a[x][y], you creating multiple hashtables, and it will require multiple visits to resolve an object.
But which is faster? Here is a jsperf testing the speed of allocation and access, respectively:
http://jsperf.com/hash-tables-2d-versus-1d
http://jsperf.com/hash-tables-2d-versus-1d/2
On my machines, the nested approach is faster.
Intuition is no match for the profiler.
Update: It was pointed out that in some limited instances, arrays really are arrays underneath. But since arrays are specialized objects, you'll find that in these same instances, objects are implemented as arrays as well (i.e., {0:'hello', 1:'world'} is internally implemented as an array. But this shouldn't frighten you from using arrays with trillions of elements, because that special case will be discarded once it no longer makes sense.
To answer your initial question, in JavaScript, arrays are nothing more than a specialized type of object. If you set up an new Array like this:
var someArray = new Array(1, 2, 3);
You end up with an Array object with a structure that looks more-or-less, like this (Note: this is strictly in regards to the data that it is storing . . . there is a LOT more to an Array object):
someArray = {
0: 1,
1: 2,
2: 3
}
What the Array object does add to the equation, though, is built in operations that allow you to interact with it in the [1, 2, 3] concept that you are used to. push() for example, will use the array's length property to figure out where the next value should be added, creates the value in that position, and increments the length property.
However (getting back to the original question), there is nothing in the array structure that is any different when it comes to accessing the values that it stores than any other property. There is no inherent looping or anything like that . . . accessing someArray[0] is essentially the same as accessing someArray.length.
In fact, the only reason that you have to access standard array values using the someArray[N] format is that, the stored array values are number-indexed, and you cannot directly access object properties that begin with a number using the "dot" technique (i.e., someArray.0 is invalid, someArray[0] is not).
Now, admittedly, that is a pretty simplistic view of the Array object in JavaScript, but, for the purposes of your question, it should be enough. If you want to know more about the inner workings, there is TONS of information to be found here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array
single dimension hash table with direct access:
var array = {
x1y3: 999,
x10y100: 0
};
function getValue(x, y) {
return array['x' + x + 'y' + y];
}
I am currently in the process of writing a GUI which fundamentally allows users to edit/populate/delete a number of settings files, where the settings are stored in JSON, using AJAX.
I have limited experience with JavaScript (I have little experience with anything beyond MATLAB to be frank), however I find myself restructuring my settings structure because of the semantics of working with an object containing more objects, rather than an array of objects. In C# I would do this using a KeyValuePair, however the JSON structure prevents me from doing what I'd really like to do here, and I was wondering whether there was an accepted convention for do this in JavaScript which I should adopt now, rather than making these changes and finding that I cause more issues than I solve.
The sample data structure, which has similar requirements to many of my structures, accepts any number of years, and within these any number of events, and within these a set number of values.
Here is the previous structure:
{"2013":
{
"someEventName":
{
"data1":"foo",
"data2":"bar",
...},
...},
...}
Here is my ideal structure, where the year/event name operates as a key of type string for a value of type Array:
["2013":
[
"someEventName":
{
"data1":"foo",
"data2":"bar",
...},
...],
...]
As far as I am aware, this would be invalid JSON notation, so here is my proposed structure:
[{"Key":"2013",
"Value":
[{"Key":"someEventName",
"Value":
{
"data1":"foo",
"data2":"bar",
...}
},
...]
},
...]
My proposed "test" for whether something should be an object containing objects or an array of objects is "does my sub-structure take a fixed, known number of objects?" If yes, design as object containing objects; if no, design as array of objects.
I am required to filter through this structure frequently to find data/values, and I don't envisage ever exploiting the index functionality that using an array brings, however pushing and removing data from an array is much more flexible than to an object and it feels like using an object containing objects deviates from the class model of OOP; on the other hand, the methods for finding my data by "Key" all seem simpler if it is an object containing objects, and I don't envisage myself using Prototype methods on these objects anyway so who cares about breaking OOP.
Response 1
In the previous structure to add a year, for example, the code would be OBJ["2014"]={}; in the new structure it would be OBJ.push({"Key":"2014", "Value":{}}); both of these solutions are similarly lacking in their complexity.
Deleting is similarly trivial in both cases.
However, if I want to manipulate the value of an event, say, using a function, if I pass a pointer to that object to the function and try to superceed the whole object in the reference, it won't work: I am forced to copy the original event (using jQuery or worse) and reinsert it at the parent level. With a "Value" attribute, I can overwrite the whole value element however I like, provided I pass the entire {"Key":"", "Value":""} object to the function. It's an awful lot cleaner in this situation for me to use the array of objects method.
I am also basing this change to arrays on the wealth of other responses on stackoverflow which encourage the use of them instead of objects.
If all you're going to do is iterate over your objects, then an array of objects makes more sense. If these are settings and people are going to need to look up a specific one then the original object notation is better. the original allows people write code like
var foo = settings['2013'][someEventName].data1
whereas getting that data out of the array of objects would requires iterating through them to find the one with the key: 2013 which depending on the length of the list will cause performance issues.
Pushing new data to the object is as simple as
settings['2014'] = {...}
and deleting data from an object is also simple
delete settings['2014']
OK, first-off let me tell you that I'm too far from being considered experienced in JavaScript... (perhaps I'm even trying to implement something not actually supported by the language?).
So... here we are...
I want to create a structure like this (it's just an illustrative example) :
Addresses
--- John
--- Phone
--- Address
--- Peter
--- Phone
--- Address
So, I've seen (or perhaps I'm just guessing) that I can do something like that (I've run all my tests in Chrome's JavaScript console) :
var addresses = [];
addresses["John"] = {};
addresses["John"].Phone = "12312312312";
// And so on...
However :
If I do addresses['123'] = {}; then a proper 124-entry array is constructed.
If I do addresses['somestring'] = {}; then addresses remains an empty array [].
What am I doing wrong? Is there no native support for proper dictionaries (or map - no matter how this thing is called) in JavaScript?
Please note: I want to be able to progressively add entries to addresses, as well as keys to each address entry (and not just create it in one-shot).
You are creating an array, but then you are using it as an object instead (which is possible because an array happens to be an object). To contain properties rather than numbered indices, you should use an object:
var addresses = {};
addresses["Holmes"] = { Phone: "14", Address: "Baker street 221b" };
JavaScript has Objects and Arrays.
Arrays are a type of Object that treats properties with numerical with special significance. It will have a length property based on the highest value property name (that is a number), and it has methods such as push, pop and forEach to manipulate its numerical members based on their number.
If I do addresses['123'] = {}; then a proper 124-entry array is constructed.
You already have an array. That just adds a member called 123 to it and updates its length.
If I do addresses['somestring'] = {};
This will add that member to the array, but it won't appear in any of the regular means of accessing array members. You have to access it by name.
Don't give named properties to arrays. Use a plain object.
Is there no native support for proper dictionaries
An object is as close as you can get.
If you want something ordered use an array with numerical properties.
If you want something with named keys, use an object.
When you do this addresses['somestring'] = {}; you wil get an empty array because {} you are assigning an empty object.
Rather if you do addresses["dd"] = {s: "s"} the addresses will have the object
Javascript does not have dictionaries or maps or associative arrays.
It does, however, have objects which can be quite similar. (They can also be quite different, so that is essential to know.)
To make things more confusing, an array is an object. You can put random properties on an array and it will work -- like an object.
Javascript arrays take integer[*] indexes and adjust the .length property.
Objects take string property names. This is important: If you use something that is not a string, it will be converted into one .. usually called [Object object]
Might want to read this:
http://eloquentjavascript.net/chapter4.html
[*] Yea, yea, yea -- they are really strings behind the scenes. It is easier to think of them as integers and avoid that grief.
I'm new to javascript and I cannot find answer about some issues, one is the following:
Why in js would be useful an hash table data structure when we can use objects as associative arrays that is simple to use and have a very good performance?
why in js would be useful an hash table data structure when we can use
objects as associative arrays that is simple to use and have a very
good performance?
The only reason I can imaging to implement an hash table data structure is if you want to preserve the ordering of the elements. The for…in loop for objects doesn't guarantee to you in which order the properties ("keys") are returned, even if commonly you can obtain them in chronological order (last added, last returned). But it's not guarantee. For instance, old version of Opera returned the properties in an apparently random order. So, if you need an "ordered" hash table, you need to implement it by yourself.
A javascript hashtable and javascript associative array (and javascript objects) are all the same thing in the underline implementation. These are just different syntax.
So :
var a = {};
a.id = "aa";
is same as:
var a = new Object();
a.id = "aa";
Which is is same as:
var a = {};
a["id"] = "aa";
Associative arrays and hashtables are the same.
These expressions usually means the same too: dictionary, associative array, hashmap, map, hashtable and... the list goes on.
There is a difference between simple ARRAY and HASHTABLE though.
If you want to search an item in an array, the more items you have inside it, the longer will the search takes.
For example searching an item in an array with 10000 elements could takes 100 times longer than in an array with 100 elements.
With hashtables, no matter how many elements you have, the performance remains the same. (Be it 100 elements or even 99999999 elements...)