個人的には、次を使用します。
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 以降 (ほぼすべて) で動作するはずです。
勝利のためのバニラJS。
このすべてのガベージ コレクションの側面についてはあまり心配しません。古いオブジェクトへのすべての参照が破棄されると、それはGCになりますが、新しいオブジェクトは基本的にすべてのプロパティを参照するため、そうではありません。
関数、配列、または正規表現は、参照によって「コピー」されます。メモリに関しては、ほとんど (すべて?) の最新の JS エンジンはstring interningを使用しているため、このプロセスでは文字列でさえ複製されません。元の構造を形成していた Numbers、Booleans、および Objects だけが GC の対象として残されていると思います。
オリジナルに同じ小文字表現のプロパティが複数ある場合、このプロセス (のすべての実装) は値を失うことに注意してください。すなわち:
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;
}, {});
};