简体   繁体   中英

How can I improve the speed of this JS function

I have the following function which replaces links in a contenteditable textarea. It works, but gets slow around 100 characters. How can I optimize this function to be faster?

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;
}

You do not have to check for each word repeatedly. All you need to do is put the words in the string in a hash and then create the hyperlinked word once for each of the cases. Then replace ONLY the words that have been changed. Here is how I would do it. Hope this helps.

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;
}

In case you do not mind loosing the extra spaces you might want to replace the lower part of code to the following

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(" ");

You can replace this lines

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

with a regular expression verification like:

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

You will have much more speed with the same result!

You need to split algorithm into two separate loops (not one in another), using a hash of words. It would look like (not tested, but you have an idea):

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 ...
    ....
    ....
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM