在JavaScript开发里,我们经常需要在创建对象时让键名由变量或表达式决定,而不是在写代码时就固定下来。ES6引入的计算属性名(computed property names)正是为了解决这一需求,它允许在对象字面量中使用方括号包裹表达式,表达式的求值结果会作为该属性的键名。

什么是计算属性名
计算属性名指的是在对象字面量中,使用方括号 [ ] 包裹一个表达式,这个表达式运行后的返回值将直接作为对象的属性键。在ES6之前,如果要根据变量设置键名,只能先创建空对象,再用方括号语法单独赋值。计算属性名把这一步合并到了对象初始化阶段,使代码更直观。
从语言规范角度看,当JavaScript引擎解析对象字面量时,遇到 [expr] 形式的键,会先执行 expr 求出值,将其转为字符串(或Symbol)后作为键绑定到新对象上。这个过程发生在对象分配内存的同时,不会带来额外的运行时开销,和先建对象再赋值在性能上基本一致。
基础用法与代码示例
下面通过一个简单例子展示计算属性名的基本写法。我们有一组用户字段,希望用变量控制键名:
const key = 'userName';
const value = '张三';
// 使用计算属性名
const user = {
[key]: value,
age: 25
};
console.log(user.userName); // 输出:张三
console.log(user['userName']); // 输出:张三
在上面的代码中,[key] 就是计算属性名,因为 key 的值是 'userName',所以最终 user 对象拥有一个名为 userName 的属性。这种方式比先写 const user = {}; user[key] = value; 更紧凑,也更容易一眼看清对象结构。
计算属性名内部不仅可以放变量,还能放任意表达式,比如字符串拼接、函数调用、三元运算等。只要表达式能返回一个合法键(字符串或Symbol),都可以作为键名使用。
const prefix = 'data';
const id = 10;
const obj = {
[prefix + '_' + id]: '记录',
[Symbol('tag')]: '临时'
};
console.log(obj['data_10']); // 输出:记录
console.log(obj[Symbol('tag')]); // 输出:undefined,因为Symbol唯一
注意上面最后一个 Symbol('tag') 的例子:每次调用 Symbol() 都会生成全新的Symbol值,所以外面用同样的 Symbol('tag') 取不到值。如果要用Symbol作为键且后续访问,应当先把Symbol存进变量。
与展开运算符的结合
计算属性名可以和对象展开运算符(spread operator)配合,完成键名重映射或动态合并。例如我们想把一个对象的键统一加上前缀:
const raw = { a: 1, b: 2 };
const mapped = {
...Object.keys(raw).reduce((acc, k) => {
acc['new_' + k] = raw[k];
return acc;
}, {})
};
console.log(mapped); // 输出:{ new_a: 1, new_b: 2 }
虽然上面的 reduce 过程没有直接在字面量里写计算属性,但如果在字面量内写,也能达到类似效果:
const raw = { a: 1, b: 2 };
const prefix = 'x_';
const built = {
...Object.entries(raw).map(([k, v]) => ({ [prefix + k]: v }))
.reduce((o, item) => ({ ...o, ...item }), {})
};
console.log(built); // 输出:{ x_a: 1, x_b: 2 }
这种写法在配置生成、表单字段动态组装等场景中非常实用。它让对象的形状完全由数据驱动,而不是依赖大量的 if 判断去手动赋值。
常见误区与注意事项
一个常见误区是认为计算属性名只能用于变量。实际上,任何能产生值的表达式都可以,包括字面量拼接。但需避免把过于复杂的逻辑塞进方括号,否则会降低可读性。如果表达式很长,建议先算出变量再放入 [ ]。
另一个注意点是键名冲突。如果对象字面量里同时有计算属性名和普通属性名,且最终求值后键名相同,后面的会覆盖前面的,这和正常对象属性覆盖规则一致。另外,计算属性名不能是 undefined 或 null,它们会被转成字符串 'undefined' 或 'null',往往不是你想要的结果。
const wrong = {
[undefined]: '值'
};
console.log(wrong['undefined']); // 输出:值
如上所示,本想用空键,实际却生成了字符串键 'undefined'。因此在动态拼键时,务必保证表达式有预期的返回值。
实际应用建议
在接口返回字段映射、多语言文案对象、动态表单模型等场合,计算属性名可以显著减少模板代码。比如根据当前语言代码生成文案对象的键:
function buildI18n(lang, texts) {
return {
[lang]: texts
};
}
const zhPack = buildI18n('zh-CN', { hello: '你好' });
console.log(zhPack['zh-CN'].hello); // 输出:你好
总体来看,计算属性名是JavaScript对象字面量灵活性的重要补充。它把“键名也是数据”的思想落到了语法层面,让开发者可以用声明式的方式写出更干净、更易维护的代码。只要留意表达式结果和键名冲突问题,就能在项目中放心使用。
JavaScript计算属性名对象键名修改时间:2026-08-08 05:30:28