Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/430.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
防止在JavaScript中污染RegExp构造函数的属性_Javascript_Regex - Fatal编程技术网

防止在JavaScript中污染RegExp构造函数的属性

防止在JavaScript中污染RegExp构造函数的属性,javascript,regex,Javascript,Regex,这是一个难题,我有一个想法,我可能能够修复它,但我想知道是否有一个(更)简单的方法 简而言之,每当在JavaScript中执行正则表达式时,都会在RegExp构造函数上为某些属性赋值。例如: /foo/.test('football') //-> true RegExp.input //-> "football" RegExp.rightContext //-> "tball" 我希望在不影响这些属性的情况下执行正则表达式。如果这是不可能的(我不认为是),我想至少在以后将

这是一个难题,我有一个想法,我可能能够修复它,但我想知道是否有一个(更)简单的方法

简而言之,每当在JavaScript中执行正则表达式时,都会在
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;
}