对象属性名称为数字

时间:2013-06-04 01:34:59

标签: javascript object

根据official JavaScript documentation,您可以使用整数定义对象文字属性名称:

  

此外,您可以使用数字或字符串文字作为属性的名称。

像这样:

me = {
    name: "Robert Rocha",
    123: 26,
    origin: "Mexico"
}

我的问题是,如何引用具有整数作为名称的属性?我尝试了通常的me.123,但收到了错误。我能想到的唯一解决方法是使用for-in循环。有什么建议吗?

6 个答案:

答案 0 :(得分:65)

您可以像引用数组一样引用对象的属性,并使用me[123]me["123"]

答案 1 :(得分:23)

点符号仅适用于作为有效标识符的属性名称。标识符必须以字母,$,_或unicode转义序列开头。对于所有其他属性名称,必须使用括号表示法。

在对象文字中,属性名称必须是标识符名称,字符串文字或数字文字(由于属性名称必须是字符串,因此将转换为字符串):

var obj = {1:1, foo:'foo', '+=+':'+=+'};

alert(obj[1] + ' ' + obj.foo + ' ' + obj['+=+']); // 1 foo +=+

答案 2 :(得分:13)

您可以使用me[123]me["123"]。两者都有效。

答案 3 :(得分:6)

您可以使用bracket notation me[123]

答案 4 :(得分:3)

以防万一其他人对此感到困惑:使用整数(而不是字符串)属性名称可能会在对象中包含对象时略微不同 - 尽管功能相同 - 会产生结果(取决于浏览器)。

没有嵌套对象的简单对象在浏览器中具有一致的行为(尽管as the accepted answer says,我们需要使用括号而不是点来访问整数属性名称):

var str_simple = {
    a: "b", c: "d", e: "f", g: "h",
};
str_simple.a === "b"; // true
str_simple.e === "f"; // true

var int_simple = {
    1: 2, 3: 4, 5: 6, 7: 8,
};
int_simple[1] === 2; // true - must use brackets instead of dots
int_simple[5] === 6; // true
// this works b/c int property names are coerced to strings anyway
int_simple[1] === int_simple['1']; // true

这个带有字符串键的嵌套对象完全按预期工作:

var str_nested = {
    a: {b: "c"}, 
    d: {e: "f", g: "h"},
};
str_nested.a; // returns object as expected, no matter the browser - {b: "c"}
str_nested.a.b === "c"; // true
str_nested.d.g === "h"; // true

但是这个带有整数键的等效嵌套对象会根据浏览器返回略有不同的结果,尽管您仍然可以以相同的方式访问嵌套对象(所以在功能上,它仍然可以正常工作):

var int_nested = {
    1: {2: 3}, 
    4: {5: 6, 7: 8},
};

// latest Chrome (57)
// Safari 10 (latest for my Mac, 10.10 Yosemite)
int_nested[1]; // returns object as expected - {2: 3}
int_nested[1][2] === 3; // true

// latest Firefox (52)
int_nested[1]; // RETURNS ARRAY-LIKE OBJECT - Object [ <2 empty slots>, 3 ]
int_nested.length; // undefined because it's not technically an array
int_nested[1][2] === 3; // true - works b/c object was padded with empty slots

// and again, in all browsers, we can exchange the integer keys
// for equivalent strings since property names are coerced to strings anyway
int_nested[1][2] === int_nested['1'][2];
int_nested['1'][2] === int_nested[1]['2'];
int_nested[1]['2'] === int_nested['1']['2'];

如果以编程方式构造嵌套对象,此行为仍会略有不同,但功能相同。例如,假设我们想编写一个函数来获取对的列表(例如[[0, 0], [0, 1], [1, 2], [2, 3]])并将其转换为嵌套对象,以便我们可以检查该对是否在O(1)时间内的对象中(例如{0: {0: true, 1: true}, 1: {2: true}, 2: {3, true}})。请注意Sets检查reference equality and not value equality,因此我们无法将该对存储在Set中并获得相同的结果:

// [[0, 0], [0, 1], [1, 2], [2, 3]] ->
// {
//  0: {0: true, 1: true},
//  1: {2: true},
//  2: {3: true},
// }
function createNestedObject(pairs) {
    var obj = {};
    for (var pair of pairs) {
        var x = pair[0], y = pair[1];
        // must create outer object for each unique x or else
        // obj[x][y] would fail b/c obj[x] would be undefined
        if (!obj.hasOwnProperty(x)) {
            obj[x] = {};
        }
        obj[x][y] = true;
    }
    return obj;
}

function exists(nested, pair) {
    var x = pair[0], y = pair[1];
    // uses !! operator so if pair isn't in nested
    // we return false instead of undefined
    return !!(nested[x] && nested[x][y]);
}

带字符串的对将按预期工作:

var pairs = [["a", "a"], ["a", "b"], ["c", "d"], ["d", "e"]];
var nested = createNestedObject(pairs);
nested; // as expected - {a: {a: true, b: true}, c: {d: true}, d: {e: true}}
exists(nested, ["a", "a"]); // true
exists(nested, ["a", "b"]); // true
exists(nested, ["ZZZ", "ZZZ"]); // false

但在某些浏览器中,整数对会有所不同,但功能相同:

var pairs = [[0, 0], [0, 1], [1, 2], [2, 3]];
var nested = createNestedObject(pairs);
nested; // in Safari 10/Chrome 57 - returns nested objects as expected
nested; // in Firefox 52 - Object [ Object[2], Object[3], Object[4] ]
// BUT still gives correct results no matter the browser
exists(nested, [0, 0]); // true
exists(nested, [0, 1]); // true
exists(nested, ['0', '0']); // true
exists(nested, [999, 999]); // false

答案 5 :(得分:1)

使用数字属性名称的情况似乎比目前为止在答案中解释的更复杂。确实,您可以通过for-in循环访问这些属性。但是,重要的是要知道for-in循环将键作为字符串给出,而不是像你期望的那样给出数字:

var obj = {1:2};
for (var key in obj) {
    alert(typeof(obj[key])); // you get "number" as expected, however
    alert(typeof(key)); // you get "string", not "number"
}

在使用JSON序列化期间发生了类似的事情:

JSON.stringify( {1:2} ) === '{"1":2}'

因此,如果您的代码依赖于这个小细节,您最好注意它。