Collections are groups of multiple values usually of the same type, identified by a key. The key must be a number or a string, while the value can be any data type: numeric, string or object. Collection pairs are ordered by key that are unique.
Array object
JavaScript is difficult to understand when you migrate from C because its behavior is strange. An array is not an enumeration of elements ordered by “index”, in fact is a disguised “associative array” with keys starting from “0” to the maximum number of elements minus one.
However you can remove elements from an array and the index will have gaps if you do this. You can even remove the first element and the array will not start with array[0]. This is because “associative array” is a generic structure used in JavaScript for all objects.
Don’t believe me? Try this:
1 2 | const array = [1,2,3]; console.log(typeof(array)); // object |
Note: The type ‘array’ do not exist in JavaScript. You have in fact declared an object here.
Associative arrays
To create a customized associative array in JavaScript we use JSON. An associative array is an object similar to an array. It has keys and values associated with the keys. Each key is unique and can be integer or a string.
Example:
1 2 3 4 5 6 7 | /* associative array */ var array = { 1:4, 2:5, 3:6 }; // read array values for (x in array) { console.log(`array[${x}]= ${array[x]}`); } |
Output:
array[1]= 4
array[2]= 5
array[3]= 6
Modify Associative Array
You can add new elements in associative array using notation: array[key] = value. If the key do not exist a new element will be created automatically. To remove an element you can use “delete” statement.
Example:
1 2 3 4 5 6 7 8 | /* associative array */ var array = { 1:4, 2:5, 3:6 }; // add a new element in array array[4] = 7; // remove an element from array delete array[1]; console.log(array); |
Output:
{
2: 5 ,
3: 6 ,
4: 7
}
String keys
Instead of numbers you can use string keys. These keys can have same convention as variables. If you follow same convention, the elements of the associative array can be accessed with dot notation:
Example:
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* associative array */ let array = { "first":1, "second":2, "third":3 }; // access element value using object notation let max = array.first; // 1 // access element value using [key] notation if (max < array["second"]) max = array["second"]; // 2 if (max < array["third"]) max = array["third"]; // 3 console.log(max); //expect: 3 |
Object methods
The Object is the fundamental class for all objects in JavaScript, therefore also “associative array” is responding to Object methods. In the next examples I show you how to use some methods but you can look into reference manual and figure out the rest:
Example:
Reading [keys, value] entries:
1 2 3 4 5 6 7 | /* associative array */ var array = { 1:4, 2:5, 3:6 }; // read array values for (element of Object.entries(array)) { console.log(element); } |
Output:
["1" ,4]
["2" ,5]
["3" ,6]
Example:
Reading [key,value] pairs using for…of loop:
1 2 3 4 5 6 7 | /* associative array */ var array = { 1:4, 2:5, 3:6 }; // deconstruct pairs for ([key,value] of Object.entries(array)) { console.log(key + "->" + value); } |
Output:
2->5
3->6
Example:
Reading keys and values in separated arrays:
1 2 3 4 5 6 | /* associative array */ const array = { "first":1, "second":2, "third":3 }; // using Object functions: console.log(Object.keys(array)); console.log(Object.values(array)); |
Output:
["first" ,"second" ,"third"]
[1 ,2 ,3]
Set object
A mathematical set is a collection of unique items. JavaScript Set is a collection of key-value pairs where key === value and key is unique. You can convert an array into a Set and then duplicates are eliminated.
Example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | / array source var array = [ 4, 5, 5, 6, 6]; // convert to set var myset = new Set(array); // elements of set are unique for (element of myset) { console.log(element); } // convert back to array var a = Array.from(myset) console.log(a); // [4,5,6] |
Set methods
You can create an empty Set then you can use methods to append data values to the set. If you attempt to append same value twice, only one will be stored in the Set. Of course you can verify if one value is in the set and you can remove values from the set.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | /* empty Set */ let mySet = new Set(); /* add some elements */ mySet.add(1); // Set [1] mySet.add(2); // Set [1, 2] mySet.add(2); // Set [1, 2] mySet.add(3); // Set [1, 2, 3] console.log([...mySet]); // [1,2,3] console.log('size='+mySet.size); // 3 /* remove one element */ mySet.delete(3); console.log(mySet.has(3)) // false console.log('size='+mySet.size); // 2 console.log([...mySet]); // [1,2] |
Note: There is a keyword: “set” that has nothing to do with “Set”. This is an unfortunate coincidence in English. Lowercase “set” is a “setter” method and not a collection. Do not confuse the two and do not give name “set” to a “Set”.
Map object
The Map object holds key-value pairs very similar to an object. Any value (both objects and primitive values) may be used as either a key or a value. That was not possible with a normal object. A map may perform better than object in scenarios involving frequent addition and removal of key pairs.
Example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | // create a Map var map = new Map( [ ["a", 1], ["b", 2], ["c", 3] ]); // elements of map are unique for ([key, value] of map) { console.log("key = "+ key + ", value = "+ value); } // convert back to array console.log(Array.from(map)); |
Map methods
Map methods are very similar to Set methods. Two methods are a little bit off. “set” and “get” methods, that are also keywords. So JavaSctript can do this (unfortunately) it is overwriting keyword meaning with methods. Do not be mad, get used to JavaScript to break the rules from time to time. Hell it is a free language, so you can’t complain about it.
Example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | // create empty Map object let myMap = new Map(); // prepare 3 keys let keyString = 'a string' let keyObj = {} let keyFunc = function() {}; let keyArray = [1,2]; // setting the values myMap.set(keyString, "key is a string"); myMap.set(keyObj, "key is object"); myMap.set(keyFunc, "key is a function"); myMap.set(keyArray, "key is a array"); // reading size of the map console.log("Map size = " + myMap.size); // 4 // getting the values console.log(myMap.get(keyString) ); console.log(myMap.get(keyObj) ); console.log(myMap.get(keyFunc) ); console.log(myMap.get(keyArray) ); |
Note: Be smart. By now you already know that JavaScript is using objects for everything. Map is also an object. When you define a new map you actually inherit methods from Map.prototype. So this is what you need to look for to find all Map methods.
References:
Spread Operator: “…”
Spread syntax allows an iterable such as an array expression or strings to be expanded in places where zero or more arguments (for function calls) or elements (for array literals) are expected, or an object expression to be expanded in places where zero or more key-value pairs (for object literals) are expected.
1 2 3 4 5 6 7 8 9 10 | // expect 3 arguments function sum(x, y, z) { return x + y + z; } // spread array elements by position const numbers = [1, 2, 3]; const result = sum(...numbers); console.log(result) // expected output: 6 |
Spreading Arrays:
You can do other interesting stuff by using spread operator with arrays:
1 2 3 4 5 6 7 8 9 10 11 12 | /* clone arrays */ var array = [1, 2, 3]; // fixture var clone = [...array]; // spread elements // test different arrays clone[3] = 4; console.log(clone); // [1, 2, 3, 4] console.log(array); // [1, 2, 3] /* concatenate arrays */ merge = [0, ...array, ...clone] console.log(merge); // [0,1,2,3,1,2,3,4] |
Spreading Object:
Spreading operator “…” can be used in object literals. This enable you to combine elements from objects or send properties of an object as parameters for a function.
1 2 3 4 5 6 7 8 9 10 11 | // define two objects let obj1 = { foo: 'foo', x: 42 }; let obj2 = { foo: 'bar', y: 13 }; // clone all attributes of object let clonedObj = { ...obj1 }; console.log(clonedObj) // Object { foo: "bar", x: 42 } // on merge, properties can not be duplicate let mergedObj = { ...obj1, ...obj2 }; console.log(mergedObj) // Object { foo: "foo", x: 42, y: 13 } |
Variable arguments:
It is possible to define functions with variable number of arguments. To call these functions you can use a larger or smaller list of arguments separated by comma. In next example we use spreading operator “…” to feed a function that receive variable number of arguments:
Example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | // calculate median number (average) function avg (...args) { let sum = 0; for (let n of args) { sum += n; } return sum/args.length; } // fixture (test data) let data = [0,1,2,3,4,5,6,7,8,9,10]; // normal call (we can not use fixture) let test = avg(0,1,2,3,4,5,6,7,8,9,10); // call using spread operator and fixture: let median = avg(...data); //spreading an array // check if the test is successful console.log(median == test); //expect true |
Rest syntax
Rest syntax is the opposite of spread syntax: the “spread” expands an array into its elements, while the “rest” collects multiple elements and condenses them into a single element. The rest operator is the same as spread operator: “…”, so it may be difficult to grasp.
Example:
1 2 3 4 5 6 7 8 9 10 11 12 | // rest arguments function test(a, b, ...more) { console.log("a = " + a); console.log("b = " + b); console.log(more); } // call function: a=1, b=2, more = [3, 4, 5] test(1,2,3,4,5); // call function: a="x", b="y", more = ["z"] test("x","y","z"); |
Note: Operator “…” is used in C for same purpose. It is called sometimes “varargs” or “variable arguments”. A function can be designed to receive as the last argument the “rest of arguments”.
Example:
The rest syntax can be used in combination with decomposition assignment. Collecting the rest of elements can be done into target array or object. The two are very different. You should remember we have done this before when we have learned about objects:
1 2 3 4 5 6 7 | // collect rest of elements let [x,...rest] = [1,2,3,4,5]; console.log(rest); // [3,4,5]; // collect rest of attributes let {a,...test} = {a: 1, b: 2, c: 3}; console.log(test); // {b: 2, c: 3}; |
Read next: Exceptions