I need something of a HashMap in javascript. Can we do this:
var map = {};
开发者_运维百科map['foo'] = true;
map['zoo'] = true;
...
if (map['foo']) {
// yes, foo exists.
}
else {
// no, foo does not exist.
}
how do we properly check for the existence of the property without inserting it if it does not exist? For example, I don't want map.foo to exist after the above check if I didn't explicitly add it,
Thanks
In your example, checking for:
if (map['foo']) {
//..
}
Not only checks if the property is not defined on the object, the condition expression of the if
statement will evaluate to false
also if the property holds a value that coerces to false
on boolean context (aka falsy values), such as 0
, NaN
, an empty string, null
, undefined
and of course false
, e.g.:
var map = {
'foo': 0 // or any other falsy value
};
if (map['foo']) {
// foo is truthy...
} else {
// foo is falsy or not defined
}
To check if a property exist on an object, regardless its value -which can be falsy, even undefined
- , you can use the hasOwnProperty
method, for example:
var map = {};
map['foo'] = 0;
if (map.hasOwnProperty('foo')) {
// foo exist physically on the object...
}
The only problem with this method is that if someone adds a property named hasOwnProperty
to an object, it wont work, for example:
var obj = {
hasOwnProperty: 'bar'
};
If you execute obj.hasOwnProperty('prop')
, it will give you a TypeError
, because the object contains a string property that shadows the method -invoking the string would cause the error-.
A workaround to this is to call the hasOwnProperty
method directly from the Object.prototype
object, for example:
if (Object.prototype.hasOwnProperty.call(obj, 'prop')) {
//..
}
You can also use the in
operator:
if ('prop' in obj) {
//...
}
The difference with the first method is that the in
operator checks also for inherited properties, for example:
var obj = {};
obj.hasOwnProperty('toString'); // false
'toString' in obj; // true, inherited from Object.prototype.toString
See also:
- Difference between undefined and not being defined in Javascript
Edit:
Extending my response to the @slebetman comment, about checking if (map.foo !== undefined)
.
As I was commenting, there are some concerns about accessing the undefined
global property and also a semantic difference between checking a property value vs. property existence.
The undefined
global property is not defined as read-only ECMAScript 3rd Edition Standard, (is now writable = false
on ES5 :)
In almost all implementations its value can be replaced.
If someone makes:
window.undefined = 'foo';
// It will break your code:
var obj = {};
if (obj.foo !== undefined) {
alert("This shouldn't ever happen!");
}
Also the semantic difference: by testing if map.foo !== undefined
we are not technically only checking if the property exist on the object or not, a property can exist, holding undefined as a value, for example:
var map = {
'foo': undefined
};
map.hasOwnProperty('foo'); // true, because the property exists although
// it holds the undefined value
map.foo !== undefined; // false
By using JavaScript Hashmap Equivalent
<html> <head> <script> HashMap = function(){ this._dict = {}; } HashMap.prototype._shared = {id: 1}; HashMap.prototype.put = function put(key, value){ if(typeof key == "object"){ if(!key.hasOwnProperty._id){ key.hasOwnProperty = function(key){ return Object.prototype.hasOwnProperty.call(this, key); } key.hasOwnProperty._id = this._shared.id++; } this._dict[key.hasOwnProperty._id] = value; }else{ this._dict[key] = value; } return this; // for chaining } HashMap.prototype.get = function get(key){ if(typeof key == "object"){ return this._dict[key.hasOwnProperty._id]; } return this._dict[key]; } var color = {}; // unique object instance var shape = {}; // unique object instance var map = new HashMap(); map.put(color, "blue"); map.put(shape, "round"); console.log("Item is", map.get(color), "and", map.get(shape)); </script> <head> <body> <script>document.write("Existing Item Testing :\t\t\t" + map.get(color)+"
"); document.write("Non - Existing Item Testing :\t\t\t" + map.get("test")+ ""); </body> </html>
Output:
Existing Item Testing : blue
Non - Existing Item Testing : undefined
Java Map and Java HashMap are different things. Java Map is a hash table that has key labeled values, and a fast search of values by keys. HashMap on the other hand has the same seak time if you search value by key or key by value.
I wrote a similar data structure to Java Map, but I am still developing the HashMap class for javascript and I will share it as soon as I can. Note that my solution is just a wrapper to the native hash table, for easier use and iteration. A bit slower put and remove times, and a bit more of memory.
You can check it out on my blog, cause it is too long for here: http://stamat.wordpress.com/javascript-map-class/
Thanks for giving it a chance! Feedback is very appreciated! :)
精彩评论