RegExp在IE8等浏览器中的兼容性问题

本文探讨了正则表达式在IE8及其更早版本中的兼容性问题,包括split()方法处理正则时的数组空值、分组结果的差异,以及lastIndex属性在0长度匹配和replace方法后的行为。对于lastIndex的问题,文章提供了两种避免死循环的解决方案,并指出在不同浏览器中replace方法对lastIndex的影响。最后,提到了IE8对[]和[^]的特殊解析,导致解析错误。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这里讲的兼容性问题主要指String的API在正则表达式的处理上不同。

匹配结果的兼容性

第一个问题:在IE<=8中,如果split()方法的限定符是正则表达式,返回的数组不包含空值元素,而如果限定符用字符串表示则没有这样的问题:

",,ab,,".split(","); // output ["","","ab","",""]
",,ab,,".split(/,/); // output ["ab"]

第二个问题:正则表达式中可能有分组,但是这个分组可能并没有参与(也就是没有匹配到任何子字符串)。关于这个分组的结果:IE<=8返回的不是undefined,而Firefox2会返回空字符串,Safari3则直接什么也不返回(结果导致数组元素个数减少)。

"y".split(/(x)?y/); // ECMA :output ["",undefined,""]
"y".split(/(x)?y/); // IE8 :output []

如果是调用字符串的match方法,返回的结果也不同:

"y".match(/(x)?y/); // ECMA :output ["y",undefined]
"y".match(/(x)?y/); // IE8 :output ["y", ""]

因此,替换的时候,返回的结果也不同:

// ECMA :output "undefined"
// IE8: output ""
"y".replace(/(x)?y/,function($0,$1){return String($1);};

关于lastIndex的几个问题

0长度匹配时,lastIndex不变

先来看正常情况:如果执行带/g的RegExp的exec或test方法,它会从RegExp的lastIndex位置开始搜索。如果exec或test方法匹配到了,则更新RegExp的lastIndex索引为当前匹配的尾部。如果没有找到,则重置lastIndex为0,同时返回null。

不正常情况:如果匹配的是空字符,也就是匹配长度为0,那么lastIndex就永远是0。其结果就是导致下面这段代码在大部分浏览器中陷入死循环。

var regex = /^/gm,
   subject ="A\nB\nC",
   match,
   endPositions = []; 

while (match = regex.exec(subject)){
   endPositions.push(regex.lastIndex);
}

// endPositions = [1,3,5] in IE <=8
// infinite loop in other browsers

为了避免死循环,IE<=8采用的方法是:即使匹配的长度为0,依然使lastIndex往后移。

解决死循环的方法一:

var regex= /^/gm,
   subject ="A\nB\nC",
   match,
   endPositions = []; 

while (match = regex.exec(subject)) {
   var zeroLengthMatch =!match[0].length;
   // Fix IE's incorrectlastIndex
   if (zeroLengthMatch&& regex.lastIndex > match.index)
      regex.lastIndex--;

   endPositions.push(regex.lastIndex);

   // Avoid an infiniteloop with zero-length matches
   if (zeroLengthMatch)
      regex.lastIndex++;
}

解决死循环方法二:使用String.prototype.replace方法。

因为在replace方法中可以轻松获取匹配字符串的长度和位置,所以可以根据这两个数据算出lastIndex = indx + match.length。

执行replace方法,lastIndex可能会变

在IE<=8中,无论是非全局匹配替换还是全局匹配替换,lastIndex都会变,而且全局匹配替换之后,lastIndex也没有重置为0。而在Firefox,Chrome,IE>=9,Safari中,当replace方法执行全局匹配替换和非全局匹配替换时,lastIndex永远是0。

IE<=8,执行String.prototype.replace方法之后,RegExp对象的lastIndex没有重置为0。

var	regexp = /l/;
var text = "hello";

text.replace(regexp, function(match) {
	// output 3 in IE8
	console.log(regexp.lastIndex);
	return match;
});

console.log(regexp.lastIndex); // output 3 in IE8

在Firefox,Chrome,IE>=9,Safari中,当replace方法执行全局匹配时,RegExp的lastIndex一直为0,而在IE<=8中lastIndex会变:

var regexp = /l/g;
var text = "hello";

text.replace(regexp, function(match) {
   console.log(regexp.lastIndex);// output 0
   return match;
});

console.log(regexp.lastIndex); // output 0 in FF,Chrome,IE>=9

关于[]和[^]

在IE<=8中,不允许出现[]或[^],这是因为IE<=8认为第一个右中括号(])属于原义字符而不是一个和左中括号相匹配的特殊字符,除非[]中含有其他字符。

因此以下正则表达式在IE<=8都会报错,错误信息为"Expected ']' in regular expression"。

var regexp = /[]/;
var regexp = /[^]/;
var regexp = /a[^]/; 
var regexp = /a[]/;
智慧农业-基于STM32F103C8T6开发的智能大棚温湿度传感系统源码(课程设计) 该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到94.5分,放心下载使用! 该资源适合计算机相关专业(如人工智能、通信工程、自动化、软件工程等)的在校学生、老师或者企业员工下载,适合小白学习或者实际项目借鉴参考! 当然也可作为毕业设计、课程设计、课程作业、项目初期立项演示等。如果基础还行,可以在此代码基础之上做改动以实现更多功能。 简介 ``` 本温室传感系统包括数据采集模块与无线蓝牙传输模块,主控MCU为STM32F103C8T6。 主要文件及文件夹为: - ./Drivers/Peripheral - ./Core/Src/main.c ``` 开发环境 ``` - 系统:windows 10 - 集成开发环境:STM32CubeIDE - 下载工具:STM32CubeProgrammer + CH340(USB to TTL) ``` 子模块 传感模块 ``` - SHT31 SHT31为I2C总线协议温湿度传感模块,支持“单次转换”和“周期转换”模式,本次设计中使用单次转换模式。 - GY30 GY30为I2C总线协议光照传感模块,支持“单次转换”和“周期转换”模式,本次设计中使用周期转换模式。 ``` 传输模块 HC-05为无线蓝牙传输模块,支持串口收发。预先于PC上使用AT指令配置蓝牙热点,接上单片机即可直接收发数据。 引脚分配 ``` - STM32 === 外设/引脚 - PA2 === HC-05/RXD - PA3 === HC-05/TXD - PA5 === LCD1602/WR - PA6 === LCD1602/RD - PA7 === LCD1602/E - PA15 === LCD1602/D0 - PB3 === LCD1602/D1 - PB4 === LCD1602/D2 - PB5 === LCD1602/D3 - PB6 === LCD1602/D4 - PB7 === LCD1602/D5 - PB8 === LCD1602/D6 - PB9 === LCD1602/D7 - PB10 === I2C-SCL(总线) - PB11 === I2C-SDA(总线)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值