Prev: FAQ Topic - Why does simple decimal arithmetic give strange results? (2010-07-29)
Next: validate 3 fields
From: RobG on 28 Jul 2010 22:51 I stumbled across a function that tests if a global variable exists or not, my version of the code is below. Other than the obvious irrelevance of such a function (a simple typeof test should be sufficient in every case I can imagine), and that the use of try..catch and eval should be limited as much as possible, are there any significant issues with it? function doesGlobalVarExist(v) { try { eval(v); return true; } catch(e) { return false; } } Given the description of the eval function in ECMA-262 ed 3 (ES 3) § 15.1.2.1 and eval code in § 10.1.2, it seems that when using a "namespace" with functions initialised from an anonymous function it is impossible to use eval to run code with global scope, e.g.: var zz = 'Global zz'; var fn = (function() { var zz = 'Local zz'; return function(v) { return eval(v); } })(); alert(fn('zz')); // shows "Local zz" The above always resolves to the local zz because the calling context is placed on eval's scope chain when it is called, so the global zz is "shadowed". Can eval code be run as global code using this scenario? Are there cases where that is desirable (such as a "doesGlobalVarExist" function)? There is a statement in ES5 §10.4.2 that says: "...if the eval code is not being evaluated by a direct call (15.1.2.1.1) to the eval function then...Initialize the execution context as if it was a global execution context" I can't see how to call eval other than as a direct call. Lastly, ES 3 says: "if the eval property is assigned to, an EvalError exception may be thrown" Neither browser does, they allow assignments to eval. -- Rob
From: David Mark on 28 Jul 2010 23:13 On Jul 28, 10:51 pm, RobG <rg...(a)iinet.net.au> wrote: > I stumbled across a function that tests if a global variable exists or > not, my version of the code is below. Other than the obvious > irrelevance of such a function (a simple typeof test should be > sufficient in every case I can imagine), and that the use of > try..catch and eval should be limited as much as possible, are there > any significant issues with it? > > function doesGlobalVarExist(v) { > > try { > eval(v); > return true; > > } catch(e) { > return false; > } > } doesGlobalVarExist('v'); // true regardless You could use:- eval(arguments[0]); ....but as you noted, there's no practical use for this. > > Given the description of the eval function in ECMA-262 ed 3 (ES 3) § > 15.1.2.1 and eval code in § 10.1.2, it seems that when using a > "namespace" with functions initialised from an anonymous function it > is impossible to use eval to run code with global scope, e.g.: > > var zz = 'Global zz'; > > var fn = (function() { > var zz = 'Local zz'; > return function(v) { > return eval(v); > } > })(); > > alert(fn('zz')); // shows "Local zz" Use the Function constructor. > > The above always resolves to the local zz because the calling context > is placed on eval's scope chain when it is called, so the global zz is > "shadowed". Can eval code be run as global code using this scenario? > Are there cases where that is desirable (such as a > "doesGlobalVarExist" function)? > > There is a statement in ES5 §10.4.2 that says: > > "...if the eval code is not being evaluated by a direct call > (15.1.2.1.1) to the eval function then...Initialize the > execution context as if it was a global execution context" That came years too late for some libraries I can think of. :) > > I can't see how to call eval other than as a direct call. // NOTE: Do NOT use this as it may require ES5 var global = this, testing = '123'; (function(v) { var testing; window.alert(global.eval(v)); // '123' })('testing'); That will work in some modern browsers without ES5. It's not something to depend on though. The Function constructor should be used instead. > > Lastly, ES 3 says: > > "if the eval property is assigned to, an EvalError > exception may be thrown" > > Neither browser does, they allow assignments to eval. Neither browser? :)
From: RobG on 29 Jul 2010 01:19 On Jul 29, 1:13 pm, David Mark <dmark.cins...(a)gmail.com> wrote: > On Jul 28, 10:51 pm, RobG <rg...(a)iinet.net.au> wrote: > > > > > I stumbled across a function that tests if a global variable exists or > > not, my version of the code is below. Other than the obvious > > irrelevance of such a function (a simple typeof test should be > > sufficient in every case I can imagine), and that the use of > > try..catch and eval should be limited as much as possible, are there > > any significant issues with it? > > > function doesGlobalVarExist(v) { > > > try { > > eval(v); > > return true; > > > } catch(e) { > > return false; > > } > > } > > doesGlobalVarExist('v'); // true regardless As is: doesGlobalVarExist(); but that would be covered by the documentation. ;-) [...] > > Given the description of the eval function in ECMA-262 ed 3 (ES 3) § > > 15.1.2.1 and eval code in § 10.1.2, it seems that when using a > > "namespace" with functions initialised from an anonymous function it > > is impossible to use eval to run code with global scope, e.g.: > > > var zz = 'Global zz'; > > > var fn = (function() { > > var zz = 'Local zz'; > > return function(v) { > > return eval(v); > > } > > })(); > > > alert(fn('zz')); // shows "Local zz" > > Use the Function constructor. Ok, using: try { Function('return ' + arguments[0] + ';')(); return true; }... seems to be a solution. > > The above always resolves to the local zz because the calling context > > is placed on eval's scope chain when it is called, so the global zz is > > "shadowed". Can eval code be run as global code using this scenario? > > Are there cases where that is desirable (such as a > > "doesGlobalVarExist" function)? > > > There is a statement in ES5 §10.4.2 that says: > > > "...if the eval code is not being evaluated by a direct call > > (15.1.2.1.1) to the eval function then...Initialize the > > execution context as if it was a global execution context" > > That came years too late for some libraries I can think of. :) [...] > > I can't see how to call eval other than as a direct call. > > // NOTE: Do NOT use this as it may require ES5 > > var global = this, testing = '123'; > > (function(v) { > var testing; > > window.alert(global.eval(v)); // '123' > > })('testing'); > > That will work in some modern browsers without ES5. It's not > something to depend on though. The Function constructor should be > used instead. I actually tried something like that but the code wasn't doing what I thought it was so it was discarded prematurely, here's a fixed version that "works": var fn = (function() { var zz = 'Outer local zz'; var global = (function(){return this})(); return function(v) { // var zz = 'Innner local zz'; try { global.eval(arguments[0]); return true; } catch(e) { return false; } } })(); alert('fn zz: ' + fn('zz')); // false But I don't understand why it works. The eval function is still called from within another function, calling it as global.eval should just change the value of the function's this keyword for property resolution, shouldn't the enclosing activation object still be on the scope chain and be involved in identifier resolution? As far as I can see, it's the same as: eval.call(global, arguments[0]); which "works" also. The spec says "...if the eval code is not being evaluated by a direct call [use global scope]", isn't global.eval a direct call, and therefore should not be given global scope? The variable object of the inner function (the one that calls global.eval) seems to be on the scope chain - uncommenting the inner local zz returns true. > > Lastly, ES 3 says: > > > "if the eval property is assigned to, an EvalError > > exception may be thrown" > > > Neither browser does, they allow assignments to eval. > > Neither browser? :) Ooops, I had a sentence that said I was testing in Firefox and IE 6 only but I seem to have edited that out, so neither of those. -- Rob
From: RobG on 29 Jul 2010 01:27 On Jul 29, 3:19 pm, RobG <rg...(a)iinet.net.au> wrote: > On Jul 29, 1:13 pm, David Mark <dmark.cins...(a)gmail.com> wrote: > > On Jul 28, 10:51 pm, RobG <rg...(a)iinet.net.au> wrote: [...] > > > I can't see how to call eval other than as a direct call. > > > // NOTE: Do NOT use this as it may require ES5 > > > var global = this, testing = '123'; > > > (function(v) { > > var testing; > > > window.alert(global.eval(v)); // '123' > > > })('testing'); > > > That will work in some modern browsers without ES5. It's not > > something to depend on though. The Function constructor should be > > used instead. > > I actually tried something like that but the code wasn't doing what I > thought it was so it was discarded prematurely, here's a fixed version > that "works": In Firefox but not IE 6. > var fn = (function() { > > var zz = 'Outer local zz'; > var global = (function(){return this})(); > return function(v) { > > // var zz = 'Innner local zz'; > > try { > global.eval(arguments[0]); > return true; > } catch(e) { > return false; > } > } > })(); > > alert('fn zz: ' + fn('zz')); // false > > But I don't understand why it works. The eval function is still called > from within another function, calling it as global.eval should just > change the value of the function's this keyword for property > resolution, shouldn't the enclosing activation object still be on the > scope chain and be involved in identifier resolution? As far as I can > see, it's the same as: > > eval.call(global, arguments[0]); > > which "works" also. The spec says "...if the eval code is not being > evaluated by a direct call [use global scope]", isn't global.eval a > direct call, and therefore should not be given global scope? In IE 6 it isn't given global scopie, it still returns true. > The > variable object of the inner function (the one that calls global.eval) > seems to be on the scope chain - uncommenting the inner local zz > returns true. It seems the outer scope is omitted in Firefox but remains in IE. A quirk that is unlikely to surface very often, but probably Firefox is not conforming to ECMA-262 here. -- Rob
From: Dmitry A. Soshnikov on 29 Jul 2010 01:51
On 29.07.2010 6:51, RobG wrote: <snip> > > There is a statement in ES5 �10.4.2 that says: > > "...if the eval code is not being evaluated by a direct call > (15.1.2.1.1) to the eval function then...Initialize the > execution context as if it was a global execution context" > > I can't see how to call eval other than as a direct call. > <http://dmitrysoshnikov.com/ecmascript/es5-chapter-2-strict-mode/#indirect-eval-call> Dmitry. |