我需要让这个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);
}
}
抱歉,不太确定如何获取代码发布,格式正确,随时可以编辑我的帖子..
谢谢。
答案 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。这将告诉您在进行更改时节省了多少时间。它还可以帮助您确定哪些函数执行时间最长(因此您可以先解决优化问题。)
答案 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搜索。