就个人而言,我会使用:
let objectKeysToLowerCase = function (origObj) {
return Object.keys(origObj).reduce(function (newObj, key) {
let val = origObj[key];
let newVal = (typeof val === 'object') ? objectKeysToLowerCase(val) : val;
newObj[key.toLowerCase()] = newVal;
return newObj;
}, {});
}
它简洁,重复处理嵌套对象并返回一个新对象而不是修改原始对象。
在我有限的本地测试中,这个函数比当前列出的其他递归解决方案更快(一旦修复)。我很想将它与其他人进行基准测试,但 jsperf 目前处于下降状态(???)。
它也是用 ES5.1 编写的,所以根据 MDN 上的文档,它应该可以在 FF 4+、Chrome 5+、IE 9.0+、Opera 12+、Safari 5+(所以,几乎所有东西)中工作。
Vanilla JS 获胜。
我不会太担心这一切的垃圾收集方面。一旦对旧对象的所有引用都被销毁,它将成为 GC,但新对象仍将基本上引用它的所有属性,因此它们不会。
任何函数、数组或正则表达式都将通过引用被“复制”。在内存方面,即使是字符串也不会被这个过程复制,因为大多数(所有?)现代 JS 引擎都使用string interning。我认为只剩下构成原始结构的数字、布尔值和对象留给 GC 处理。
请注意,如果原始具有多个具有相同小写表示的属性,则此过程的(所有实现)将丢失值。IE:
let myObj = { xx: 'There', xX: 'can be', Xx: 'only', XX: 'one!' };
console.log(myObj);
// { xx: 'There', xX: 'can be', Xx: 'only', XX: 'one!' }
let newObj = objectKeysToLowerCase(myObj);
console.log(newObj);
// { xx: 'one!' }
当然,有时这正是您想要的。
2018-07-17 更新
一些人注意到原始函数不适用于数组。这是一个扩展的、更有弹性的版本。如果初始值是数组或简单值,它会通过数组正确递归并工作:
let objectKeysToLowerCase = function (input) {
if (typeof input !== 'object') return input;
if (Array.isArray(input)) return input.map(objectKeysToLowerCase);
return Object.keys(input).reduce(function (newObj, key) {
let val = input[key];
let newVal = (typeof val === 'object') && val !== null ? objectKeysToLowerCase(val) : val;
newObj[key.toLowerCase()] = newVal;
return newObj;
}, {});
};