Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   Javascript (http://www.velocityreviews.com/forums/f68-javascript.html)
-   -   get the global object in any environment (http://www.velocityreviews.com/forums/t940506-get-the-global-object-in-any-environment.html)

Stoyan 02-21-2010 02:37 AM

get the global object in any environment
 
Hi group,

Since JS is everywhere (client, server, desktop...), it makes sense to
think how to write code that could run in environments other than the
one originally in mind. Perhaps it's not a good idea to use `window`
when the code could possibly run in environment that has no idea what
`window` is.

so this pattern came to mind:
var global = function(){return this;}();
However this apparently won't work in ES5 strict which aims to prevent
errors from calling constructors without `new`

Another hacky idea is to call a function that assumes global when
`this` is unusable. Andrea Giammarchi came up with the shortest form
(http://twitter.com/WebReflection/status/9406207674)
var global = [].sort.call(null);

The question is - is that ES5 strict-safe? Or any other ideas how to
get access to the global without hardcoding its name?

Of course alternatively the new environment could simply define window
and problem is solved. E.g. if in some environment the global object
is called `foo`, then just do a global var window = foo; and call it a
day :)

Thoughts?

Thanks,
Stoyan


Thomas 'PointedEars' Lahn 02-21-2010 03:13 AM

Re: get the global object in any environment
 
Stoyan wrote:

> Since JS is everywhere (client, server, desktop...), it makes sense to
> think how to write code that could run in environments other than the
> one originally in mind. Perhaps it's not a good idea to use `window`
> when the code could possibly run in environment that has no idea what
> `window` is.


Sigh. [psf 10.1] It has *never* been a good idea to use a proprietary,
host-defined property, that is supposed to refer to a host object to access
a different, standardized, native object. But some people just would not
listen.

> so this pattern came to mind:
> var global = function(){return this;}();
> However this apparently won't work in ES5 strict which aims to prevent
> errors from calling constructors without `new`


Have you seen a single conforming implementation of ES5, in particular have
you seen a widely distributed one that supports strict mode yet? If yes,
which one? If no, why bother now? (JFYI: It took almost 10 years for ES3F
to be widely implemented. Why do you expect ES5 to be any faster?)

Besides, I doubt this has anything to do with constructors.

> Another hacky idea is to call a function that assumes global when
> `this` is unusable. Andrea Giammarchi came up with the shortest form
> (http://twitter.com/WebReflection/status/9406207674)
> var global = [].sort.call(null);


Very efficient; very compatible, too. NOT.

> The question is - is that ES5 strict-safe?


Read the Specification for yourself (for a change). Ask smart questions
here if anything you read is still unclear.

> Or any other ideas how to get access to the global without hardcoding
> its name?


What exactly do you mean by "the global"?

> Of course alternatively the new environment could simply define window
> and problem is solved.


What hypothetical new environment are you talking about? Why should any
non-browser environment implement a property that only makes sense in a
browser environment?

> E.g. if in some environment the global object is called `foo`,


Objects do not have names, they have an identity each.

> then just do a global var window = foo; and call it a day :)
>
> Thoughts?


var _global = this;

in the global execution context.

(In my JSX since quite a few years. Newer versions introduced `jsx.global'
as in-library reference -- locally aliased to jsx_global where reasonable
-- to avoid possible incompatibilities with other libraries.)

Do you realize that this is recommended literally on the first page of the
Core JavaScript 1.5 Reference?


PointedEars
--
var bugRiddenCrashPronePieceOfJunk = (
navigator.userAgent.indexOf('MSIE 5') != -1
&& navigator.userAgent.indexOf('Mac') != -1
) // Plone, register_function.js:16

Stoyan 02-21-2010 04:00 AM

Re: get the global object in any environment
 
Thanks Thomas!

> Have you seen a single conforming implementation of ES5, in particular have
> you seen a widely distributed one that supports strict mode yet? *If yes,
> which one? *If no, why bother now? *(JFYI: It took almost 10 years for ES3F
> to be widely implemented. *Why do you expect ES5 to be any faster?)


Good point. But we can hope :)

> > Another hacky idea is to call a function that assumes global when
> > `this` is unusable. Andrea Giammarchi came up with the shortest form
> > (http://twitter.com/WebReflection/status/9406207674)
> > var global = [].sort.call(null);

>
> Very efficient; very compatible, too. *NOT.


You're right. Not Andrea's fault, he just make my clumsy version much
shorter.
What I had was worse:
var global = function(){var x;return(x=[].sort)()}();


> Read the Specification for yourself (for a change). *Ask smart questions
> here if anything you read is still unclear.


Thanks, I'll ask :)

>
> > Or any other ideas how to get access to the global without hardcoding
> > its name?

>
> What exactly do you mean by "the global"?
>


I meant "the global object"

> > Of course alternatively the new environment could simply define window
> > and problem is solved.

>
> What hypothetical new environment are you talking about? *Why should any
> non-browser environment implement a property that only makes sense in a
> browser environment?
>



What I had in mind was - say you're building a library and it's so
useful it makes sense to use the same library in other environments,
not only the browser. For example you can do server-side scripts or
write photoshop scripts. The photoshop environment for example doesn't
have `window`, but it does have a global `app`.

In such cases when you use a library which uses `window` to refer to
the global object, you can probably do
var window = this;
and the library should work


> > Thoughts?

>
> * var _global = this;
>
> in the global execution context.
>


I was thinking about when not in the global context? Say your library
has a function and inside that function you want check the global
namespace for something. Probably to far-fetched case, I don't know.

I guess a good approach for a library is to store a global reference
for future internal use, just like you suggested.

var MyLib = function() {
// my whole lib is here,
// no other global vars leaked

return {
someMethod: function() {
var g = MyLib._global;
//...
}
};
}();
MyLib._global = this;

This way someMethod() doesn't need to figure out access to the global
object on its own.


Thanks again for your reply!

Stoyan

> (In my JSX since quite a few years. *Newer versions introduced `jsx.global'
> as in-library reference -- locally aliased to jsx_global where reasonable
> -- to avoid possible incompatibilities with other libraries.)
>
> Do you realize that this is recommended literally on the first page of the
> Core JavaScript 1.5 Reference?
>
> PointedEars
> --
> var bugRiddenCrashPronePieceOfJunk = (
> * * navigator.userAgent.indexOf('MSIE 5') != -1
> * * && navigator.userAgent.indexOf('Mac') != -1
> ) *// Plone, register_function.js:16



David Mark 02-21-2010 04:09 AM

Re: get the global object in any environment
 
Stoyan wrote:
> Hi group,
>
> Since JS is everywhere (client, server, desktop...), it makes sense to
> think how to write code that could run in environments other than the
> one originally in mind.


Indeed.

> Perhaps it's not a good idea to use `window`
> when the code could possibly run in environment that has no idea what
> `window` is.


Definitely a bad idea.

>
> so this pattern came to mind:
> var global = function(){return this;}();
> However this apparently won't work in ES5 strict which aims to prevent
> errors from calling constructors without `new`


Right.

>
> Another hacky idea is to call a function that assumes global when
> `this` is unusable. Andrea Giammarchi came up with the shortest form
> (http://twitter.com/WebReflection/status/9406207674)
> var global = [].sort.call(null);


Hack-y is right.

>
> The question is - is that ES5 strict-safe? Or any other ideas how to
> get access to the global without hardcoding its name?


I imagine it is not going to foul up ES5 strict mode.

>
> Of course alternatively the new environment could simply define window
> and problem is solved.


It isn't up to a random environment to solve issues specific to your
script. ;)

> E.g. if in some environment the global object
> is called `foo`, then just do a global var window = foo; and call it a
> day :)


No need to do anything like that (and it would certainly cause issues in
_browsers_). And what makes you think there will even be a global
property (e.g. foo) that references the Global Object? That's what the
- this - identifier is for (in the global context).

>
> Thoughts?


Why not just do this in the global context:-

var global = this;

....and call it a day. :)

That's what I did in My Library, which has no unqualified - window -
references. Come to think of it, it has no such _qualified_ references
either, which I don't consider ideal. So as not to assume that the
Global Object is the window object (despite the fact that it has been
observed to be in many browsers), ideally some of those references
should have been written:-

(global.window || global)

The determining factor is whether they are used to qualify references to
properties that are known to be specific to the window object in
browsers (e.g. the alert method).

Of course, this is another case where the declaration of a global -
window - variable could cause problems (e.g. if it did not reference the
Global Object). Trying to make other environments look like browsers is
just as bad an idea as trying to make IE look like a quasi-standard
browser (as seen in at least one misguided library).

Such environmental differences can be important, depending on context,
so should not be arbitrarily spackled over. See also jQuery's
height/width methods, which on gets seek to make every element look like
it uses the one box model its developers consider to be "correct". They
didn't bother to mirror these contortions for set operations, so
basically they return dimensions that are of no practical use unless the
element's box model happens to be the "correct" one.

Thomas 'PointedEars' Lahn 02-21-2010 04:27 AM

Re: get the global object in any environment
 
Stoyan wrote:

> Thanks Thomas!


Thank you for keeping proper attribution next time.

> [Thomas 'PointedEars' Lahn wrote:]
>> [Stoyan wrote:]
>> > Or any other ideas how to get access to the global without hardcoding
>> > its name?

>> What exactly do you mean by "the global"?

>
> I meant "the global object"


Then, as I said, objects do not have names.

>> > Of course alternatively the new environment could simply define window
>> > and problem is solved.

> What hypothetical new environment are you talking about? Why should any
>> non-browser environment implement a property that only makes sense in a
>> browser environment?

>
> What I had in mind was - say you're building a library and it's so
> useful it makes sense to use the same library in other environments,
> not only the browser. For example you can do server-side scripts or
> write photoshop scripts. The photoshop environment for example doesn't
> have `window`, but it does have a global `app`.
>
> In such cases when you use a library which uses `window` to refer to
> the global object, you can probably do
> var window = this;
> and the library should work


You are still having the misconception that anything other than `this' in
the global execution context is supposed to refer to the ECMAScript Global
Object.

>> > Thoughts?

>>
>> var _global = this;
>>
>> in the global execution context.

>
> I was thinking about when not in the global context?


Then you use the global variable or any other property that stores the
appropriate value. Preferably you would assign the value to a local
variable if you used it repeatedly, to keep the effective scope chain
short.

> Say your library has a function and inside that function you want check
> the global namespace for something. Probably to far-fetched case, I
> don't know.


Not at all, I am doing this already, for example in my URI-escape wrapper
in string.js.

> I guess a good approach for a library is to store a global reference
> for future internal use, just like you suggested.
>
> var MyLib = function() {
> // my whole lib is here,
> // no other global vars leaked


What you state in the comment is not entirely true; if MyLib is global, any
code can access MyLib._global. However, you could it make so, of course:

var MyLib = (function(global) {
/* global */
})(this);

> return {
> someMethod: function() {
> var g = MyLib._global;
> //...
> }
> };
> }();
> MyLib._global = this;


Or something less ugly. The namespacing approach is heavily overrated
(and over-used) to begin with.

> This way someMethod() doesn't need to figure out access to the global
> object on its own.


It does not really matter how you access that object value, only that it is
available in the relevant execution contexts.

> Thanks again for your reply!
> [snip]


You are welcome. Thank you in advance for quoting properly next time.

<http://jibbering.com/faq/#posting>


PointedEars
--
Anyone who slaps a 'this page is best viewed with Browser X' label on
a Web page appears to be yearning for the bad old days, before the Web,
when you had very little chance of reading a document written on another
computer, another word processor, or another network. -- Tim Berners-Lee

Thomas 'PointedEars' Lahn 02-21-2010 04:29 AM

Re: get the global object in any environment
 
David Mark wrote:

> Why not just do this in the global context:-
>
> var global = this;
>
> ...and call it a day. :)
>
> That's what I did in My Library, which has no unqualified - window -
> references. Come to think of it, it has no such _qualified_ references
> either, which I don't consider ideal. So as not to assume that the
> Global Object is the window object (despite the fact that it has been
> observed to be in many browsers), ideally some of those references
> should have been written:-
>
> (global.window || global)


Ouch.


PointedEars
--
Anyone who slaps a 'this page is best viewed with Browser X' label on
a Web page appears to be yearning for the bad old days, before the Web,
when you had very little chance of reading a document written on another
computer, another word processor, or another network. -- Tim Berners-Lee

David Mark 02-21-2010 04:32 AM

Re: get the global object in any environment
 
Thomas 'PointedEars' Lahn wrote:
> David Mark wrote:
>
>> Why not just do this in the global context:-
>>
>> var global = this;
>>
>> ...and call it a day. :)
>>
>> That's what I did in My Library, which has no unqualified - window -
>> references. Come to think of it, it has no such _qualified_ references
>> either, which I don't consider ideal. So as not to assume that the
>> Global Object is the window object (despite the fact that it has been
>> observed to be in many browsers), ideally some of those references
>> should have been written:-
>>
>> (global.window || global)

>
> Ouch.


And what do we consider to be painful about that? :) You snipped my
disclaimer.

(global.window || global).alert('Hello from any environment'); // see
previous disclaimer

If you simply use global.alert, you are assuming that - window - and the
Global Object are the same thing (and I know you don't promote that
assumption). So what's your line?

Thomas 'PointedEars' Lahn 02-21-2010 04:57 AM

Re: get the global object in any environment
 
David Mark wrote:

> Thomas 'PointedEars' Lahn wrote:
>> David Mark wrote:
>>> Why not just do this in the global context:-
>>>
>>> var global = this;
>>>
>>> ...and call it a day. :)
>>>
>>> That's what I did in My Library, which has no unqualified - window -
>>> references. Come to think of it, it has no such _qualified_ references
>>> either, which I don't consider ideal. So as not to assume that the
>>> Global Object is the window object (despite the fact that it has been
>>> observed to be in many browsers), ideally some of those references
>>> should have been written:-
>>>
>>> (global.window || global)

>>
>> Ouch.

>
> And what do we consider to be painful about that? :) You snipped my
> disclaimer.


Your disclaimer is nonsense.

> (global.window || global).alert('Hello from any environment'); // see
> previous disclaimer


As is this.

> If you simply use global.alert, you are assuming that - window - and the
> Global Object are the same thing (and I know you don't promote that
> assumption).


Yes, you are, by this very construction.

> So what's your line?


Don't.


PointedEars
--
realism: HTML 4.01 Strict
evangelism: XHTML 1.0 Strict
madness: XHTML 1.1 as application/xhtml+xml
-- Bjoern Hoehrmann

David Mark 02-21-2010 05:13 AM

Re: get the global object in any environment
 
Thomas 'PointedEars' Lahn wrote:
> David Mark wrote:
>
>> Thomas 'PointedEars' Lahn wrote:
>>> David Mark wrote:
>>>> Why not just do this in the global context:-
>>>>
>>>> var global = this;
>>>>
>>>> ...and call it a day. :)
>>>>
>>>> That's what I did in My Library, which has no unqualified - window -
>>>> references. Come to think of it, it has no such _qualified_ references
>>>> either, which I don't consider ideal. So as not to assume that the
>>>> Global Object is the window object (despite the fact that it has been
>>>> observed to be in many browsers), ideally some of those references
>>>> should have been written:-
>>>>
>>>> (global.window || global)
>>> Ouch.

>> And what do we consider to be painful about that? :) You snipped my
>> disclaimer.

>
> Your disclaimer is nonsense.


Is it? ISTM that if you declare a global - window - variable, you are
going to screw it up. No?

>
>> (global.window || global).alert('Hello from any environment'); // see
>> previous disclaimer

>
> As is this.


I think not. A non-browser may well feature a global alert method, just
as some have been demonstrated to feature a global setTimeout method,
but no global window object.

>
>> If you simply use global.alert, you are assuming that - window - and the
>> Global Object are the same thing (and I know you don't promote that
>> assumption).

>
> Yes, you are, by this very construction.


I don't think you understood what I was demonstrating. If there is a
global window property (as in browsers), it will be used. If not, it
will use the reference to the Global Object. Obviously, feature
detection has been omitted from the example, but that doesn't seem to be
your beef.

>
>> So what's your line?

>
> Don't.
>


I meant your line of _code_ for calling alert (or setTimeout or
whatever) in an environment-agnostic fashion.

Thomas 'PointedEars' Lahn 02-21-2010 06:08 AM

Re: get the global object in any environment
 
David Mark wrote:

> Thomas 'PointedEars' Lahn wrote:
>> David Mark wrote:
>>> Thomas 'PointedEars' Lahn wrote:
>>>> David Mark wrote:
>>>>> Why not just do this in the global context:-
>>>>>
>>>>> var global = this;
>>>>>
>>>>> ...and call it a day. :)
>>>>>
>>>>> That's what I did in My Library, which has no unqualified - window -
>>>>> references. Come to think of it, it has no such _qualified_
>>>>> references
>>>>> either, which I don't consider ideal. So as not to assume that the
>>>>> Global Object is the window object (despite the fact that it has been
>>>>> observed to be in many browsers), ideally some of those references
>>>>> should have been written:-
>>>>>
>>>>> (global.window || global)
>>>> Ouch.
>>> And what do we consider to be painful about that? :) You snipped my
>>> disclaimer.

>>
>> Your disclaimer is nonsense.

>
> Is it? ISTM that if you declare a global - window - variable, you are
> going to screw it up. No?


AFAIR, nobody suggested doing that. (And yes, you are going to screw up in
the environments we know about. But this is about unknown environments, is
it not?)

>>> (global.window || global).alert('Hello from any environment'); // see
>>> previous disclaimer

>>
>> As is this.

>
> I think not. A non-browser may well feature a global alert method, just
> as some have been demonstrated to feature a global setTimeout method,
> but no global window object.


And if my grandmother had wheels, she'd be a motorcycle. See below.

>>> If you simply use global.alert, you are assuming that - window - and
>>> the Global Object are the same thing (and I know you don't promote that
>>> assumption).

>>
>> Yes, you are, by this very construction.

>
> I don't think you understood what I was demonstrating. If there is a
> global window property (as in browsers), it will be used. If not, it
> will use the reference to the Global Object. Obviously, feature
> detection has been omitted from the example, but that doesn't seem to be
> your beef.


Are you really asking what problems I have with this code? Well, I do not
quite know where to begin.

Missing feature detection is only one part of my criticism: A type-
converting test involving an unknown potential host object and you can find
nothing wrong with it? And have we not established by now that one does
not grow reference worms, particularly not with method calls unless we know
for sure that the MemberExpression left-hand side can evaluate to a fitting
object reference, and particularly not if the code is exposed to unknown
runtime environments?

The other part is, of course, your readily jumping to conclusions here.

First of all, you should rest assured you do not know *anything* about
unknown environments (else they would not be unknown, would they?), so all
your talk about "properties that are known to be specific to the window
object in browsers" does not make any sense in that context. It is really
apples and oranges. Whereas you have not even tried to address the
question which browsers you are actually talking about here. Keep in mind
that we are talking about a host object here, so it can have (and evidently
has) different properties in different browsers, including those that you
do not yet know.

Then, if you assume that the two expressions refer to different objects
instead of the same (else you would not need the OR operation in the first
place), where did the global object of the other environment suddenly get
the magic alert() method from?

And that aside, why would you even expect such a method to work the same as
the method defined for Window instances from a completely different runtime
environment to begin with -- because the property has the same name? What
does, for example, the implementor of an ECMAScript implementation for an
e-book reader need to care what your favorite Web browser implements, and
how it does that? Suppose, just suppose, it would work remotely the same
as in that Web browser (i.e. it displayed a message to the user, and would
not, e.g. log it to a file in the reader's filesystem -- or the book
server's? -- instead): All things considered it could require, for example,
a second argument to indicate the message title, a third for the message
type aso., and throw a TypeError when those are missing (or `undefined').
Or the order of expected arguments could be reversed or interchanged. Or
it could take no arguments at all. Or it could only be called under
certain circumstances. Or ... And then -- what?

>>> So what's your line?

>> Don't.

>
> I meant your line of _code_ for calling alert (or setTimeout or
> whatever) in an environment-agnostic fashion.


As you can hopefully see by now, there can be no such thing. The very
definition of "proprietary" precludes any reasonable assumptions about the
availability or functionality of such features in runtime environments with
ECMAScript binding that one knows nothing about.


PointedEars
--
Prototype.js was written by people who don't know javascript for people
who don't know javascript. People who don't know javascript are not
the best source of advice on designing systems that use javascript.
-- Richard Cornford, cljs, <f806at$ail$1$8300dec7@news.demon.co.uk>


All times are GMT. The time now is 06:45 PM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.