2012-10-15 111 views
0

我正在研究這個腳本,它允許您使用插值變量構建正則表達式。目前,我得到了這一點,它精美的作品:使用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 

我想通過使用變量名,而不必使用索引來提高這個腳本並通過在變量PARAMS,所以我想用eval,讓我擺脫了vars和重構的代碼位:與p

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] : ''); 
} 

現在的問題revious例子是這樣的:

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

回答

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]; }); 
    ... 
} 
+0

是的,這是一個好主意,但仍然很冗長,但我喜歡。看起來像我的_令人敬畏的idea_不是那麼可怕... – elclanrs

+0

@elclanrs,好吧,如果你仍然想堅持使用全局範圍,那麼你可以使用'window' – Alexander

2

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

當控制進入eval代碼的執行上下文時,上一個活動執行上下文(稱爲調用上下文)用於確定範圍鏈,變量對象和此值。如果沒有調用上下文,則初始化範圍鏈,變量實例化以及確定該值與全局代碼一樣。

來源:ES 3.1 10.2.2 Eval Code

+0

所以它周圍的唯一途徑,我發現是,如果我使用'this.foo =「lol''然後'eval'將輸出正確的值,但這並不理想。必須有辦法做我想做的事,但是怎麼做? – elclanrs

+0

剛剛意識到它的工作原理是因爲'this'是'window' ... Arrg,似乎沒有辦法繞過它。 – elclanrs