簡體   English   中英

使用eval正確確定范圍

[英]Getting the scope right with eval

我正在研究此腳本,該腳本可讓您使用插值變量構建正則表達式。 目前,我得到了它,並且效果很好:

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)但這顯然沒有用。 有任何想法嗎?

您不能設置eval的范圍。 它繼承了本地執行上下文,因此只能看到其調用上下文所看到的內容(在這種情況下,在func )。 不幸的是,這沒有辦法。

當控件進入評估代碼的執行上下文時,先前的活動執行上下文(稱為調用上下文)將用於確定范圍鏈,變量對象和this值。 如果沒有調用上下文,則與全局代碼一樣,執行范圍鏈的初始化,變量實例化和此值的確定。

從: ES 3.1 10.2.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]; });
  ...
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM