0

我有以下使用大量正则表达式的 javascript 函数。有没有办法可以简化这个?

function encode(str){
    if(typeof str==='number'){
        return str;
    }
    if(typeof str!=='string'){
        return '';
    }
    var enc=str;
    enc=enc.replace(/_/g,'_u');  //underscore
    enc=enc.replace(/(\r\n|\r|\n)/g,'_r'); //return
    enc=enc.replace(/&/g,'_a');  //ampersand
    enc=enc.replace(/\\/g,'_b'); //backslash
    enc=enc.replace(/:/g,'_c');  //colon
    enc=enc.replace(/"/g,'_d');  //double quote
    enc=enc.replace(/=/g,'_e');  //equals
    enc=enc.replace(/€/g,'_4');  //euro
    enc=enc.replace(/\>/g,'_g'); //greater than
    enc=enc.replace(/#/g,'_h');  //hash
    enc=enc.replace(/'/g,'_i');  //inverted comma
    enc=enc.replace(/\</g,'_l'); //less than
    enc=enc.replace(/¬/g,'_n');  //not
    enc=enc.replace(/\|/g,'_1'); //pipe
    enc=enc.replace(/¦/g,'_2');  //broken pipe
    enc=enc.replace(/\+/g,'_p'); //plus
    enc=enc.replace(/£/g,'_3');  //pound
    enc=enc.replace(/\?/g,'_q'); //question mark
    enc=enc.replace(/\//g,'_s'); //slash
    enc=enc.replace(/\~/g,'_t'); //tlide
    enc=enc.replace(/\`/g,'_z'); //back quote
    enc=enc.replace(/\s/g,'_0'); //space
    enc=enc.replace(/[\u0000-\u001f]/g,'');
    return enc;
};
4

2 回答 2

3

您可以创建从“要替换的字符串”到“替换”的映射,而不是创建“模式”到“替换”的映射,然后使用带有回调的单个替换函数:

var map = {
    "_": "_u",
    "\r\n": "_r",
    "\r": "_r",
    "\n": "_r",
    "&": "_a",
    /* .. etc .. */
};

enc = enc.replace(
        /\r\n|[_\r\n&\\:"=€&gt;#'<¬|¦+£?\/~`\s\u0000-\u001f]/g,
        function(m) {
            return map[m[0]];
        }
);

一旦您添加不会产生固定字符串的替换模式(因为它们使用量词,如+or *),这种方法就会失败。

但是,它在大多数浏览器中实际上要快得多。请参阅此 JSPerf

除此之外,没有办法进行有条件的替换(这是您进一步优化所需要的)。

于 2013-08-16T09:55:43.890 回答
1

你可以这样做:

var map = {
    "_": "_u",
    "(\r\n|\r|\n)": "_r",
    "&": "_a",
    /* .. etc .. */
};
var i;
var enc = "_abc&";
for (i in map) {
    enc = enc.replace(new RegExp(i, "g"), map[i]);
}
console.log(enc); // _uabc_a

我使用new RegExp是因为您无法编写正则表达式。请记住,您不需要分隔符 ( /) 并且修饰符 ( g) 在别处。

于 2013-08-16T09:35:41.940 回答