Reputation: 7861
My question is regarding JavaScript Closures and the Eval() function.
I have some code that looks like this, there is also some other jQuery plugin related code taht is not shown. I can update the question with more code if needed.
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 is not capturing rowData and _CurrentDataRowIndex, both are undefined when the AsynchronousBind function is called. How does eval work with closures? I am wondering why the rowData and rowIndex arguments are undefined in AsynchronousBind.
Edit:
I am aware of the controversial nature of eval(), however this is for a behind the firewall app, and I'm adding to a plugin we've already written that uses eval to parse templates that contain HTML and JavaScript.
Here is an example of the string being passed into eval():
"$.fn.ScreenSetup.AsyncBind( _CurrentDataRow.isPromotionAvailable, {
'FunctionArgs': {'doAsync' : true,
'finished' : false},
'Property': 'isPromotionAvailable()',
'ControlType': 'TextBox',
'ControlIdPrefix': 'promoAvail'}, rowData, 3)"
Edit (Fixed):
Realized that when I added rowData and rowItem I I forgot to change the following in my plugin:
var asyncMethods = {
AsyncBind: function (func, args) { return AsynchronousBind(func, args) }
}
Should of been:
var asyncMethods = {
AsyncBind: function (func, args, rowData, rowIndex) { return AsynchronousBind(func, args, rowData, rowIndex) }
}
Updating this fixed the undefined reference in the AsyncBind function.
Upvotes: 3
Views: 3753
Reputation: 78840
Understanding eval scope is an interesting article. It shows that the scope is inconsistent among browsers. If you must use eval, you should be careful to only count on it being in global scope, and don't reuse global variable names in your local scope in case it is evaluated locally.
Better yet, just don't use eval. You probably have other options.
Upvotes: 6