[英]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值。 如果沒有調用上下文,則與全局代碼一樣,執行范圍鏈的初始化,變量實例化和此值的確定。
我既不喜歡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.