0

我正在研究这个脚本,它可以让您使用插值变量构建正则表达式。目前我得到了这个,它工作得很好:

function sRegExp( regex, vars ) {
  vars = Array.prototype.slice.call( arguments, 1 );
  regex = regex.toString();
  var newRegex = regex.replace(/(^\/|\/$|\/([igm]+)$)/g, '')
    .replace( /#\{(\d)\}/g, function( a, b ) { return vars[ +b ]; });
  var mods = regex.match( /\/([igm]+)$/ );
  return new RegExp( newRegex, mods ? mods[1] : '' );
}

我像这样使用它:

function func() {
  var foo = 'lol';
  return sRegExp( /baz #{0}/i, foo );
}

console.log( func() ); //=> /baz lol/i

我想通过使用变量名来改进这个脚本,而不是使用索引并将变量作为参数传递,所以我想到了使用eval,所以我去掉vars并重构了代码:

function sRegExp( regex ) {
  regex = regex.toString();
  var newRegex = regex.replace(/(^\/|\/$|\/([igm]+)$)/g, '')
   .replace( /#\{(\w+)\}/g, function( a, b ) { return eval( b ); });
                 __^__                               __^__
  var mods = regex.match( /\/([igm]+)$/ );
  return new RegExp( newRegex, mods ? mods[1] : '' );
}

上一个示例现在的问题是:

console.log( func() ); //=> foo is not defined

但在全球范围内...

var foo = 'lol';
function func() {
  return sRegExp( /baz #{foo}/i );
}

console.log( func() ); //=> /baz lol/i

如何设置eval. 我试过eval.call(func)了,但这显然没有用。有任何想法吗?

4

2 回答 2

2

您不能设置 的范围eval。它继承了本地执行上下文,因此只能看到其调用上下文看到的内容(在本例中为 within func)。不幸的是,没有办法解决这个问题。

当控制进入 eval 代码的执行上下文时,先前的活动执行上下文(称为调用上下文)用于确定作用域链、变量对象和 this 值。如果没有调用上下文,则初始化作用域链、变量实例化和 this 值的确定就像全局代码一样执行。

来自:ES 3.1 10.2.2 评估代码

于 2012-10-15T07:50:58.777 回答
2

我不喜欢eval也不喜欢弄乱全球空间。所以,我的回答是有偏见的。

您可以将命名变量作为参数传递。

function func() {
  return sRegExp( /baz #{foo}/i, { foo: "lol" } );
}

function sRegExp( regex, vars ) {
  ...
  var newRegex = regex.replace(/(^\/|\/$|\/([igm]+)$)/g, '')
      .replace( /#\{(\w+)\}/g, function( a, b ) { return vars[b]; });
  ...
}
于 2012-10-15T07:54:24.043 回答