Hash Map is usually used in JavaScript as a simple place to store key-value pairs. However, Object is not a true hash map and can potentially cause problems if used improperly. And JavaScript may not provide local hash mapping (at least not cross-browser compatible), there is a better way to declare object properties.
A simple implementation of Hash Map:
var hashMap = { Set : function(key,value){this[key] = value}, Get : function(key){return this[key]}, Contains : function(key){return this.Get(key) == null?false:true}, Remove : function(key){delete this[key]} }Example of usage:
hashMap.Set("name","John Smith"); hashMap.Set("age",24); hashMap.Get("name");//John Smith hashMap.Contains("title");//false hashMap.Contains("name");//true hashMap.Remove("age");Issues in Object declaring members
This problem may be due to the inheritance mechanism of the object prototype chain. Take the toString method as an example. If the in operator is used to determine whether the object exists:
var map = {};'toString' in map; // trueBecause the in operator will look for whether the object exists from all prototypes. To solve this problem, you can use the hasOwnProperty method to detect whether the object exists:
var map = {};map.hasOwnProperty('toString'); // falseThis method works very well, but if you define a hasOwnProperty property, it may be troublesome:
var map = {};map.hasOwnProperty = 'foo';map.hasOwnProperty('hasOwnproperty'); // TypeErrorA quick fix to this is to use native objects.
var map = {};map.hasOwnProperty = 'foo';{}.hasOwnProperty.call(map, 'hasOwnproperty'); // trueThis method will not cause any problems. Every time you judge whether the properties in the object exist, you must filter out the methods in the prototype chain:
var map = {};var has = {}.hasOwnProperty;for(var key in map){ if(has.call(map, key)){ // do something }}Naked object
The trick to creating a real Hash Map is to solve all the prototype objects. We can achieve this effect through Object.create
var obj = {};// is equivalent to:var obj = Object.create(Object.prototype);In addition, this method allows you to completely abandon the prototype and directly use null to inherit.
var map = Object.create(null);map instanceof Object; // falseObject.prototype.isPrototypeOf(map); // falseObject.getPrototypeOf(map); // null
These naked objects (or dictionaries) are ideal as Hasp Map. Because there will be no conflict, it will resist any type conversion, such as this will cause errors.
var map = Object.create(null);map + ""; // TypeError: Cannot convert object to primitive value
There are no reserved words here, it is designed for Hash Map, for example.
var map = Object.create(null);'toString' in map; // falseGoing further, for ... in loops have become simpler, we just need to write the loop like this.
var map = Object.create(null);for(var key in map){ // do something}Apart from these differences, it is no different from the general Object key-value storage. The object can be serialized, declared prototypes and inherited, and the use of context variables is the same.
var map = Object.create(null);Object.defineProperties(map, { 'foo': { value: 1, enumerable: true }, 'bar': { value: 2, enumerable: false }});map.foo; // 1map['bar']; // 2JSON.stringify(map); // {"foo":1}{}.hasOwnProperty.call(map, 'foo'); // true{}.propertyIsEnumerable.call(map, 'bar'); // falseEven the variable detection methods mentioned above are also applicable.
var map = Object.create(null);typeof map; // object{}.toString.call(map); // [object Object]{}.valueOf.call(map); // Object {}