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
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? :)
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
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
<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.
Yes. Passing no argument at all would not lead to defined results.
>
> [...]
>
>
>
> > > 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.
To a non-problem of course. :)
>
> > > 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":
You did see the disclaimer, right? Do not use that code. It is not
based on standards and is known to fail in some ES3 implementations.
>
> 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.
Neither did the Dojo authors. ;) The fact is that it doesn't work
(not cross-browser anyway) and should never be expected to work
outside of ES5.
> 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]);
Different browsers do different things with that. I posted it as an
example of the bit of ES5 you quoted. I assume they put that clause
in there to prop up faltering libraries and other junk code prevalent
on the Web.
>
> 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?
Which spec are we talking about? ES5? ES3 says that global.eval may
well throw an exception and guarantees nothing about its behavior.
> 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.
In ES3 there is no telling. There have been charts published here
before detailing what the various browsers do with such a call. Even
if they were all observed to do the same thing, it is best to avoid it
as the specs make no promises as to its behavior.
See my previous follow-up. The use of global.eval is unpredictable.
That's why it was one of the first things I tried to yank out of
Dojo's loader (of course, it's still in there, but they do have some
very nice new background graphics to compensate).
>
> > 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.
There's nothing related to this in that spec to conform to. That's
the problem.
function isGlobal(what) {
return execScript('"' + what + '" in this');
}
in ES3 we can generally use
function isGlobal(what) {
return what in (function(){return this}());
}
but since in ES5 and "use strict" this won't be the global object ...
// compatible ES5 and "use strict"
var isGlobal = function (what) {
function $isGlobal(what) {
return what in context;
}
var
script = document.createElement("script"),
context = document.documentElement
;
script.text = "this.$isGlobal=this;";
context.insertBefore(script, context.firstChild);
context.removeChild(script);
script = null;
context = $isGlobal;
delete context.$isGlobal;
context.isGlobal = (isGlobal = $isGlobal);
return isGlobal(what);
};
Regards,
Andrea Giammarchi
uhm, there is a typo in the global name, call it _isGlobal or the
context will be the function ...
And what's with falsy values ?
> 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?
You never know for sure. Browser makers seem to be changing this every
day. But to be sure you could do:
(new Function("p", "return eval(p)"))(evalInput);
> 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.
var indirectEval= window.eval;
indirectEval();
> 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.
Why not:
"k" in window
--> false
var k;
--> undefined
"k" in window
--> true
?
--
Jorge.
Scene missing?
>
> function isGlobal(what) {
> return execScript('"' + what + '" in this');
>
> }
Why wouldn't you just use a function constructor (as described
previously?)
>
> in ES3 we can generally use
>
> function isGlobal(what) {
> return what in (function(){return this}());
>
> }
>
> but since in ES5 and "use strict" this won't be the global object ...
According to the bit of ES5 that Rob quoted, this is trivial to do in
ES5 with global.eval. And again, why not just use the Function
constructor?
>
> // compatible ES5 and "use strict"
Is this meant to run in the global context?
> var isGlobal = function (what) {
> function $isGlobal(what) {
Please don't use "$" as a function name prefix.
> return what in context;
> }
> var
> script = document.createElement("script"),
> context = document.documentElement
> ;
> script.text = "this.$isGlobal=this;";
As I know we've discussed (remember Randy Webb?) this is not cross-
browser code.
> context.insertBefore(script, context.firstChild);
Never insert scripts outside of the head or body. Why would you
attempt to manipulate the DOM in such a non-standard way. Again, not
cross-browser compatible.
> context.removeChild(script);
> script = null;
That line is a waste of time.
> context = $isGlobal;
A function declared locally above.
> delete context.$isGlobal;
So, at this point your $isGlobal function has a property called
$isGlobal and you want to delete it? I don't see it, nor do I see
where this is supposed to be going.
> context.isGlobal = (isGlobal = $isGlobal);
> return isGlobal(what);
I'm literally speechless. :(
>
> };
>
Do not use this code under any circumstances.
We covered that one, Jorge.
>
> > 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.
>
> var indirectEval= window.eval;
> indirectEval();
Why do you insist on using that host object in lieu of the Global
Object?
>
> > 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.
>
> Why not:
>
> "k" in window
> --> false
> var k;
> --> undefined
> "k" in window
> --> true
>
You know full well why not. :(
Or do you? At the very least, you've been told a thousand times.
There's no standard that says the window object *is* the Global
Object. You are simply making bad inferences (from observations of a
necessarily limited set of user agents).
The window object may mirror global properties and setting its
properties may set properties on the Global Object. It may appear in
every way (that you've had time to test) to be the Global Object, but
there is no way to know for sure what is going on behind the scenes
with that host object and not a shred of specification anywhere that
says it must behave as you assume.
You document that the one argument is required and must be a (non-
empty) string. End of story.
Glad we got that cleared up. However...
text-decoration:line-through;
--
Jorge.
Can't help but wonder why this group isn't more popular. (?) Nothing
subterranean going on here. :)
Adios, El Abuelo.
"In addition, for some languages, such as ECMAScript [ECMAScript], the
Window interface is implemented by the object that provides the global
namespace for script execution"
Grrr: http://www.w3.org/TR/Window/#introduction
--
Jorge.
How many times do we have to go over this? For one, that's obviously
not the language specification you have cited. That's an offhand
reference to a non-normative part of the language specs. In other
words, it's worthless, except to confuse people who don't know any
better. Are you among those people or simply trying to notch some
sort of hollow "victory" here?
I expected better from you, El Abuelo. Every time I give you the
slightest shred of credit, you make me regret it.
Are you leaving ?
--
Jorge.
Soon enough; but age before beauty... :)
I mean, haven't you done enough here?
We don't have to agree, Mark, so don't worry.
I saw the "This section is not normative." in bold in there. But,
there's so many that aren't normative -yet- in the browsers...
http://google.com/search?q="This+section+is+not+normative"site=w3.org
--> About 416 results
Say, e.g. the timers, the navigator object, the XHRs... don't you use
them ? Well, you shouldn't: they're not in any standard! (maybe
they've been finally standardized recently (?)).
--
Jorge.
Worry about what?
>
> I saw the "This section is not normative." in bold in there. But,
> there's so many that aren't normative -yet- in the browsers...
The section it refers to in the *language specification* is not
normative either.
>
> http://google.com/search?q="This+section+is+not+normative"site=w3.org
> --> About 416 results
And?
>
> Say, e.g. the timers, the navigator object, the XHRs... don't you use
> them ?
For one, you are looking at the wrong specifications as we are
discussing language features. For two, there is no standard DOM
specification for the window object anyway.
> Well, you shouldn't: they're not in any standard! (maybe
> they've been finally standardized recently (?)).
You don't get it. Don't use something that has no formal
specification if there is a standard alternative. And certainly don't
make assumptions about host objects when you don't have to. ;)
Since when is the Global Object a host object? :-)
--
Jorge.
The Global Object is a language feature, the 'window' symbol is not.
--
Jorge.
Yes, exactly. And you brought it into the discussion where it had no
place. ;)
Since never, Jorge. Are you trying to be funny?
Isn't the biggest problem with this (and any eval-like solution) that
it isn't without side effects?
What if the variable you are checking contains executable code?
var foo = 'alert("foo")';
doesGlobalVarExist(foo); // alerts foo;
And if the only goal here is to test if a variable has a value, then
typeof is the proper way to go as both null and undefined will eval
just fine and result in true being returned from the above function.
The w3 site is the right place to show you where to read that the
'window' symbol (not a language feature) that you believe to be a host
object (it's the object that implements the Window interface) is in
fact ("for some languages, such as ECMAScript") the Global Object
("the object that provides the global namespace for script
execution"), which is not a host object -but you seem to believe it
is-.
Now, next, come and tell me that it is in IEs, so that I can ROTFLOL.
--
Jorge.
True.
> And if the only goal here is to test if a variable has a value, then
> typeof is the proper way to go (...)
ISTM that typeof does not reveal "has a value" properly because a var
that exists might hold the value undefined, and typeof would return
undefined too for a var that does not exist. As the topic of this
thread is "does global variable exist", I'd say that typeof is not the
proper solution.
--
Jorge.
In that case the only option is
if ((new Function('return "nameOfVar" in this;'))()) {
// nameOfVar exists in the global scope
}
You are going in circles Jorge. As I mentioned (right above) the
window object had no place in the discussion in the first place.
> that you believe to be a host
> object (it's the object that implements the Window interface)
Of course it is a host object. It's sure as hell not a language
feature (as you yourself just noted).
> is in
> fact ("for some languages, such as ECMAScript") the Global Object
> ("the object that provides the global namespace for script
> execution"), which is not a host object -but you seem to believe it
> is-.
Again, round and round in circles. We just had this discussion.
Again, you are quoting from something that is far removed from being a
standard (and that is certainly not part of the language
specification).
>
> Now, next, come and tell me that it is in IEs, so that I can ROTFLOL.
I'll tell you no such thing. Nobody could say definitively what it is
in IE, except the IE developers. Thing is, you shouldn't need to
wonder about it.
Get better Jorge!
I already wrote about the typo, the concept is clear.
Tell e which browser does not support that insertBefore, thanks.
script = null is pointless but specially with DOM nodes and IE around
I always prefer to nullify pointers and since it does not hurt,
pointless comment from your side.
new Function is pointless as well, new before Function is a
misconception of the Function itself
the Function suggestion is bad in any case, and the eval ...
(new Function("p", "return eval(p)"))("p")
// "p", FAIL!
var arguments = 123;
(new Function("p", "return eval(p)"))("arguments");
// [object Arguments], FAIL!
You are always blind man, you rush too much with your bossy blaming
and you keep doing mistakes ( who doesn't, but no reason to pick over
everything and obvious things, this does not make you a better
developer ... just annoying one that keeps doing mistakes ... )
Once again:
// compatible ES5 and "use strict"
var isGlobal = function (what) {
function $isGlobal(what) {
return what in context;
}
var
script = document.createElement("script"),
context = document.documentElement
;
script.text = "this._isGlobal=this;";
context.insertBefore(script, context.firstChild);
context.removeChild(script);
script = null; // comment out if it hurts ...
context = _isGlobal;
delete context._isGlobal;
context.isGlobal = (isGlobal = $isGlobal);
return isGlobal(what);
};
Regards,
Andrea Giammarchi
And Andrea Giammarchi still doesn't know how to quote on Usenet, so
his posts have no context at all.
And no, in all of the years you have been posting here, due to your
quoting problems and a palpable language barrier (prose and code),
I've never "gotten" a single thing from you.
>
> I already wrote about the typo, the concept is clear.
Nobody ever knows what you are writing about. See above. And there's
nothing clear about your code.
>
> Tell e which browser does not support that insertBefore, thanks.
Show you where it fails? Can you see every browser, every rendering
and parse mode, past, present and future? Assuming no, why would you
do something so obviously hinged on your observations when there are
any number of reasonable alternatives that are based on the standards
referenced by browser developers?
>
> script = null is pointless but specially with DOM nodes and IE around
> I always prefer to nullify pointers and since it does not hurt,
> pointless comment from your side.
It simply wastes space and obscures your intentions. For all I knew,
you pasted that in at random.
>
> new Function is pointless as well, new before Function is a
> misconception of the Function itself
What are you talking about? I find myself saying that a lot when
"discussing" browser scripting with you.
>
> the Function suggestion is bad in any case, and the eval ...
I didn't suggest anything to do with eval. Quite the contrary, I said
not to use it at all.
>
> (new Function("p", "return eval(p)"))("p")
> // "p", FAIL!
Not only did I point that out previously, but I gave the solution.
>
> var arguments = 123;
> (new Function("p", "return eval(p)"))("arguments");
> // [object Arguments], FAIL!
I didn't write anything like that (and certainly never would). And
please stop shouting.
>
> You are always blind man, you rush too much with your bossy blaming
> and you keep doing mistakes ( who doesn't, but no reason to pick over
> everything and obvious things, this does not make you a better
> developer ... just annoying one that keeps doing mistakes ... )
You are beyond belief. You write bad code followed by "FAIL!" and
then call me a blind man. What does any of this mean? And again, I
often find myself asking you such questions.
>
> Once again:
>
[snip junk code]
No thanks!
As there seems to be some confusion down the line, I should point out
that this question is not asking for a script injection solution
(which I'm sure we both know is the only way to run code in the global
context), but a way to use eval (or its alias the Function
constructor) in a nested local scope without pollution from the
containing scope.
As a (bogus) script injection solution has been introduced in
response, I recommend looking at the feature testing bit of the
addScript function in My Library as it could be modified to solve this
(purely academic) problem. In fact, the injected "solution"
introduced looks suspiciously like a broken imitation of it (or of
some of Randy Webb's old work).
As Pointy would put it: Non sequitur.
The Window interface is implemented on the Global Object, not on a
host object. HTH.
--
Jorge.
Nice.
function doesGlobalVarExist (varName) {
return Function('return "'+ varName+ '" in this')();
}
--
Jorge.
> 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?
Others have pointed out a lot of shortcommings.
Generally, you have a problem with function parameters shadowing what
you can see through the scope chain (e.g. try checking if "arguments"
is a property of the global object?)
To avoid that, don't use eval (the non-direct call to eval isn't
in all browsers yet, and eval has side effects). Ok, generally,
don't use eval. Using eval is a sign that you are doing something
wrong[1].
Passing the name of a variable around as a string is also a sign that
you are doing something wrong - you are working at two different levels
at the same time.
In any case, just check for the property on the global object:
function doesGlobalVarExist(v) {
var global = function(){return this;}();
return v in global;
}
(It probablt doesn't work safe in strict mode ES5)
/L
--
Lasse Reichstein Holst Nielsen
'Javascript frameworks is a disruptive technology'
<snip>
>
> In any case, just check for the property on the global object:
>
> function doesGlobalVarExist(v) {
> var global = function(){return this;}();
> return v in global;
> }
>
> (It probablt doesn't work safe in strict mode ES5)
>
Yes, it doesn't work in strict mode ES5, and not probably but exactly
(because `global' is `undefined' in this case ). You can read "Strict
Mode" article mentioned by me in this thread earlier if you want. There
all these cases are discussed.
And only indirect `eval' call may help to get global `this' value.
Dmitry.
I really don't understand the worries about ES5 strict mode. Even
when ES5 is widely implemented, strict mode will be completely
optional. That being said, in production code, this is the best
solution (and will work in anything new enough to support the - in -
operator, which is virtually everything in use today):-
var global = this;
(function() {
function isGlobal(s) {
return s in global;
}
// App goes here
})();
Everything else discussed in this thread was academic (and some of it
really awful).
function doesGlobalVarExist (v) {
return v in function(){return this}() }
--
Jorge.
Yeah, I think so. Moreover, as I mentioned, many programmers will
understand "strict mode" features incorrectly (I've heard even phrases
such as "we are not "children", but professionals, so use strict mode
only" -- not regarding ES, but in general -- HTML doctype, Perl, etc.).
Thus, presence of this feature is not related with the professionalism
in any respect. Using strict mode because it makes code more
professional -- is for laymen debates. And separating a language on
"strict" and "non-strict" will force those laymen make useless holywars.
Also, if to look on strict mode from the other side, it's about
inattentive, but not professional programmer -- a helper which warnings
such inattentive programmer if he uses e.g. `arguments' as a formal
parameter's name.
However, for "graceful degradation" -- for example, if the language
wants to remove some obsolete garbage, it's a good feature -- to mark
those deprecated stuff in strict mode (e.g. `with' statement, which
possible will be removed from newer versions; although, for me there
have never been problems with `with', but I used it rarely).
So from this position, `strict mode' is good. And possible someone (and
I think now someone, but about 90% of future ES programmers) will use
strict mode on the program level. And since the strictness inherits it
from the parent context, simple FD, FE will also be always strict. And
therefore, `function () {return this;}' will return `undefined'.
And a `Function' function may help to solve this issue -- since such
functions do not inherit strictness (it's needed to write "use strict"
directly in the body of the `Function' function).
> That being said, in production code, this is the best
> solution (and will work in anything new enough to support the - in -
> operator, which is virtually everything in use today):-
>
> var global = this;
>
> (function() {
>
> function isGlobal(s) {
> return s in global;
> }
>
> // App goes here
>
> })();
>
Yeah, agreed, that most of the discussed stuff is less about practical
cases. On practice, simple `var global = this;' or with `defineProperty'
is enough. Talks about shadowing etc. -- just theoretical things, which
can be interesting, but on practice we hardly will do this (I'm not
stupid to shadow `global' variable which I specially defined to get
global object with the local one `var global = 10' Who will do this?
Don't know.).
> Everything else discussed in this thread was academic (and some of it
> really awful).
Academical theoretic discussions are also may be interesting (I am e.g.
ECMAScript theorist, besides my practical work, which currently isn't
even massively related with JS (but was many years of course) -- I
program on Erlang now and small part on JS). Knowing this stuff allows
to quickly answer practical questions/issues which many only-practical
programmers like to name "WTF(JS)?".
Dmitry.
Most PERL programs would burn up under the strict microscope. CPAN is
the Dynamic Drive of the PERL world. As for doctypes, strict makes
sense unless you are actually transitioning from one type of markup to
another.
What is laughable is that for years the majority of new sites have
used the transitional XHTML doctype.
Why? Because the developers were sure they were supposed to be using
the "more advanced" (but dead) language, but didn't really understand
why. They likely aspired to validate their creations at some point,
but found strict validation too difficult, so settled for a
"transitional" period (that has lasted a decade for some). And, of
course, faced with the fact that IE did not support XHTML for the
first decade of the century, served it with an HTML MIME type, causing
browsers to error correct it back to HTML.
Or maybe the majority are simply propagating examples from the turn of
the century via their clipboards. :)
> Thus, presence of this feature is not related with the professionalism
> in any respect.
Certainly not. In fact, putting "use strict" at the top of s script
today implies the opposite. Same for using an HTML5 doctype. Rookies
always strive to use the "coolest" new technologies, even before their
end-users are ready for them.
> Using strict mode because it makes code more
> professional -- is for laymen debates.
Use JSLint, but know enough to interpret the results. End of story.
Great for catching typos too.
> And separating a language on
> "strict" and "non-strict" will force those laymen make useless holywars.
When it comes to JS, the average developer is so completely lost that
they won't likely look for ways to make browser scripting "harder".
Hell, most of the "major" libraries can't even get through JSLint, let
alone achieve respectable results.
> Also, if to look on strict mode from the other side, it's about
> inattentive, but not professional programmer -- a helper which warnings
> such inattentive programmer if he uses e.g. `arguments' as a formal
> parameter's name.
LOL. JSLint (or the like) would flag such nonsense. Of course, if a
developer is really that out of it, they've got bigger problems.
>
> However, for "graceful degradation" -- for example, if the language
> wants to remove some obsolete garbage, it's a good feature -- to mark
> those deprecated stuff in strict mode (e.g. `with' statement, which
> possible will be removed from newer versions; although, for me there
> have never been problems with `with', but I used it rarely).
JSLint will almost certainly flag that too. Personally, in almost
fifteen years, I've never used a - with - clause.
>
> So from this position, `strict mode' is good. And possible someone (and
> I think now someone, but about 90% of future ES programmers) will use
> strict mode on the program level.
Not sure how you arrived at that figure, but I definitely disagree.
More like 10%.
> And since the strictness inherits it
> from the parent context, simple FD, FE will also be always strict. And
> therefore, `function () {return this;}' will return `undefined'.
So don't use it (in any context). ES5 is not yet widely implemented
anyway.
>
> And a `Function' function may help to solve this issue -- since such
> functions do not inherit strictness (it's needed to write "use strict"
> directly in the body of the `Function' function).
A function created by calling the Function constructor? That's
usually avoided as bad form. In terms of style, it's no better than
eval.
>
>
>
> > That being said, in production code, this is the best
> > solution (and will work in anything new enough to support the - in -
> > operator, which is virtually everything in use today):-
>
> > var global = this;
>
> > (function() {
>
> > function isGlobal(s) {
> > return s in global;
> > }
>
> > // App goes here
>
> > })();
>
> Yeah, agreed, that most of the discussed stuff is less about practical
> cases.
Yes, and some of it is downright dangerous.
> On practice, simple `var global = this;' or with `defineProperty'
> is enough.
Yes.
> Talks about shadowing etc. -- just theoretical things, which
> can be interesting, but on practice we hardly will do this (I'm not
> stupid to shadow `global' variable which I specially defined to get
> global object with the local one `var global = 10' Who will do this?
> Don't know.).
Right. But there will always be those who waste time seeking the Holy
Grail solution to every problem, when in context a dixie cup would
suffice.
>
> > Everything else discussed in this thread was academic (and some of it
> > really awful).
>
> Academical theoretic discussions are also may be interesting (I am e.g.
> ECMAScript theorist, besides my practical work, which currently isn't
> even massively related with JS (but was many years of course) -- I
> program on Erlang now and small part on JS). Knowing this stuff allows
> to quickly answer practical questions/issues which many only-practical
> programmers like to name "WTF(JS)?".
>
That's a familiar refrain (or at least demeanor). The sad truth is
that most people involved with or on the periphery of JS see it as a
vexing mystery. I suppose that programmers that are proficient with
"real" languages like Java, C++ or whatever, feel learning a "toy"
language like JS will be an easy career boost. Once they falter in
the most marketable application of JS (browser scripting), they start
to curse it as "broken" and look for libraries to bridge the gap (as
would be natural in other languages).
What they don't realize is that the authors of most libraries are
almost as confused as they are. They see how much trouble the library
authors are having, year-in and year-out and it makes them feel
better. At this point, the whole culture is based on programming for
failure and the language is an easy (but perfectly innocent)
scapegoat.
Some of them end up here and when told that they are confused, they
are very quick to rush back to the soothing tones of blogs and Web
forums populated by people suffering from the same mass hysteria.
Others actually learn and go straight to the top of the food chain. ;)
> I really don't understand the worries about ES5 strict mode. Even
> when ES5 is widely implemented, strict mode will be completely
> optional. That being said, in production code, this is the best
> solution (and will work in anything new enough to support the - in -
> operator, which is virtually everything in use today):-
>
> var global = this;
>
> (function() {
>
> function isGlobal(s) {
> return s in global;
> }
>
> // App goes here
>
> })();
It's enough, but I would prefer:
(function (global /* = this */) {
// App goes here
})(this);
Regarding strict mode, I assume in the near future that will be the
new marketing trick of the most popular js libs. There will be:
"JQuery is compatible with ECMAScript 5 strict mode"
The strict mode is only helpful during development stage and for
beginner developers. The beginners can use these features for creating
good habits as JS developer. For people in this group I don't think
strict mode is something helpful. For example I use
`javascript.options.strict;true` in Firefox and in error console I get
warnings and errors for many thinks. e.g. undeclared
assignments.
That's amusing, coming from someone who apparently isn't even familiar
enough with Perl to know how it's spelled. Are you aware that ES5's "use
strict" pragma was directly inspired by Perl? And that almost all of the
modules on CPAN are running in strict mode? I don't know why you felt it
necessary to compare CPAN to a collection of amateur scripts like
Dynamic Drive. If you had bothered to take a closer look, you could have
discovered a review process, an official procedure for testing, a
dependency resolver, a bug tracker, namespace management, versioning,
format and naming conventions, tracking of module maintainers,
documentation, mailing lists, IRC channels, a usenet gateway, 100+
mirror sites, etc. Judging from your uninformed statement, I don't think
you've ever worked with CPAN before.
Yes, I'm overprotective about Perl :)
--
stefan
I think there's a support group...
:-)
--
Scott
That's how I "spell" it. Or at least how I spelled it in that
message. :)
And I am quite familiar with Perl and the general quality of freebie
Perl scripts found on the Web (particularly CPAN).
> Are you aware that ES5's "use
> strict" pragma was directly inspired by Perl?
How is that relevant?
> And that almost all of the
> modules on CPAN are running in strict mode?
Are they? Could I possibly have had the wrong site in mind (it's been
a few years). Regardless, strict mode does not good software
make. ;)
> I don't know why you felt it
> necessary to compare CPAN to a collection of amateur scripts like
> Dynamic Drive.
Because it is. I've had to work on lots of Perl applications that use
CPAN modules. Many of them were horrible (the apps and the modules).
> If you had bothered to take a closer look, you could have
> discovered a review process, an official procedure for testing, a
> dependency resolver, a bug tracker, namespace management, versioning,
> format and naming conventions, tracking of module maintainers,
> documentation, mailing lists, IRC channels, a usenet gateway, 100+
> mirror sites, etc.
I was referring only to the quality of the code contained therein (and
obviously not *all* of it). You can wrap up bad code in pretty bows,
but it's still bad code. Could be that the majority of it is better
than I remember, but not the bits I had to deal with. I'm
particularly reminded of several HTTP related scripts (and especially
an AIM interface).
> Judging from your uninformed statement, I don't think
> you've ever worked with CPAN before.
Obviously that's a false assumption.
>
> Yes, I'm overprotective about Perl :)
>
Overprotective of PERL or the specific scripts on CPAN?
Because Dmitry was talking about "strict mode" in ES5, and you replied
with your "strict microscope" quip, quoted above.
>> And that almost all of the
>> modules on CPAN are running in strict mode?
>
> Are they? Could I possibly have had the wrong site in mind (it's been
> a few years). Regardless, strict mode does not good software
> make. ;)
Agreed. I will also gladly admit that there are a few bad apples in the
CPAN basket, but going by Sturgeon's Law ("ninety percent of everything
is crud"), I think CPAN is doing pretty well.
>> I don't know why you felt it
>> necessary to compare CPAN to a collection of amateur scripts like
>> Dynamic Drive.
>
> Because it is. I've had to work on lots of Perl applications that use
> CPAN modules. Many of them were horrible (the apps and the modules).
From what I've read, any software at all appears horrible to you (with
the possible exception of My Library). Has anybody else ever written
code that meets your approval?
>> Judging from your uninformed statement, I don't think
>> you've ever worked with CPAN before.
>
> Obviously that's a false assumption.
Possibly. I retract that.
>> Yes, I'm overprotective about Perl :)
>
> Overprotective of PERL or the specific scripts on CPAN?
Perl and CPAN as a whole. Individual modules may be out of date, or even
flat out ugly, but there's still a world of difference between CPAN and
a script kiddy site like Dynamic Drive.
--
stefan
Okay.
>
> >> And that almost all of the
> >> modules on CPAN are running in strict mode?
>
> > Are they? Could I possibly have had the wrong site in mind (it's been
> > a few years). Regardless, strict mode does not good software
> > make. ;)
>
> Agreed. I will also gladly admit that there are a few bad apples in the
> CPAN basket, but going by Sturgeon's Law ("ninety percent of everything
> is crud"), I think CPAN is doing pretty well.
Yeah, don't get me wrong. The general quality of Perl scripts is far
higher than JS. So, CPAN is certainly a much better repository than
Dynamic Drive (if you can even call that site a repository). I was
just noting a parallel.
>
> >> I don't know why you felt it
> >> necessary to compare CPAN to a collection of amateur scripts like
> >> Dynamic Drive.
>
> > Because it is. I've had to work on lots of Perl applications that use
> > CPAN modules. Many of them were horrible (the apps and the modules).
>
> From what I've read, any software at all appears horrible to you (with
> the possible exception of My Library).
Now that's a gross exaggeration. When have I written about anything
but freebie JS scripts? I think it goes without saying that virtually
of those are horrible (and I am hardly alone in that assessment).
> Has anybody else ever written
> code that meets your approval?
Of course.
>
> >> Judging from your uninformed statement, I don't think
> >> you've ever worked with CPAN before.
>
> > Obviously that's a false assumption.
>
> Possibly. I retract that.
Fair enough. But change possibly to definitely.
>
> >> Yes, I'm overprotective about Perl :)
>
> > Overprotective of PERL or the specific scripts on CPAN?
>
> Perl and CPAN as a whole. Individual modules may be out of date, or even
> flat out ugly, but there's still a world of difference between CPAN and
> a script kiddy site like Dynamic Drive.
>
Yes, they are similar in one way, but certainly not identical (or even
on the same playing field).
I'm pretty sure ES5 strict mode is not only useful during development
stage, but can also make code run faster.
Eliminating `with` statement (which, AFAIK, is a terrible performance
hit in newer JS engines, preventing certain optimizations), making
`arguments` non-writable (again, more optimizations can be made), making
`arguments`' array indexed properties non-bound to formal parameters,
preventing `eval` from instantiating variables in containing scope, etc.
--
kangax