JavaScript闭包 - Eval()和捕获Eval()范围内的变量

时间:2011-09-21 16:33:06

标签: javascript closures

我的问题是关于JavaScript Closures和Eval()函数。

我有一些看起来像这样的代码,还有一些其他jQuery插件相关的代码没有显示。如果需要,我可以用更多代码更新问题。

var _CurrentDataRowIndex = 1;

function LoadParsedRowTemplate(rowData, type) {

    var result;
    var asyncbinder = /&\{[\S\s]*?}&/g;

        while ((result = asyncbinder.exec(template)) != null) {
            replacement = eval("$.fn.ScreenSetup." + result[0].substring(2, result[0].length - 3) + ", rowData, " + _CurrentDataRowIndex + ")");
            template = template.replace(result[0], "AsyncBind!!");
            asyncbinder.lastIndex = 0;
        }

}

function AsynchronousBind(asyncFunc, args, rowData, rowIndex) {

    var watchTimer;

    asyncFunc.apply(this, Array.prototype.slice.call(args.FunctionArgs, 0));

    watchTimer = setInterval(function () {

        if (args.finished) {
            clearTimeout(watchTimer);
        }
        else {
            try {
                console.log("watching the async function for a return on row: " + rowIndex);
            }
            catch (err) {
            }
        }

    }, 1000);

}

Eval没有捕获rowData和_CurrentDataRowIndex,当调用AsynchronousBind函数时,两者都是未定义的。 eval如何使用闭包?我想知道为什么在AsynchronousBind中未定义rowData和rowIndex参数。

修改

我知道eval()的争议本质,但这是针对防火墙应用程序的背后,我正在添加一个我们已编写的插件,它使用eval来解析包含HTML和JavaScript的模板。

以下是传递给eval()的字符串示例:

 "$.fn.ScreenSetup.AsyncBind( _CurrentDataRow.isPromotionAvailable, {
     'FunctionArgs': {'doAsync' : true, 
                      'finished' : false}, 
      'Property': 'isPromotionAvailable()', 
      'ControlType': 'TextBox', 
      'ControlIdPrefix': 'promoAvail'}, rowData, 3)"

修改(固定):

意识到当我添加rowData和rowItem时,我忘记在我的插件中更改以下内容:

var asyncMethods = {
    AsyncBind: function (func, args) { return AsynchronousBind(func, args) }
}

应该是:

var asyncMethods = {
    AsyncBind: function (func, args, rowData, rowIndex) { return AsynchronousBind(func, args, rowData, rowIndex) }
}

更新此项修复了AsyncBind函数中未定义的引用。

1 个答案:

答案 0 :(得分:5)

Understanding eval scope是一篇有趣的文章。它表明浏览器的范围不一致。如果必须使用eval,则应注意仅依赖于它在全局范围内,并且如果在本地范围内进行求值,则不要在本地范围内重用全局变量名。

更好的是,只是不要使用eval。你可能还有其他选择。