【问题标题】:Optimizing JavaScript code that lowercases JSON property names优化将 JSON 属性名称小写的 JavaScript 代码
【发布时间】:2012-02-23 21:23:32
【问题描述】:

我正在开发一个接收带有大写属性名称的 JSON 数据的 Web 应用程序。我需要这些属性名称是小写的,所以我使用一个函数递归循环遍历 JSON 对象并将它们转换为小写。

问题是我的 JSON 回复可能会变得非常大。我希望该函数能够很好地执行,即使它必须处理具有 60,000 个属性名称和各种嵌套级别的 JSON。

小写函数为:

FN = function (obj)
{var ret = null;
    if (typeof(obj) == "string" || typeof(obj) == "number")
        return obj;
    else if (obj.push)
        ret = [];
    else
        ret = {};
    for (var key in obj)
        ret[String(key).toLowerCase()] = FN(obj[key]);
    return ret;
};

我正在这里执行一些基准测试:http://jsfiddle.net/emw89/7/

上面的测试在我的机器上大约 570 毫秒。

我可以做些什么来提高这个功能的性能吗?

编辑:我关闭了我的 IE,重新打开了 IE 并再次运行了 jsfiddle 基准测试——它现在对我来说大约是 180 毫秒。直到那时,我的 IE 已经连续打开了几天,所以也许这就是导致性能如此糟糕的原因。无论哪种方式,我仍然对是否有进一步优化此功能的方法感兴趣。处理 JSON 所花费的任何额外时间都会直接增加每个 AJAX 请求的运行时间。

【问题讨论】:

  • 对我来说完成大约 150 毫秒
  • 78ms - IE9。 i7 CPU 万岁。 Chrome 似乎慢了大约 30%。所有的费用都在递归中,所以我不确定还有很多其他可以做的事情。
  • 两个字:Chrome Frame
  • 您能否提供更多背景信息?为什么你需要它们小写?不能修复 JSON 的来源吗?
  • 我刚刚关闭/重新打开了我的 IE,处理时间从 ~570ms 下降到 ~180ms。也许长时间打开 IE 会降低性能……谁知道呢? @Tim 我需要这个功能的原因是因为我从一个奇怪的专有后端提取数据。该后端将记录结构数据序列化为 JSON,所有属性名称都大写——无法绕过它。这个函数的替代方法是将我的代码和客户端模板中的所有属性都大写——但这很快就会变得丑陋。

标签: javascript performance internet-explorer


【解决方案1】:
var lowerCache = {};

FN = function (obj)
{
    if (typeof(obj) === "string" || typeof(obj) === "number")
        return obj;

        var l = obj.length;
    if (l) {
        l |= 0;
        var result = [];
        result.length = l;
        for (var i = 0; i < l; i++) {
            var newVal = obj[i];
            result[i] = typeof(newVal) === "string" ? newVal : FN(newVal);
        }
        return result;
    } else {
     var ret = {};
     for (var key in obj) {

         var keyStr = typeof(key) === "string" ? key : String(key);
         var newKey = lowerCache[keyStr];
         if (newKey === undefined) {
             newKey = keyStr.toLowerCase();
             lowerCache[keyStr] = newKey;
         }

         var newVal = obj[key];
         ret[newKey] = typeof(newVal) === "string" ? newVal : FN(newVal);
     }
     return ret;
    }
};

快 100%。

【讨论】:

  • hm...如果 obj 是数组,则此代码返回空数组,还是我弄错了
  • 这看起来像是赢家,但我会暂时不回答这个问题,以防另一位魔术师想出什么办法。
  • 做了一些错误修正。还是快很多。
  • 您能简单介绍一下您期望的数据吗?数据是否经常具有相同的键值?结构是否规则?
  • 发布了缓存到较低结果的新版本。
【解决方案2】:

我会用简单的正则表达式替换来做到这一点。

  1. 使用 JSON 将对象转换为字符串
  2. 将所有具有相同名称的属性替换为小写
  3. 再次将字符串转换为对象

例如

var obj = { SENAD: "meskin" };

var str = JSON.stringify(obj);

function lCase(xxx)
{
    pattern = /\"([a-z0-9_-]{0,})\"\:/gi;
    return  xxx.replace(pattern, function() { return arguments[0].toLowerCase() });
}
str = lCase(str);

var newObj = JSON.parse(str);
alert(newObj.senad);
console.log(str);

我希望这会有所帮助。

【讨论】:

  • +1 根据 JSON 的复杂性,我认为这可能更可取。 JSON 已经是一个字符串,所以你应该可以跳过第 1 步(这是优于其他方法的优势)。
【解决方案3】:

如果您正在使用 IE(或任何其他浏览器 - 但 IE 最有可能吐出虚拟对象)处理大型 JSON 对象,我建议您以块的形式处理您的 json/array。

可以在此处找到对该过程的详细说明 http://oreilly.com/server-administration/excerpts/even-faster-websites/writing-efficient-javascript.html(向下滚动到“让步的定时器模式”标题)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-08-21
    • 2014-03-14
    • 2018-06-26
    • 1970-01-01
    • 2017-10-09
    • 1970-01-01
    • 2020-06-20
    • 1970-01-01
    相关资源
    最近更新 更多