JAVA SCRIPT - Creating Unique Key/Value Pairs with Uniquely Different Keys - Supercoders | Web Development and Design | Tutorial for Java, PHP, HTML, Javascript JAVA SCRIPT - Creating Unique Key/Value Pairs with Uniquely Different Keys - Supercoders | Web Development and Design | Tutorial for Java, PHP, HTML, Javascript

Breaking

Post Top Ad

Post Top Ad

Wednesday, March 6, 2019

JAVA SCRIPT - Creating Unique Key/Value Pairs with Uniquely Different Keys

Creating Unique Key/Value Pairs with Uniquely Different Keys 


Problem

You want to create a set of key/value pairs, but not all of the keys are strings.

Solution 

Use the new Map object:

var myMap = new Map();
myMap.set("value1", "this is value");
myMap.set(3, "another value");
myMap.set(NaN, "isn't this interesting");
myMap.set(window, "really now");
console.log(myMap.get("value1")); // this is a value
console.log(myMap.get(NaN)); // isn't this interesting
console.log(myMap.get(3)); // another value
console.log(myMap.get(window)); // really now


EXPLAIN


Prior to ES 6, you could create key/value pairs by creating an Object using a specialized syntax (to avoid default values), and adding each key and value to the new object:

var newObj = Object.create(null, {
 prop1: {
 value: undefined,
 enumerable: true,
 writable: true,
 configurable: true
 },
 prop2: {
 value: undefined,
 enumerable: true,
 writable: true,
configurable: true
 }
 });
newObj.prop1 = "first";
newObj.prop2 = "second";
newObj.prop3 = "third"; // added third prop
console.log(newObj.prop1); // first
console.log(newObj.prop2); // second


Using Object.create() with null as the first parameter ensures that the object doesn’t inherit the Object prototype, and the only properties are those specifically added. If you didn’t care about creating a completely clean object, you could also use an object literal:

var newObj = { prop1: "first", prop2: "second"};


One limitation with using objects as a way of mapping key/value pairs, other than having to ensure they’re created without an existing prototype, is that keys are strings. Even when it seems as if our use of non-string values is acceptable:


newObj.NaN = 'hey, it works!';

What happens is the NaN is really converted into a string representation of NaN:

for (var prop in newObj) {
 console.log(prop); // NaN prints out as "NaN"
}

In addition, trying to assign a property such as a function, or a number, throws an error:

newObj.5 = 'no way';
newObj.function() {} = 'Seriously?';

However, functions, numbers, strings, objects…all of these are allowable with a Map, as demonstrated in the solution. Use set() to add new key/value pairs, and delete() to remove those no longer needed:

myMap.set('mykey',100);
myMap.delete('mykey');

And use clear() to clear all collection members. Unlike object properties, it’s simple to discover how many key/value pairs a Map contains:

console.log(myMap.size); // 3

And you can easily traverse through both keys and values:

// iterating through both key an value
for (var [key, value] of myMap) {
 console.log(key + " = " + value);
}
// iterating through keys
for (var key of myMap.keys()) {
 console.log(key);
}
// iterating through values
for (var value of myMap.values()) {
 console.log(value);
}
// using forEach
myMap.forEach(function(value) {
 console.log(value);
});


All the traversals use iterators, except for forEach(). The first example uses an implicit entries() method that returns an object with an array of [key, value] pairs, allowing us to access both in the loop. The entries(), keys(), and values() function all return iterators, which also means we can use the following syntax with each:

var mapIter = myMap.keys();
console.log(mapIter.next().value); // "value1"
console.log(mapIter.next().value); // 3
console.log(mapIter.next().value); // NaN

You can also discover if a specific key is contained in a Map collection with has():

myMap.set(23,'value');
console.log(myMap.has(23)); // true

The solution demonstrates using NaN as a key value. As the Mozilla Developer Network entry on Map notes, while NaN is technically not equivalent to itself, when used as a key, it is equivalent:

myMap.set(NaN, 'nada');
var id = Number('not a number');
console.log(myMap.get(id)); // 'nada'

When all is said and done, though, you may want to just forgo using NaN as a key.

ADVANCE

As with Sets, Map keys and values can be objects, as well as scalar values. This includes the built-in objects, such as window. But the objects must be exactly equal—they can’t be equivalent. In the following code snippet, two object literals, an array, and window are used to set members in the Map. 

The code tries to access the Array object’s value using another equivalent array literal, but it doesn’t work. Only when I use the exact same object (whether through the original variable, or a new one assigned the object), can the application access the value:


var b = {first: 'apple', second: 'pear'};
var c = {first: '5', second: '1'};
var d = [1,2,3,4];
var e = b;
var myMap = new Map();
myMap.set(b, 'first');
myMap.set(c, 'second');
myMap.set(d, 'array');
myMap.set(window,'global');
console.log(myMap.get(window)); // 'global'
console.log(myMap.get([1,2,3,4])); // undefined
console.log(myMap.get(d)); // 'array'
console.log(myMap.get(e)); // 'first'

There is also another new object, WeakMap, that functions in a similar manner to Map, except the collection only accepts object keys, and the object keys are held weakly, and therefore can be garbage collected. This means the WeakMap collection can’t be enu‐ merated, but does help prevent unexpected and unwanted memory leaks.

No comments:

Post a Comment

Post Top Ad