木灵鱼儿 - 正则表达式
type: channel
link: https://www.mulingyuer.com/tag/%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F/
items: 字符和正则表达式

字符和正则表达式
type: item
date: 2019-06-14T07:23:36+08:00
description: 字符串连接标准的方式都是A+B通过+进行连接，如果是下面这种写法：str += 'one' + 'two';这段代码会经历四个步骤：先在内存中创建一个新的临时字符串（内容为空）one和two先进行连接并赋值给临时字符串临时字符串与str进行连接返回的值赋值给str如果我们这样写可以避免创建临时字符串str += 'one'; str += 'two';因为只有一个字符串需要添加，然后str本身就是字符串，所以只对str进行了操作，没有再去创建新的临时字符。但是这样写太过麻烦，于是可以这样写：str = str + 'one' + 'two';因为字符的操作是从=符号开始，从左到右操作，此时str本身是一个占据在内存中的字符串，所以无需创建新的临时字符，然后依次往右连接，最后赋值，为此可以加快速度。但是在ie7及更早的版本，这种方式反倒没有加速的效果，反而会增加用时，原因是ie每次连接的时候都会每进行一步就复制一次，先将str和one连接的结果复制一次，复制一次后再复制后面的two，然后再将这两个连接的结果复制一次，依次 重复，所以在旧版的ie中，使用+=反倒更快了。但是+=也不能说明就是ie的最佳方案，在大量文字连接中，+=也是很慢，但是我们可以通过数组项合并的方式提高速度。数组项合并Array.prototype.join方法是将数组中的分隔符改变成其他的值，我们可以通过去除这个分隔符达到合并数组的效果，但是这个方法实际上在现在浏览器中是一个比较慢的方法，在旧版的ie反倒可以达到意料之外的效果。var str = 'I', strs = [], num = 5000, newStr = null; while(num--) { strs.push(str); } newStr = strs.join('');这样写反倒快于用for循环str+ ‘I’的方法。当然也仅限于旧版的ie。正则表达式正则表达式的优化要首先明白他的工作原理，最主要的就是理解回溯。回溯就是当正则匹配到一定的值后会继续查找正则后面的值，比如/.*\s+/；首先正则会贪婪的将所有字符匹配到，然后进行回溯，也就是从最后一个字符往前查找，当找到一个\s是并不会立即放弃，它还会继续回溯，直到找不到\s字符了。如果是惰性模式/.*?\s+/，它的方式又不一样了，惰性可以理解为最少次数，所以他会从最开始一个一个字符回溯，找到一个\s后并不会立即停止，它还会继续查找，直到后面的字符不是\s后才会停止。使用不明确的正则容易造成回溯失控，你可以把回溯理解为路口，当你到了一个站点后，就会根据实际情况产生多个不同的选择，每个选择为一个路口，当正则在第一个路口找不到的时候就会返回到第二个路口，然后无限重复，直到找到了值或者全部路口都找不到才会停下，所以说，能找到的正则时间最短，找不到的正则是最慢的，因为他要不断的回溯。为此宽泛的正则性能往往不如更具体的选择，.*往往不如[white]这种实际指出的值，然后我们还可以通过一些位置符减少回溯的次数，比如\b、\B这种。var str = 'AAAAAAAAAAAAAAAAAAAAAAAAAA'; var reg = /A+A+B/g; var time = +new Date(); alert(reg.test(str) +' ' + (+new Date() - time))这段代码中，如果str没有最后的B字符，正则依旧会不断的重复回溯很多次，A+A+会产生众多的路口，为此我们要考虑到一种情况，就是当str中没有B的时候该怎么办？这里我们就可以使用预查?!var str = 'AAAAAAAAAAAAAAAAAAAAAAAAAA'; var reg = /A+A+(?=B)B/g; var time = +new Date(); alert(reg.test(str) +' ' + (+new Date() - time))通过这个预查可以减少回溯的点，因为预查已经判断到了A+A+的部分，后面是要有B的，那么正则就不会再一个个判断，为此减少了时间，alert输出的时候，你会发现使用之前的正则返回1毫秒的时间，而使用预查的只用了0毫秒，速度非常之快，如果在大量文本内容的时候，预查的优势也会很高，但是不能滥用，预查也是可以进行一定的优化的。捕获正则中的捕获()也就是分组会将里面的内容额外的保存起来，如果大量不用的捕获，会浪费内存的空间，为此可以使用非捕获来减少空间占用。/^[a-z]+(?:.*)/通过非捕获?:来达到减少占用。事实上预查虽然是一个()，但是他是非捕获性的，所以他不能被回调所调用。何时不使用正则其实这里主要是因为正则只能从开始匹配到末尾，没办法从末尾匹配到开头，哪怕你使用了$字符申明，但是他依旧是从前到后，所以如果是针…