防止在JavaScript中污染RegExp构造函数的属性
这是一个难题,我有一个想法,我可能能够修复它,但我想知道是否有一个(更)简单的方法 简而言之,每当在JavaScript中执行正则表达式时,都会在防止在JavaScript中污染RegExp构造函数的属性,javascript,regex,Javascript,Regex,这是一个难题,我有一个想法,我可能能够修复它,但我想知道是否有一个(更)简单的方法 简而言之,每当在JavaScript中执行正则表达式时,都会在RegExp构造函数上为某些属性赋值。例如: /foo/.test('football') //-> true RegExp.input //-> "football" RegExp.rightContext //-> "tball" 我希望在不影响这些属性的情况下执行正则表达式。如果这是不可能的(我不认为是),我想至少在以后将
RegExp
构造函数上为某些属性赋值。例如:
/foo/.test('football')
//-> true
RegExp.input
//-> "football"
RegExp.rightContext
//-> "tball"
我希望在不影响这些属性的情况下执行正则表达式。如果这是不可能的(我不认为是),我想至少在以后将它们恢复到以前的值
我知道input
/$\ucode>是可写的,但其他大多数似乎都不是。一种选择可能是重建一个正则表达式,重新应用所有这些值,但我认为这将是相当困难的
我之所以希望这样做,是因为我正在编写一个测试,并使用test262套件对其进行测试。test262套件在某些测试中失败,它会检查RegExp对象是否具有这些属性的意外值。这是最终结果。这比我最初的努力要有力一点;它正确地转义子表达式,确保它们以正确的顺序出现,并且在找到空表达式时不会停止:
/**
* Constructs a regular expression to restore tainted RegExp properties
*/
function createRegExpRestore () {
var lm = RegExp.lastMatch,
ret = {
input: RegExp.input
},
esc = /[.?*+^$[\]\\(){}|-]/g,
reg = [],
cap = {};
// Create a snapshot of all the 'captured' properties
for (var i = 1; i <= 9; i++)
cap['$'+i] = RegExp['$'+i];
// Escape any special characters in the lastMatch string
lm = lm.replace(esc, '\\$0');
// Now, iterate over the captured snapshot
for (var i = 1; i <= 9; i++) {
var m = cap['$'+i];
// If it's empty, add an empty capturing group
if (!m)
lm = '()' + lm;
// Else find the escaped string in lm wrap it to capture it
else
lm = lm.replace(m.replace(esc, '\\$0'), '($0)');
// Push to `reg` and chop `lm`
reg.push(lm.slice(0, lm.indexOf('(') + 1));
lm = lm.slice(lm.indexOf('(') + 1);
}
// Create the property-reconstructing regular expression
ret.exp = RegExp(reg.join('') + lm, RegExp.multiline ? 'm' : '');
return ret;
}
您可以尝试为测试创建包装函数:
var fTest = RegExp.test;
RegExp.test = function() {
var bReturn = fTest.apply(RegExp, arguments);
delete RegExp.input;
delete RegExp.rightContext;
return bReturn;
}
这一定是暂时的吗?我喜欢你揭示的难题。然而,我的想法是,您正在更改系统中不需要更改以适应损坏部分的部分:损坏部分是您的测试框架。如果最终产品不要求RegExp对象保持其原始状态,那么就没有理由让框架中的任意测试强迫您重写代码。我想说的是,您想要更改的部分是测试框架。我想你是在寻找配置选项之类的选项来忽略对RegExp对象的某些测试?@Hurricane:是的,我可以选择忽略它,我几乎做到了。如果这个解决方案不是那么容易的话,我可能会的。然而,由于我正在为本机API编写一个垫片,我希望它尽可能接近实现,以覆盖所有基础。不过,我已经多次将测试规则向我倾斜,这是不可能的。这不会“恢复”以前的状态(它只是从对象中删除这些属性),在大多数属性都是getter的Google Chrome中也不起作用。此外,它还改变了内置的RegExp.prototype.test
方法的行为,这是不需要的。
var fTest = RegExp.test;
RegExp.test = function() {
var bReturn = fTest.apply(RegExp, arguments);
delete RegExp.input;
delete RegExp.rightContext;
return bReturn;
}