Ассоциативный массив без toString и т.д.

Я хочу создать ассоциативный массив:

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

и я хочу быть уверенным, что любой доступный ключ будет числом:

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

Я знаю, что JS не печатает, поэтому я не могу автоматически проверять это, но я могу обеспечить в своем собственном коде, что я только назначаю строки этому аа.

Теперь я беру ключи от пользователя. Я хочу показать значение для этого ключа. Однако, если пользователь дает мне что-то вроде "toString", он вернет функцию, а не int! Есть ли способ убедиться, что любая строка, которую он мне дает, - это только то, что я определяю? Это единственное решение:

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

и т.д...

Ответ 1

Будет ли это работать для вас?

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

Update:

С помощью Moss Collum и pottedmeat я рекомендую это общее решение:

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

Update2: Забыл ".call". (спасибо pottedmeat за указание этого)

Update3: (О ключе)

Обратите внимание на следующее: ключ будет внутренне преобразован в строку, потому что ключ на самом деле является именем атрибута.

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

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

При попытке использовать объект:

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".

Теперь, когда вы знаете, что это всегда строка, давайте ее использовать:

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".

Ответ 2

Одной из возможностей было бы использовать hasOwnProperty, чтобы проверить, что ключ - это то, что вы явно добавили в массив. Поэтому вместо:

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

вы бы сказали:

function findNumber(userEnteredKey) {
    if (Object.prototype.hasOwnProperty.call(aa,userEnteredKey))
        return aa[userEnteredKey];
}

В качестве альтернативы вы можете использовать typeof, чтобы проверить, что что-то есть число перед его возвратом. Но мне нравится подход hasOwnProperty, потому что он заставит вас возвращать все, что вы не намеренно помещали в массив.

Ответ 3

Действительно простой ответ: когда вы создаете новый ключ, добавьте его с помощью некоторой строковой константы.

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

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

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