请帮我重构这个jQuery代码

时间:2010-01-28 17:49:34

标签: javascript json translation

我需要让这个jquery运行得更快,我没有创建所有这些函数,但需要他们的方法来进行页面内容的实时翻译。

所以我很感激任何重构以获得更好性能的建议,以下代码。


/* function 1 read json into array */
/* function 2 loop through array */
/* function 3 replace text nodes based on data from looped array */

var en_lang = new Array();
var fr_lang = new Array();
var frca_lang = new Array();
var my_data = null;
var en_count = 1;
var fr_count = 1;
var frca_count = 1;

if(typeof(language) != "undefined"){
    var language = 'frca';
}

function replaceText(oldText, newText, node){ 
  node = node || document.body; // base node 

  var childs = node.childNodes, i = 0;

  while(node = childs[i]){ 
    if (node.nodeType == 3){ // text node found, do the replacement
      if (node.textContent) {
        node.textContent = node.textContent.replace(oldText, newText);
      } else { // support to IE
        node.nodeValue = node.nodeValue.replace(oldText, newText);
      }
    } else { // not a text mode, look forward
      replaceText(oldText, newText, node); 
    } 
    i++; 
  } 
}
function parsejSON(my_data) {
    /* THIS PART GRABS DATA FROM TOP OF JSON FILE */

    /* grab recordcount */
    var recordcount = my_data.recordcount;
    /* grab columnlist */
    var columnlist = my_data.columnlist;
    /* grab json data */
    var json_data = my_data.data;

    /* PUTS JSON DATA INTO ARRAYS */
    for(var x = 0; x < recordcount; x++) {
        var lng = json_data.lng[x];
        var phrase = json_data.phrase[x];

        if (lng == 'french') {

            fr_lang[fr_count] = phrase;
            fr_count = fr_count + 1;
        }
        if (lng == 'french canadian') {

            frca_lang[frca_count] = phrase;
            frca_count = frca_count + 1;
        }
        if (lng == 'english') {

            en_lang[en_count] = phrase;
            en_count = en_count + 1;
        }
    }

    /* use a replacetext function above to replace all text */ 

    for(var x = 0; x < en_lang.length; x++) {
      var from = en_lang[x];
      if (language == 'fr') {  
        var to = fr_lang[x];
      }
      if (language == 'frca') {  
        var to = frca_lang[x];
      }
      replaceText(from, to);
    }



}

抱歉,不太确定如何获取代码发布,格式正确,随时可以编辑我的帖子..

谢谢。

3 个答案:

答案 0 :(得分:2)

通过检查你的代码,我可以告诉你,你的最大开销是在replaceText函数中创建的。对于每个文本项,您的代码会一次又一次地遍历整个DOM结构。代码不是一次性执行此操作,而是遍历文档en_lang.length次。节点操作比JavaScript代码慢得多,因此如果en_lang数组中有很多项,并且文档结构很复杂,则渲染时间会急剧增加。通过在一个循环中替换所有文本项将节省大量时间。

二。我可以看到,在每个节点上执行分配操作。 node.textContent = node.textContent.replace(oldText, newText); 如果您的节点不包含任何匹配信息,则此操作过度。通过仅在需要的地方进行DOM分配,您可以节省另外几毫秒的渲染时间。

<击>第三。递归。真有趣的话题。可以使用,可以不使用。你更喜欢什么。但有时递归可能是代码中的瓶颈。在这种情况下,replaceText是一种重新启动操作,这会导致不必要的内存消耗和CPU时间。您可以通过使用getElementsByTagName函数询问一步来获取所有节点。

第四个:“if”操作在“parseJson”里面的第一个for循环。我不知道为什么,但你不使用if-else语句,但简单如果。这意味着运行时应该遍历所有“if”语句,即使它已经找到了正确的语句。在这种情况下,为了提高JavaScript效率,最好使用“switch”语句而不是“if”或“if-else”。它更快。

第五。现在让我们看看第二个“for”循环。你根本不应该使用任何开关或if语句。该部分中的“if”语句完全矫枉过正。在for循环之前你知道你的“语言”变量的值,所以你可以在for循环之前缓存“to”数组并使用已经缓存的数组。

六:另一个小小的改进,而不是使用frca_count = frca_count + 1;你可以使用增量运算符:frca_count ++。它还会加速代码。

七。在你的第二个“for:语句中,你在条件部分使用en_lang.length。如果你看一下前面的”for“循环,你可以看到它有一个具有相同值的变量:”en_count“。用它代替en_lang。加速循环本身的长度。

将这一切结合在一起,我想出了类似的东西。

function parsejSON(my_data) {
 /* THIS PART GRABS DATA FROM TOP OF JSON FILE */

 /* grab recordcount */
 var recordcount = my_data.recordcount;
 /* grab columnlist */
 var columnlist  = my_data.columnlist;
 /* grab json data */
 var json_data   = my_data.data;

 /* PUTS JSON DATA INTO ARRAYS */
 for(var x = 0; x < recordcount; x++) {
  var lng    = json_data.lng[x];
  var phrase = json_data.phrase[x];

 // ( conclusion # 4)
  switch(lng){
   case 'french':
    // ( conclusion # 6)
    fr_lang[fr_count++] = phrase;
    break;
   case 'french canadian':
    frca_lang[frca_count++] = phrase;
    break;
   case 'english':
    en_lang[en_count++] = phrase;
    break;
  }
 }

 /* use a replacetext function above to replace all text */ 
 // ( conclusion # 5)
 var toCache = (language == 'fr') ? fr_lang 
 : (language  == 'frca' ? frca_lang : null);


 // ( conclusion # x)
 var content = function(node, txt){
  if(txt){
   if(node.textContent){
    node.textContent = txt;
   }else if(node.nodeValue){
    node.nodeValue = txt;
   }
  }else{
   return node.textContent ? node.textContent : node.nodeValue;
  }
 };

 // recursive tree walker
 (function(parent){
     var childs = parent.childNodes;
     if(childs && childs.length){
         for(var i=0,node;node = childs[i];i++){
             if(node.nodeType == 3){ // text node found, do the replacement
                 var value  = content(node);
                 // ( conclusion # 7)
                 for(var x = 0; x < en_count; x++) {
                     var from = en_lang[x];
                     var to   = toCache[x];
                     // ( conclusion # 2)
                    if(value.match(from)){
                        content(node, value.replace(from,to));
                    }
                 }
             }else{
                 arguments.callee(node);
             }
         }
     }
 })(document.body);

}

我希望所有这一切都应该成功。祝你好运

EDITED:因为getElementsByTagName(“*”)没有返回#text节点,所以我改变了使用递归树walker的解决方案。

答案 1 :(得分:0)

您可以在firebug中尝试console.time。这将告诉您在进行更改时节省了多少时间。它还可以帮助您确定哪些函数执行时间最长(因此您可以先解决优化问题。)

How to measure time taken by a function to execute

答案 2 :(得分:0)

我建议将每个本地化的参数放入span标记,然后您可以更轻松地选择和更新参数。拥有.localize类名,带有.l-PARMNAME类名的allong将具有相当严格的可选性。

ex:<span class="localize l-PARMNAME">English Value</span>

然后您可以将数据包含在......

jsonData: { //note: this can come back from your ajax call
  language:'fr', 
  parms: { 
    "PARMNAME": "parm value",
    "OTHERPARM": "other value",
    ...
  }
}


$.each(jsonData.parms, function(key, value){
  ($('span.localize.l-'+key).text(value);
});

上面的代码应该在更新的浏览器中运行得更快(使用jquery),它们具有更好的选择模型。它几乎可以在任何浏览器中运行。如果性能仍然存在问题,您可以循环遍历$(“span.localize”)。each()并检查相应的子标记。

否则,您可以简单地循环您的英文版本,但我建议为每个可复制节点使用span标记。即使只是“span.localize”选择器会给你一个较小的节点,你可以比较.text()值,并匹配/替换整个字符串......在文本节点中的字符串上使用.replace是公平的重,因为你必须得到文本的值,匹配字符串,(基于正则表达式),然后将新值输入文本节点。能够拥有一个窄标签选择器,从那里能够专门定位你想要的节点,可以在更新的浏览器中使用改进的dom搜索。