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。ローカル実行コンテキストを継承するため、呼び出し元のコンテキスト (この場合は 内func) が参照するもののみを参照します。残念ながら、これを回避する方法はありません。

制御が eval コードの実行コンテキストに入ると、呼び出しコンテキストと呼ばれる以前のアクティブな実行コンテキストを使用して、スコープ チェーン、変数オブジェクト、および this 値が決定されます。呼び出しコンテキストがない場合、グローバル コードの場合と同様に、スコープ チェーンの初期化、変数のインスタンス化、および this 値の決定が実行されます。

From: 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 に答える