2014-03-26 52 views
1

我有以下函數替換contenteditable textarea中的鏈接。它的工作原理,但緩慢大約100個字符。我怎樣才能優化這個功能更快?我該如何提高這個JS函數的速度

function makeLinksFrom (str) { 
    var wordArray = str.replace(/(<([^>]+)>)/ig,"").split(' '); 
    var domainsArray = ['.com', '.net', '.co', '.ca', '.io', '.me']; 

    wordArray.forEach(function(word) { 
     domainsArray.forEach(function(domain) { 
      if(word.indexOf(domain) != -1 && word.substr(word.length - 6) == '&nbsp;') { 
       if(word.indexOf('http://') == -1) { 
        str = str.replace(word, '<a target="_blank" contenteditable="false" href="http://'+clean(word)+'">link</a>&nbsp;'); 
       } else { 
        str = str.replace(word, '<a target="_blank" contenteditable="false" href="'+clean(word)+'">link</a>&nbsp;'); 
       } 
      } 
     }); 
    }); 

    return str; 
} 
+1

簡單的優化,可能會或可能沒有太大的差別:拉回調的foreach出來,你正在重新定義內的回調在'每個條目wordArray'。此外,嘗試標準的循環,而不是'forEach'。儘管一個新的算法可能是你最好的選擇。 –

+0

將一個或兩個數據結構更改爲對象。你重複遍歷結構才能找到。那在使用對象時比迭代列表要便宜得多 –

+0

我認爲你的代碼至少有2個問題,並且在某些情況下不會按你的需要工作。 – Sebas

回答

1

您不必重複檢查每個單詞。所有你需要做的就是把這些單詞放在一個散列中,然後爲每個案例創建一個超鏈接的單詞。然後只更換已更改的單詞。這是我會怎麼做的。希望這可以幫助。

function makeLinksFrom (str) { 
    var wordArray = str.replace(/(<([^>]+)>)/ig,"").split(' '); 
    var domainsArray = ['.com', '.net', '.co', '.ca', '.io', '.me']; 

    var positions = {}; 
    wordArray.forEach(function(word){ 
     var value = positions[word]; 
     positions[word] = 1; 

    }); 

    var keys = Object.keys(positions); 
    var cleanWord = {}; 
    keys.forEach(function(key){ 
     domainsArray.forEach(function(domain){ 
      if(key.indexOf(domain) != -1 && key.substr(word.length - 6) == '&nbsp;') { 
      if(key.indexOf('http://') == -1){ 
       cleanWord[key] = '<a target="_blank" contenteditable="false" href="http://'+clean(word)+'">link</a>&nbsp;'; 
      }else{ 
       cleanWord[key] = '<a target="_blank" contenteditable="false" href="'+clean(word)+'">link</a>&nbsp;'; 
      } 
     } 
     }); 
    }); 

    keys.forEach(function(key){ 
     if(key != cleanWord[key]) 
     str = str.replace(key, cleanWord[key]); 
    }); 

    return str; 
} 

在你不介意失去多餘的空格情況下,你可能需要的代碼下部更換以下

keys.forEach(function(key){ 
     domainsArray.forEach(function(domain){ 
      if(key.indexOf(domain) != -1 && key.substr(word.length - 6) == '&nbsp;') { 
      if(key.indexOf('http://') == -1){ 
       cleanWord[key] = '<a target="_blank" contenteditable="false" href="http://'+clean(word)+'">link</a>&nbsp;'; 
      }else{ 
       cleanWord[key] = '<a target="_blank" contenteditable="false" href="'+clean(word)+'">link</a>&nbsp;'; 
      } 
      }else{ 
      cleanWord[key] = word; 
      } 
     }); 
    }); 
    var newArr = []; 
    wordArray.forEach(function(word){ 
     newArr.push(cleanWord[word]); 
    }); 

    return newArr.join(" "); 
0

您可以像更換此行

domainsArray.forEach(function(domain) { 
    if(word.indexOf(domain) != -1 && word.substr(word.length - 6) == '&nbsp;') 

用正則表達式驗證:

if (work.match(/.+\\.(com|net|co|ca|io|me)/) != null && word.substr(word.length - 6) == '&nbsp;') 

你將有更多的速度相同的結果!

+0

你測試了這個建議嗎?正則表達式並不總是比多個手動比較更快。 – jfriend00

+0

我沒有測試改進,但在這種情況下,你將獲得更多的處理。你將避免做一個額外的循環,將運行5次,並在每個比較兩個更多的比較。它將彌補使用er解決方案的成本。 – Zini

0

您需要算法分成兩個獨立的迴路(沒有之一另一個),使用單詞散列。它看起來像(未測試,但你有一個想法):

var hash = {}; 
var key; 

var i; 
for (i=0; i<wordArray.length; i++) { 
    for (var j=0; j<domainsArray.length; j++); 
     key = word[i] + "/" + domain[j]; 
     hash[key] = key; 
    } 
} 

for (key in hash) { 
    word = hash[key].split('/')[0]; 
    domain = hash[key].split('/')[1]; 
    if (word.indexOf(domain) != -1 ... 
    .... 
    .... 
}