views:

1190

answers:

3

I want to create an associative array:

var aa = {} //equivalent to Object(), new Object(), etc...

and I want to be sure that any key I access is going to be a number:

aa['hey'] = 4.3;
aa['btar'] = 43.1;

I know JS doesn't have typing, so I can't automatically check this, but I can ensure in my own code that I only assign strings to this aa.

Now I'm taking keys from the user. I want to display the value for that key. However, if the user gives me something like "toString", he'll get back a function, not an int! Is there any way to make sure any string he gives me is only something I define? Is the only solution something like:

delete aa['toString'];
delete aa['hasOwnProperty'];

etc...

+3  A: 

One possibility would be to use hasOwnProperty to check that the key is something you explicitly added to the array. So instead of:

function findNumber(userEnteredKey) {
    return aa[userEnteredKey];
}

you'd say:

function findNumber(userEnteredKey) {
    if (aa.hasOwnProperty(userEnteredKey))
        return aa[userEnteredKey];
}

Alternately, you could use typeof to check that anything is a number before returning it. But I like the hasOwnProperty approach, because it'll keep you from returning anything that you didn't intentionally put in the array.

Moss Collum
Problem with this is that it will fail if the user has entered the key "hasOwnProperty".
some
You'd use `Object.prototype.hasOwnProperty.call(aa, userEnteredKey)`
pottedmeat
@pottedmeat: yes, that will solve the problem.
some
@Moss: +1 for hasOwnProperty.
some
Ooh, that's what I get for being out of practice with JavaScript. Thanks for the correction!
Moss Collum
+3  A: 

Will this work for you?

function getValue(id){
  return (!isNaN(aa[id])) ? aa[id] : undefined;
}

Update:

With the help from Moss Collum and pottedmeat I recommend this generic solution:

function getValue(hash,key) {
    return Object.prototype.hasOwnProperty.call(hash,key) ? hash[key] : undefined;
}

Update2: Had forgot the ".call". (thanks pottedmeat for pointing that out)

Update3: (About the key)

Note the following: The key will internally be converted to a string because the key is actually a name of an attribute.

var test = {
  2:"Defined as numeric", 
  "2":"Defined as string" 
}  

alert(test[2]); //Alerts "Defined as string"

If trying to use an object:

var test={}, test2={};
test[test2]="message"; //Using an object as a key.

alert(test[test2]); //Alerts "message". Looks like it works...

alert(test[  test2.toString() ]);
//If it really was an object this would not have worked,
// but it also alerts "message".

Now that you know that it is always a string, lets use it:

var test={};

var test2={
    toString:function(){return "some_unique_value";}
    //Note that the attribute name (toString) don't need quotes.
}

test[test2]="message";
alert(test[ "some_unique_value"] ); //Alerts "message".
some
yup, the 2nd would work - thanks! the first will not at all, i don't think =P.
Claudiu
It has to be Object.prototype.hasOwnProperty.call(hash, key)The call method of any function object allows us to call the hasOwnProperty method as if it were a method of the hash object
pottedmeat
@pottedmeat: Thanks, fixed it.
some
@Claudio: The first one (with isNaN) works because a function or undefined is not a number. So by testing if aa[id] is a number, you get that number, or else you get undefined. I have tested it in firefox and it works there.
some
@Claudio: And you said you wanted a number, right? ;) But the second one is more generic and works for all types of values. Just remember that internally the key is a string.
some
@some: ah, thanks, i didn't catch that. my use case was actually more general. the key is a string? isn't it a hashed version of whatever you pass in? or is it the hashed version of the string. if it is, then how does it work for objs you define yourself?
Claudiu
@Claudio: No, its not hashed. The "key" is the name of the attribute in the object, and therefore must be a string (internally .toString() of the key will be called so you can use a numeric, but it will silently be converted to a string )
some
@Claudio: I updated the post with some more examples.
some
@some: very interesting about the hash, very valuable information! thanks. wish i could double-upvote you.
Claudiu
@Claudiu: Too bad I put this as community wiki then ;) (and sorry for misspelling your name)
some
+1  A: 

Really simple answer: when you create a new key prepend it with some string constant of your own.

var a = {};
var k = 'MYAPP.COLLECTIONFOO.KEY.';

function setkey(userstring)
{
  a[k+userstring] = 42;
}

function getkey(userstring)
{
  return a[k+userstring];
}
annakata