对象属性名称作为数字

IT技术 javascript object
2021-01-17 16:10:00

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

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

像这样:

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

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

6个回答

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

仅供参考:大多数现代浏览器优化只有整数键的对象(想想以整数为键的字典)。因此,所有其他条件相同的me[123]情况下,性能可能会更高。
2021-03-13 16:10:00
@Joshua - 你的评论在所有方面都是错误的。你甚至尝试过吗?如果aArray,您可以分配a[123] = 1然后a["123"] = 2,相同的数组元素将被更改。同样,如果oObject,您可以设置o[123] = 1并且它将设置的'123'属性o(就像您执行了一样o['123'] = 1。此外,由于Array实例也是Object实例,a['xyz']即使a,您也可以设置和读取Array。所有这些行为都在ECMAScript 语言规范
2021-03-21 16:10:00
-1. 周围没有 JSON 字符串。它不是数组,而是一个普通对象。
2021-03-25 16:10:00
进一步解释一下:我正在研究charAtvscharCodeAt优化,所以下面的代码有点具体,但正如你所看到的,整数键查找快得多(即使是hasOwnProperty改进一点的Map.get调用,以及调用)。我在早期的基准测试中发现的警告是你可能只有整数键:jsbench.github.io/#f1f9afdba2eac615645c80335c48ed10 jsbench.github.io/#8345886c28796a6d825c292900d01777
2021-03-27 16:10:00
@Joshua 我刚刚在 Chrome 的控制台中对其进行了测试,它允许我设置和获取带或不带引号的对象属性。数组也是一样,它们似乎也适用于任一版本......
2021-03-30 16:10:00

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

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

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

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

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

您可以使用括号表示法 me[123]

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

没有嵌套对象的简单对象在浏览器中具有一致的行为(尽管正如公认的答案所说,我们需要使用方括号而不是点来访问整数属性名称):

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}})。请注意,集合检查引用相等而不是值相等,因此我们无法将配对本身存储在集合中并获得相同的结果:

// [[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