根据官方 JavaScript 文档,您可以使用整数定义对象文字属性名称:
此外,您可以使用数字或字符串文字作为属性名称。
像这样:
me = {
name: "Robert Rocha",
123: 26,
origin: "Mexico"
}
我的问题是,您如何引用具有整数作为名称的属性?我尝试了通常的方法me.123
,但出现了错误。我能想到的唯一解决方法是使用for-in
循环。有什么建议么?
根据官方 JavaScript 文档,您可以使用整数定义对象文字属性名称:
此外,您可以使用数字或字符串文字作为属性名称。
像这样:
me = {
name: "Robert Rocha",
123: 26,
origin: "Mexico"
}
我的问题是,您如何引用具有整数作为名称的属性?我尝试了通常的方法me.123
,但出现了错误。我能想到的唯一解决方法是使用for-in
循环。有什么建议么?
您可以像引用数组一样引用对象的属性,并使用me[123]
或me["123"]
点表示法仅适用于作为有效标识符的属性名称。标识符必须以字母、$、_ 或 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}}
)。请注意,Sets检查引用相等而不是值相等,因此我们无法将对本身存储在 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
数字属性名称的情况似乎比迄今为止的答案中解释的要复杂。确实,您可以通过 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}'
因此,如果您的代码依赖于这个小细节,您最好注意它。