开发者

Using a javascript object like a java Map?

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! :)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜