javascript 性能分析:字符串和正则表达式

来源:互联网 发布:淘宝网限制发布 编辑:程序博客网 时间:2024/06/11 13:38

       几乎所有的js都与字符串操作紧密相连。典型的就是ajax从服务器获取字符串将这些字符串转换成更容易的js对象,然后从数据中生成html字符串。包含合并,分解,重新排列,搜索,遍历,以及其他方法处理字符串。

  字符串链接:

1.Plus (+) and Plus-Equals (+=) Operators 加或加等于操作

 str += "one" + "two";

上面发生的步骤:

内存中创建了一个临时字符串

临时字符串被赋值于“onetwo”

临时字符串与str的值进行链接

结果赋值为str

str += "one";
str += "two";

但这个链接避免了临时字符串的创建速度更快。

str = str + "one" + "two";  合并多个短字符串比链接一个大字符串更快(避免多次拷贝那些大字符串) 这个表达式拷贝了2次str 合并了2次 比 str = "one" + "two"; 而这个表达式 创建了临时字符串和2次拷贝大字符串 性能冲击要轻得多。

Firefox 和编译期合并:Firefox所有的字符串都属于编译期常量 Firefox自动在编译过程中合并他们。这样速度更快。

Array.prototype.join 数组链接字符串

var str = "I'm a thirty-five character string.",
newStr = "",
appends = 5000;
while (appends--) {
newStr += str;
}

上面的代码 可以用数组链接改进

var str = "I'm a thirty-five character string.",
strs = [],
newStr,
appends = 5000;
while (appends--) {
strs[strs.length] = str;
}
newStr = strs.join("");

String.prototype.concat  字符串原有属性追加字符串

// append one string
str = str.concat(s1);
// append three strings
str = str.concat(s1, s2, s3);
// append every string in an array by using the array
// as the list of arguments
str = String.prototype.concat.apply(str, array);

但是concat 属性比+和+=速度要慢

正则表达式:

一 工作原理:当你创建一个正则表达式对象后(使用正则表达式直接量或RegExp构造器)浏览器会检测有没有模版错误,然后转换为本机代码列程 用于执行匹配工作

二 设置起始位置: 确定目标字符串的搜索开始位置 是字符串的开始位置还是指定的开始位置。或尝试失败后将最后尝试的位置推后一个位置进行搜索。在这个阶段各个浏览器厂商优化正则表达式引擎  主要跳过没有必要的步骤。

三 匹配每个正则表达式的字元:一个一个扫描文本和匹配模版 失败后回溯到扫描之前的位置上。

四 匹配成功或失败

分支和回溯:

 /h(ello|appy) hippo/.test("hello there, happy hippo");  

重复和回溯:

var str = "<p>Para 1.</p>" +
"<img src='smiley.jpg'>" +
"<p>Para 2.</p>" +
"<div>Div.</div>";
/<p>.*<\/p>/i.test(str);

*是贪婪量词 可以改用非贪婪量词 *?尝试的匹配的过程不同

回溯失控:

/<html>[\s\S]*?<head>[\s\S]*?<title>[\s\S]*?<\/title>[\s\S]*?<\/head>
[\s\S]*?<body>[\s\S]*?<\/body>[\s\S]*?<\/html>/  

如果目标字符串缺少一个或多个标签的时候 情况很糟糕

/<html>(?:(?!<head>)[\s\S])*<head>(?:(?!<title>)[\s\S])*<title>
(?:(?!<\/title>)[\s\S])*<\/title>(?:(?!<\/head>)[\s\S])*<\/head>
(?:(?!<body>)[\s\S])*<body>(?:(?!<\/body>)[\s\S])*<\/body>
(?:(?!<\/html>)[\s\S])*<\/html>/

这个改进的虽然可以避免回溯失控但是效率非常底下。

使用前瞻和后向引用列举原子组:

/<html>(?=([\s\S]*?<head>))\1(?=([\s\S]*?<title>))\2(?=([\s\S]*?
<\/title>))\3(?=([\s\S]*?<\/head>))\4(?=([\s\S]*?<body>))\5
(?=([\s\S]*?<\/body>))\6[\s\S]*?<\/html>/







 

原创粉丝点击