Why use an ES6 Map instead of a plain javascript object? - javascript

If we can make key/value pairs with plain javascript objects, then what is the reason to use the new ES6 Map object?
When should I use one and when the other? Is Map limited to values or can it contain functions as well?

Anything can be used as a key in a map.
Maps are ordered, and that allows for iteration.
Combining 1 and 2, when you iterate over a map, you'll get a useful array of key-value pairs!
Check out the map.prototype.forEach() documentation.
Source: Another good question/answer exchange. Worth marking this one as a duplicate.
Update:
Adding to this answer to address the question directly:
You should use a map whenever you need to associate things together or preserve insertion order (common data structures need this).
You can use an object when you don't need to do this, but they just do different things.
Update 2:
OP asked if functions are okay too. Yes, because values can be functions too! Check it out:
let x = new Map();
let y = () => {
console.log('derp');
}
x.set(y, "HI");
console.log(x.get(y)); // will log "HI"
For more info, check out the source of this quote, in a great chapter of Eloquent JavaScript:
"Every value has a type that determines its role. There are six basic types of values in JavaScript: numbers, strings, Booleans, objects, functions, and undefined values."
Also, the main differences between Map and Object, from MDN, under the header "Objects and Maps Compared":
An Object has a prototype, so there are default keys in the map. However, this can be bypassed using map = Object.create(null).
The keys of an Object are Strings, where they can be any value for a Map.
You can get the size of a Map easily while you have to manually keep track of size for an Object.
Again, the keys can be any value!

Maps are ordered.
Map keys do not have to be strings

Related

collections.js - differance between SortedMap and SortedArrayMap

I was searching for a sorted map in javascript and found collections.js's implementation - SortedMap. I also see that they have something called SortedArrayMap.
In the description of SortedArrayMap it says:
A map of key value pairs, sorted by key, backed by an array.
(Source)
And in the description of SortedMap it says:
A map with entries sorted by key.
What exactly does backed by an array mean? and what is the difference between it and the normal SortedMap?
As stated on http://www.collectionsjs.com/map, maps are different as they work like dictionaries but accepting even objects as a key.
Reading the Dict documentation on http://www.collectionsjs.com/dict we understand that:
A dictionary is a specialized map. The keys are required to be strings.
An array is simply a data structure where you can insert anything using a simple push(thingToInsert). Items inserted into an Array are just values without a key to point to them.
At first glance, SortedArrayMap uses a binary search strategy to maintain the order of the entries and is backed by an array, which means that use an array as a basic data structure(to maintain data of key). So that means in the end, that it uses a map based on SortedArray class.
However, SortedMap is a general key/value collection, where you can access values with their relative key(quick access rather than an array order).
Anyway, if you want to dive a bit more into this topic, you can find a very good explanation on the is the official website of collections.js,

Will JSON Evolve to Have Native Support for Ecmascript Map Objects?

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.

Is it impossible to use the item() method for getting of array item?

I learn JavaScript through the "JavaScript & jQuery" book by John Duckett (Russian translate).
Author writes two code examples of array item getting:
var colors = ["white", "black","custom"];
var el = document.getElementById('colors');
el.textContent = colors[0];
and
var colors = new Array("white", "black","custom");
var el = document.getElementById('colors');
el.innerHTML = colors.item(0);
In the article he wrotes that for getting of array item can be used item() method. But in the code sources he uses colors[0] instead of colors.item(0) in the second variant.
I see that colors.item(0) doesn't work. Is it wrong info?
JavaScript arrays are specialised objects, which have a particular behaviour and a particular set of methods. .item() is not one of them.
There are many other JavaScript objects which also contain a collection of values. Some of these objects include an .item() method.
The thing is, even though these objects may have some similarity with arrays in that they contain a collection of values, they’re not the same. Arrays, have some features, and these other objects have some others.
To learn more about what JavaScript arrays do have, you can look at: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array
In principal, it would be possible to add an .item() method to arrays by adding to the Array prototype. However, it is certainly not a natural part of JavaScript arrays.
Edit
One of the important properties of the array is in how it is accessed: you can read, replace or create an item using the square brackets ([]). Non-array collections don’t have this feature, so the items need to be accessed with a dedicated method.
Another important property is that the .length property is automatically updated.
Yes, it looks like a mistake in the book. The Array class doesn't have an item method. colors[i] should be used to get an element at a specified index.

how does javascript move to a specific index in an array?

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];
}

Trouble with "dictionary" creation in JavaScript

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.

Categories

Resources