Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Primitive Re-definition

3 views
Skip to first unread message

Michael Haufe ("TNO")

unread,
Sep 13, 2009, 8:28:16 PM9/13/09
to
There seems to be a trend among jQuery "Rock Stars" that involves
redefining primitive values for "lookup efficiency". For example, I
saw the following in one of the JQuery Conference power points:

var TRUE = true,
FALSE = false,
undefined = undefined;

I've also seen something similar in the jQuery source code.

In 9 years of JavaScript development, I've never seen such a thing
done. Am I right to think that this pattern is practically pointless
in most if not all cases, or did I miss the boat on this one?

RobG

unread,
Sep 13, 2009, 8:43:36 PM9/13/09
to
On Sep 14, 10:28 am, "Michael Haufe (\"TNO\")"

I've seen this done in environments using multiple languages as a way
of creating a single variable name for true, false, etc. across all
the languages. I can't see that it's necessary in a single language
environment or where multiple languages are being used and they all
have the same syntax for those values.

I don't think it shouldn't be in a particular library - it should be
left to the programming group to decide what the generic variable
names will be, and then to define them in a manner that won't conflict
with other scripts in use.


--
Rob

RobG

unread,
Sep 13, 2009, 8:51:06 PM9/13/09
to
On Sep 14, 10:43 am, RobG <robg...@gmail.com> wrote:
> On Sep 14, 10:28 am, "Michael Haufe (\"TNO\")"
>
> <t...@thenewobjective.com> wrote:
> > There seems to be a trend among jQuery "Rock Stars" that involves
> > redefining primitive values for "lookup efficiency". For example, I
> > saw the following in one of the JQuery Conference power points:
>
> > var TRUE = true,
> > FALSE = false,
> > undefined = undefined;
>
> > I've also seen something similar in the jQuery source code.
>
> > In 9 years of JavaScript development, I've never seen such a thing
> > done. Am I right to think that this pattern is practically pointless
> > in most if not all cases, or did I miss the boat on this one?
>
> I've seen this done in environments using multiple languages as a way
> of creating a single variable name for true, false, etc. across all
> the languages. I can't see that it's necessary in a single language
> environment or where multiple languages are being used and they all
> have the same syntax for those values.
>
> I don't think it shouldn't be in a particular library

That should have been:

I think it shouldn't be in a particular library...


And it doesn't seem to be used in the current version of jQuery
(1.3.2).


--
Rob

-TNO-

unread,
Sep 13, 2009, 9:00:14 PM9/13/09
to
On Sep 13, 7:51 pm, RobG <robg...@gmail.com> wrote:

> And it doesn't seem to be used in the current version of jQuery
> (1.3.2).

Line 18:
-------------------------------------
14. var
15. // Will speed up references to window, and allows munging
its name.
16. window = this,
17. // Will speed up references to undefined, and allows
munging its name.
18. undefined,
19. // Map over jQuery in case of overwrite
20. _jQuery = window.jQuery,
21. // Map over the $ in case of overwrite
22. _$ = window.$,
------------------------------------------------------------

RobG

unread,
Sep 13, 2009, 11:14:57 PM9/13/09
to


I searched for TRUE and FALSE. :-(

Any idea whether the "speed up references" claim has any basis in
fact?

Testing 1,000,000 loops gave the following results:

Browser Global Local
IE 235 110
Firefox 3 3

So while it might be measurably faster in IE, I don't think it makes
any practical difference. The string "undefined" only appears 50 times
in jQuery, perhaps it's the "munging" part that is important to the
author. Where does that happen?


Here's my test function:

function testRef(n) {
var i = n, msg, t;

var s = new Date();
while (i--) {
(t == undefined);
}
var f = new Date();

msg = 'Global undefined: ' + (f - s);
i = n;

s = new Date();
var UNDEFINED = undefined;
while (i--) {
(t == UNDEFINED);
}
f = new Date();

msg += '\nLocal undefined: ' + (f - s);

alert(msg);

}


testRef(1000000);

--
Rob

-TNO-

unread,
Sep 13, 2009, 11:59:11 PM9/13/09
to
On Sep 13, 10:14 pm, RobG <robg...@gmail.com> wrote:

> So while it might be measurably faster in IE, I don't think it makes
> any practical difference. The string "undefined" only appears 50 times
> in jQuery, perhaps it's the "munging" part that is important to the
> author. Where does that happen?
>

Here are my results to verify your own (I copied your code to a test
page here: http://thenewobjective.com/temp/vartest.html):

Global | Local
FireFox 3.5.3 3ms | 3ms
Chrome 2.0 9ms | 6ms
Safari 4.0.2 16ms | 16ms
Opera 10.00 82ms | 62ms
IE 8 109ms | 53ms
IE 7 195ms | 109ms (IE Tester)
IE 6 192ms | 112ms (IE Tester)

kangax

unread,
Sep 14, 2009, 12:05:20 AM9/14/09
to

I wouldn't call it "primitive re-definition". All that's happening here
is creation of local variables to speed-up identifier resolution. Zakas
recently had a presentation about this exact subject
(http://www.youtube.com/watch?v=mHtdZgou0qU) concluding that it is
indeed faster *in some cases*. Ditto for property resolution, of course.

What's strange about your particular snippet is aliasing of `true` and
`false` values. While `undefined` case somewhat makes sense (it's a
plain variable and needs to be resolved against a scope chain all the
way up to the global scope) I would be very surprised to see
implementations performing better with local variables rather than plain
boolean literals. I would assume that literals can be somehow *optimized
statically*, whereas variables can only be determined at runtime.

As far as munging, well yes, aliasing something like `undefined` to a
local variable will allow compressor to munge those variables:

if (x == undefined || y == undefined || z == undefined) {}

will compress into:

if(x==undefined||y==undefined||z==undefined){}

whereas aliased version:

var UNDEFINED = undefined;
if (x == UNDEFINED || y == UNDEFINED || z == UNDEFINED) {}

will compress into a smaller:

var A=undefined;if(x==A||y==A||z==A){}

The difference grows with the amount of occurrences of aliased variables
of course.

--
kangax

Lasse Reichstein Nielsen

unread,
Sep 14, 2009, 1:00:51 AM9/14/09
to
"Michael Haufe (\"TNO\")" <t...@thenewobjective.com> writes:

> There seems to be a trend among jQuery "Rock Stars" that involves
> redefining primitive values for "lookup efficiency".

I'm glad you quoted that. It makes almost no sense.

> For example, I
> saw the following in one of the JQuery Conference power points:
>
> var TRUE = true,
> FALSE = false,
> undefined = undefined;

That's just silly.
I can accept "undefined", because that would be a lookup on the
global object otherwise (but the "= undefined" is unnecessary).
The global object can be slower than most other objects and scopes,
for numerous reasons.

But "true" and "false" are *keywords*! They have no lookup time
at all, and are evaluated directly in the parser. Any aliasing
will be slower (if that matters at all).

> I've also seen something similar in the jQuery source code.

Voodoo science.

> In 9 years of JavaScript development, I've never seen such a thing
> done. Am I right to think that this pattern is practically pointless
> in most if not all cases, or did I miss the boat on this one?

I can see a point in avoiding accesses to the global object inside a
tight loop, so "undefined" makes sense. The rest are pretty much
stupid, mostly harmless, but slightly slower than just doing the right
thing.

/L
--
Lasse Reichstein Holst Nielsen
'Javascript frameworks is a disruptive technology'

Lasse Reichstein Nielsen

unread,
Sep 14, 2009, 1:17:18 AM9/14/09
to
-TNO- <t...@thenewobjective.com> writes:

These do make some sense. Avoiding lookups on the global object does
make a difference (but as with all optimizations - don't do it unless
you have profiled and found it to make a signficant contribution).

Taking a copy to be safe against overwriting also makes sense,
especially in library code that might be combined with other
libraries.

RobG

unread,
Sep 14, 2009, 3:12:13 AM9/14/09
to
On Sep 14, 3:17 pm, Lasse Reichstein Nielsen <lrn.unr...@gmail.com>
wrote:

> -TNO- <t...@thenewobjective.com> writes:
> > On Sep 13, 7:51 pm, RobG <robg...@gmail.com> wrote:
>
> >> And it doesn't seem to be used in the current version of jQuery
> >> (1.3.2).
>
> > Line 18:
> > -------------------------------------
> > 14.    var
> > 15.        // Will speed up references to window, and allows munging
> > its name.
> > 16.        window = this,
> > 17.        // Will speed up references to undefined, and allows
> > munging its name.
> > 18.        undefined,
> > 19.        // Map over jQuery in case of overwrite
> > 20.        _jQuery = window.jQuery,
> > 21.        // Map over the $ in case of overwrite
> > 22.        _$ = window.$,
> > ------------------------------------------------------------
>
> These do make some sense. Avoiding lookups on the global object does
> make a difference (but as with all optimizations - don't do it unless
> you have profiled and found it to make a signficant contribution).

Your hint about the length of the scope chain got me thinking about
making it longer - so I did. However, avoiding global lookups still
doesn't make a lot of difference. I also made the comparison in the
same scope as the function running the loop so that only the undefined
lookup should use the scope chain.

IE:
Global undefined level 0: 172
Global undefined level 1: 234
Global undefined level 2: 281
Local level 0: 47
Local level 2: 156

Firefox:
Global undefined level 0: 2
Global undefined level 1: 153
Global undefined level 2: 151
Local level 0: 2
Local level 2: 124

Performance seems to be enhanced more by executing statements as
global code than messing with local declarations of global variables.

Here's the new code:

<script type="text/javascript">

function testRef(n) {
var i = n, msg = [], f, s, t;


s = new Date();
while (i--) {

(t === undefined);
}
f = new Date();
msg.push('Global undefined level 0: ' + (f - s));

function level1() {


i = n;
s = new Date();

var t;
while (i--) {
(t === undefined);
}
f = new Date();
msg.push('\nGlobal undefined level 1: ' + (f - s));
}

level1();

function level2() {
(function() {


i = n;
s = new Date();

var t;
while (i--) {
(t === undefined);
}
f = new Date();
msg.push('\nGlobal undefined level 2: ' + (f - s));
})();
}

level2();

i = n;
s = new Date();
var UNDEFINED = undefined;
while (i--) {

(t === UNDEFINED);
}
f = new Date();
msg.push('\nLocal level 0: ' + (f - s));

function local2() {
(function() {


i = n;
s = new Date();
var UNDEFINED = undefined;

var t;
while (i--) {
(t === UNDEFINED);
}
f = new Date();
msg.push('\nLocal level 2: ' + (f - s));
})();
}
local2();

document.getElementById('div0').innerHTML = msg.join('<br>');
}

window.onload = function(){testRef(500000);};

</script>

<div id="div0"></div>


>
> Taking a copy to be safe against overwriting also makes sense,
> especially in library code that might be combined with other
> libraries.

I can understand that perspective. However, it woud be better to use:

var UNDEFINED;

so that it is obvious within the code that it has been defined within
the script. Also, using:

var undefined = undefined;

means that if some other script that assigns it an unexpected value
runs first, the "local" undefined will get that unexpected value.


--
Rob

Garrett Smith

unread,
Sep 14, 2009, 3:44:14 AM9/14/09
to
RobG wrote:
> On Sep 14, 11:00 am, -TNO- <t...@thenewobjective.com> wrote:
>> On Sep 13, 7:51 pm, RobG <robg...@gmail.com> wrote:
>>
>>> And it doesn't seem to be used in the current version of jQuery
>>> (1.3.2).
>> Line 18:
>> -------------------------------------
>> 14. var
>> 15. // Will speed up references to window, and allows munging
>> its name.
>> 16. window = this,
>> 17. // Will speed up references to undefined, and allows
>> munging its name.

Means the identifier becomes shortened in minification, to something
like |b|.
[snip]

>
> I searched for TRUE and FALSE. :-(

Not there. Look to Cappuccino for that. Plus nil, Nil, NULL, NO, YES,
etc. All globals there, so not mungeable.

>
> Any idea whether the "speed up references" claim has any basis in
> fact?

I have a test for scope chain and identifier resolution, as well as
assignment and reading using the identifier from global object or
containing scope. The results vary depending on the browser.

I will post that up in a new thread tomorrow. It is getting late here,
almost 1am.
--
Garrett
comp.lang.javascript FAQ: http://jibbering.com/faq/

Thomas 'PointedEars' Lahn

unread,
Sep 14, 2009, 4:24:19 AM9/14/09
to
RobG wrote:
> On Sep 14, 11:00 am, -TNO- <t...@thenewobjective.com> wrote:
>> On Sep 13, 7:51 pm, RobG <robg...@gmail.com> wrote:
>>> And it doesn't seem to be used in the current version of jQuery
>>> (1.3.2).
>> Line 18:
>> -------------------------------------
>> 14. var
>> 15. // Will speed up references to window, and allows munging
>> its name.
>> 16. window = this,
>> 17. // Will speed up references to undefined, and allows
>> munging its name.
>> 18. undefined,
>> 19. // Map over jQuery in case of overwrite
>> 20. _jQuery = window.jQuery,
>> 21. // Map over the $ in case of overwrite
>> 22. _$ = window.$,
>> ------------------------------------------------------------
>
>
> I searched for TRUE and FALSE. :-(
>
> Any idea whether the "speed up references" claim has any basis in
> fact?

Scope chain; see Nicholas Zakas' presentation about it, which is correct in
that regard. However, identifying `window' with `this' (i.e., the reference
to the ECMAScript Global Object here) is jQuery's first bug, of course.


PointedEars
--
Use any version of Microsoft Frontpage to create your site.
(This won't prevent people from viewing your source, but no one
will want to steal it.)
-- from <http://www.vortex-webdesign.com/help/hidesource.htm> (404-comp.)

Gabriel Gilini

unread,
Sep 14, 2009, 8:48:26 AM9/14/09
to
On Sep 14, 5:24 am, Thomas 'PointedEars' Lahn <PointedE...@web.de>
wrote:
[...]

> However, identifying `window' with `this' (i.e., the reference
> to the ECMAScript Global Object here) is jQuery's first bug, of course.

I understand that `window' is a property of the Global Object. But
besides semantics, what else could that misconception cause?

--
Gabriel Gilini

Thomas 'PointedEars' Lahn

unread,
Sep 14, 2009, 8:53:38 AM9/14/09
to

Semantics *is* the problem. One object is a host object; the other one is
not. One object has built-in properties that have a special meaning; the
other one doesn't have them, and vice-versa.

Your signature is borken, it must be delimited by a line containing only
"-- " (except newline).


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$8300...@news.demon.co.uk>

kangax

unread,
Sep 14, 2009, 9:20:54 AM9/14/09
to
RobG wrote:
> On Sep 14, 3:17 pm, Lasse Reichstein Nielsen <lrn.unr...@gmail.com>
> wrote:
[...]

>> Taking a copy to be safe against overwriting also makes sense,
>> especially in library code that might be combined with other
>> libraries.
>
> I can understand that perspective. However, it woud be better to use:
>
> var UNDEFINED;
>
> so that it is obvious within the code that it has been defined within
> the script. Also, using:
>
> var undefined = undefined;

I would replace `undefined` on RHS with `void` (also mentioned here by
PE recently):

var undefined = void 0;

or:

(function(undefined){

// do stuff

})();

Here, you get a "safe" `undefined` with faster resolution. The
difference with global `undefined` (for the code that uses it) is
undetectable (well almost), so the whole thing is rather transparent.

[...]

--
kangax

Lasse Reichstein Nielsen

unread,
Sep 14, 2009, 12:55:58 PM9/14/09
to
RobG <rob...@gmail.com> writes:

> Also, using:
>
> var undefined = undefined;
>
> means that if some other script that assigns it an unexpected value
> runs first, the "local" undefined will get that unexpected value.

Actually not. The variable "undefined" refers to the variable defined
in the same scope. Remember that in Javascript, all variables (and
functions) are declared before the body of a function is executed.
The line above "var undefined = undefined" is equivalent to
"var undefined; undefined = undefined;"

Thomas 'PointedEars' Lahn

unread,
Sep 14, 2009, 1:27:20 PM9/14/09
to
kangax wrote:

> RobG wrote:
>> var undefined = undefined;
>
> I would replace `undefined` on RHS with `void` (also mentioned here by
> PE recently):
>
> var undefined = void 0;
>
> or:
>
> (function(undefined){
>
> // do stuff
>
> })();
>
> Here, you get a "safe" `undefined` with faster resolution. The
> difference with global `undefined` (for the code that uses it) is
> undetectable (well almost), so the whole thing is rather transparent.

Actually, in a *local* execution context,

var undefined;

suffices.

Garrett Smith

unread,
Sep 14, 2009, 4:54:49 PM9/14/09
to
kangax wrote:
> RobG wrote:
>> On Sep 14, 3:17 pm, Lasse Reichstein Nielsen <lrn.unr...@gmail.com>
>> wrote:
> [...]
>>> Taking a copy to be safe against overwriting also makes sense,
>>> especially in library code that might be combined with other
>>> libraries.
>>
>> I can understand that perspective. However, it woud be better to use:
>>
>> var UNDEFINED;
>>

When extracting a method to another scope, the extracted method might
need to redefine UNDEFINED (if it references that from the scope chain
it is being extracted from).

>> so that it is obvious within the code that it has been defined within
>> the script. Also, using:
>>
>> var undefined = undefined;
>
> I would replace `undefined` on RHS with `void` (also mentioned here by
> PE recently):
>

What is wrong with:-

var undefined;

?

kangax

unread,
Sep 14, 2009, 5:49:24 PM9/14/09
to
Garrett Smith wrote:
> kangax wrote:
>> RobG wrote:
>>> On Sep 14, 3:17 pm, Lasse Reichstein Nielsen <lrn.unr...@gmail.com>
>>> wrote:
[...]
>>> so that it is obvious within the code that it has been defined within
>>> the script. Also, using:
>>>
>>> var undefined = undefined;
>>
>> I would replace `undefined` on RHS with `void` (also mentioned here by
>> PE recently):
>>
>
> What is wrong with:-
>
> var undefined;
>
> ?
>

Nothing. I completely overlooked it :)

--
kangax

RobG

unread,
Sep 14, 2009, 6:38:13 PM9/14/09
to
On Sep 15, 2:55 am, Lasse Reichstein Nielsen <lrn.unr...@gmail.com>
wrote:

> RobG <robg...@gmail.com> writes:
> > Also, using:
>
> >   var undefined = undefined;
>
> > means that if some other script that assigns it an unexpected value
> > runs first, the "local" undefined will get that unexpected value.
>
> Actually not. The variable "undefined" refers to the variable defined
> in the same scope. Remember that in Javascript, all variables (and
> functions) are declared before the body of a function is executed.
> The line above "var undefined = undefined" is equivalent to
> "var undefined; undefined = undefined;"

Ah yes, hadn't thought about that!


--
Rob

Gabriel Gilini

unread,
Sep 14, 2009, 7:44:53 PM9/14/09
to
Thomas 'PointedEars' Lahn wrote:
> Gabriel Gilini wrote:
>> On Sep 14, 5:24 am, Thomas 'PointedEars' Lahn <PointedE...@web.de>
>> wrote:
>> [...]
>>> However, identifying `window' with `this' (i.e., the reference
>>> to the ECMAScript Global Object here) is jQuery's first bug, of course.
>> I understand that `window' is a property of the Global Object. But
>> besides semantics, what else could that misconception cause?
>
> Semantics *is* the problem. One object is a host object; the other one is
> not. One object has built-in properties that have a special meaning; the
> other one doesn't have them, and vice-versa.

Ok.

> Your signature is borken, it must be delimited by a line containing only
> "-- " (except newline).

It's that stupid Google Groups, it should be fine now.

--
Gabriel Gilini

David Mark

unread,
Sep 14, 2009, 7:57:33 PM9/14/09
to
On Sep 14, 1:17 am, Lasse Reichstein Nielsen <lrn.unr...@gmail.com>
wrote:

> -TNO- <t...@thenewobjective.com> writes:
> > On Sep 13, 7:51 pm, RobG <robg...@gmail.com> wrote:
>
> >> And it doesn't seem to be used in the current version of jQuery
> >> (1.3.2).
>
> > Line 18:
> > -------------------------------------
> > 14.    var
> > 15.        // Will speed up references to window, and allows munging
> > its name.
> > 16.        window = this,
> > 17.        // Will speed up references to undefined, and allows
> > munging its name.
> > 18.        undefined,
> > 19.        // Map over jQuery in case of overwrite
> > 20.        _jQuery = window.jQuery,
> > 21.        // Map over the $ in case of overwrite
> > 22.        _$ = window.$,
> > ------------------------------------------------------------
>
> These do make some sense.

Not in the bigger picture. And if optimization is in order, why isn't
that this.jQuery and this.$?

> Avoiding lookups on the global object does
> make a difference (but as with all optimizations - don't do it unless
> you have profiled and found it to make a signficant contribution).

And there won't be unfortunate side effects, like memory leaks.
Preserving a reference to the mother of all host objects can't be
considered good practice.

>
> Taking a copy to be safe against overwriting also makes sense,
> especially in library code that might be combined with other
> libraries.

I don't know. I think I'd want to know if some rogue library was
overwriting my methods. ;)

RobG

unread,
Sep 15, 2009, 12:27:47 AM9/15/09
to
On Sep 14, 5:12 pm, RobG <robg...@gmail.com> wrote:
> On Sep 14, 3:17 pm, Lasse Reichstein Nielsen <lrn.unr...@gmail.com>
> wrote:
[...]

> > These do make some sense. Avoiding lookups on the global object does
> > make a difference (but as with all optimizations - don't do it unless
> > you have profiled and found it to make a signficant contribution).
>
> Your hint about the length of the scope chain got me thinking about
> making it longer - so I did.  However, avoiding global lookups still
> doesn't make a lot of difference. I also made the comparison in the
> same scope as the function running the loop so that only the undefined
> lookup should use the scope chain.
>
> IE:
> Global undefined level 0: 172
> Global undefined level 1: 234
> Global undefined level 2: 281
> Local level 0: 47
> Local level 2: 156
>
> Firefox:
> Global undefined level 0: 2
> Global undefined level 1: 153
> Global undefined level 2: 151
> Local level 0: 2
> Local level 2: 124
>
> Performance seems to be enhanced more by executing statements as
> global code than messing with local declarations of global variables.


I looked at the code again and realised the counter i was still being
looked-up along the scope chain, so I created a local alais. Here's
the new results:

IE
Global undefined level 0: 172

Global undefined level 1: 156
Global undefined level 2: 188
Local level 0: 62
Local level 2: 63

Firefox
Global undefined level 0: 1
Global undefined level 1: 2
Global undefined level 2: 1
Local level 0: 1
Local level 2: 1

So it would seem that global properties like undefined may well
already be optimised and that creating a local scope for such
variables has no measurable performance benefit.

What I was measuring was the lookup of a standard variable on the
scope chain, so aliasing those may make a (big) difference.

Updated code:

function testRef(n) {
var i = n, msg = [], f, s, t;


s = new Date();
while (i--) {
(t === undefined);
}
f = new Date();
msg.push('Global undefined level 0: ' + (f - s));

function level1() {
var i = n, t;


s = new Date();
while (i--) {
(t === undefined);
}
f = new Date();

msg.push('\nGlobal undefined level 1: ' + (f - s));
}

level1();

function level2() {
(function() {
var i = n, t;


s = new Date();
while (i--) {
(t === undefined);
}
f = new Date();

msg.push('\nGlobal undefined level 2: ' + (f - s));
})();
}

level2();

i = n;
s = new Date();

var UNDEFINED;


while (i--) {
(t === UNDEFINED);
}
f = new Date();
msg.push('\nLocal level 0: ' + (f - s));

function local2() {
(function() {
var i = n, t, UNDEFINED;


s = new Date();
while (i--) {

(t === UNDEFINED);
}
f = new Date();
msg.push('\nLocal level 2: ' + (f - s));
})();
}
local2();

document.getElementById('div0').innerHTML = msg.join('<br>');
}

window.onload = function(){testRef(500000);};


--
Rob

kangax

unread,
Sep 15, 2009, 8:40:15 AM9/15/09
to

Let me guess, was it FF3.5.x you were testing with? :)

The thing is that newer engines (especially FF3.5 which, afaik, should
have JIT on) are rather indifferent to these optimizations.

It is older ones that show somewhat substantial difference. Here are FF
results on my machine (Mac OS X 10.6.1):

FF 3.5.2:

Global undefined level 0: 1

Global undefined level 1: 1
Global undefined level 2: 2


Local level 0: 1
Local level 2: 1

FF 3.0.13:

Global undefined level 0: 82
Global undefined level 1: 83
Global undefined level 2: 83
Local level 0: 24
Local level 2: 24

FF 2.0.20:

Global undefined level 0: 600
Global undefined level 1: 627
Global undefined level 2: 1116
Local level 0: 17
Local level 2: 17

FF 1.5.0.7

Global undefined level 0: 689
Global undefined level 1: 698
Global undefined level 2: 1397
Local level 0: 30
Local level 2: 29

[snip test]

--
kangax

Jeremy J Starcher

unread,
Sep 15, 2009, 1:42:54 PM9/15/09
to
>
> var TRUE = true,
> FALSE = false,
> undefined = undefined;
>
> I've also seen something similar in the jQuery source code.
>
> In 9 years of JavaScript development, I've never seen such a thing done.
> Am I right to think that this pattern is practically pointless in most
> if not all cases, or did I miss the boat on this one?

The original versions of Javascript did not have an 'undefined' constant,
though they did have an undefined value.

For a while, it was common to include the line:
var undefined;

in your script.

Hasn't been needed in ... a long while now.

Thomas 'PointedEars' Lahn

unread,
Sep 15, 2009, 3:22:21 PM9/15/09
to
Jeremy J Starcher wrote:
>> var TRUE = true,
>> FALSE = false,
>> undefined = undefined;
>>
>> I've also seen something similar in the jQuery source code.
>>
>> In 9 years of JavaScript development, I've never seen such a thing done.
>> Am I right to think that this pattern is practically pointless in most
>> if not all cases, or did I miss the boat on this one?
>
> The original versions of Javascript did not have an 'undefined' constant,
> though they did have an undefined value.

What are you talking about? The very problem and the cause of this thread
is that `undefined' is _not_ a constant; it is a property of the global
object, if that, that can successfully be assigned to.

> For a while, it was common to include the line:
> var undefined;
>
> in your script.

Apparently you have not been paying attention.

If that was so, it was as error-prone as it is now, at least in the global
execution context. Because variable instantiation happens before execution,
and variable redeclaration does _not_ reset an existing properties'/already
declared variable's value. Suppose the global object has a property named
`undefined', as in implementations of ECMAScript Edition 3 Final, then

/* injected by foreign script */
undefined = true;

/* in one's own script */
var undefined;

does not change anything.

> Hasn't been needed in ... a long while now.

Because of the variability of `undefined', it may appear to be necessary to
define one's own in one's scripts.

Please leave one attribution line per quotation level.


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

Jeremy J Starcher

unread,
Sep 15, 2009, 3:36:07 PM9/15/09
to
On Tue, 15 Sep 2009 21:22:21 +0200, Thomas 'PointedEars' Lahn wrote:

> Jeremy J Starcher wrote:
>>> var TRUE = true,
>>> FALSE = false,
>>> undefined = undefined;
>>>
>>> I've also seen something similar in the jQuery source code.
>>>
>>> In 9 years of JavaScript development, I've never seen such a thing
>>> done. Am I right to think that this pattern is practically pointless
>>> in most if not all cases, or did I miss the boat on this one?
>>
>> The original versions of Javascript did not have an 'undefined'
>> constant, though they did have an undefined value.
>
> What are you talking about? The very problem and the cause of this
> thread is that `undefined' is _not_ a constant; it is a property of the
> global object, if that, that can successfully be assigned to.

Poor choice of words. The early implementations did not have a property
of the global object with the name 'undefined.'

>> For a while, it was common to include the line: var undefined;
>>
>> in your script.
>
> Apparently you have not been paying attention.
>
> If that was so, it was as error-prone as it is now, at least in the
> global execution context. Because variable instantiation happens before
> execution, and variable redeclaration does _not_ reset an existing
> properties'/already declared variable's value. Suppose the global
> object has a property named `undefined', as in implementations of

> ECMAScript Edition 3 Final, then [snip]

I'm not saying it wasn't error prone. I am saying that if you wanted a
variable or property with the value of undefined to check against, you
had to create your own and 'undefined' was the popular choice.

ECMAScript Edition 3 Final means nothing in this context, because this
practice (and its need) are much earlier than this standard. I believe
that good coders should have a sense of history, not only about computers
in general, but about the language they are using. I bring this up out
of that sense of history.n

Garrett Smith

unread,
Sep 15, 2009, 4:51:11 PM9/15/09
to
Thomas 'PointedEars' Lahn wrote:
> Gabriel Gilini wrote:
>> On Sep 14, 5:24 am, Thomas 'PointedEars' Lahn <PointedE...@web.de>
>> wrote:
>> [...]
>>> However, identifying `window' with `this' (i.e., the reference
>>> to the ECMAScript Global Object here) is jQuery's first bug, of course.
>> I understand that `window' is a property of the Global Object. But
>> besides semantics, what else could that misconception cause?
>
> Semantics *is* the problem. One object is a host object; the other one is
> not. One object has built-in properties that have a special meaning; the
> other one doesn't have them, and vice-versa.
>

In a recent thread "Re: [[Delete]]'ing window properties in IE", we
discussed how IE's global object also a host object, and it is not the
global variable object.

| The global variable object is implemented as a JScript object, and the
| global object is implemented by the host.

Taken from Eric Lippert's blog entry.

jdalton

unread,
Sep 15, 2009, 5:08:35 PM9/15/09
to
Hi All,

Just wanted to give a heads up to those performing benchmarks and
tests on local vs global lookup speeds.
It has been done before in the clj. Here are some more benchmarks
(which link to the clj threads)

http://homepage.mac.com/jorgechamorro/cljs/032/
http://homepage.mac.com/jorgechamorro/cljs/033/

- JDD

Garrett Smith

unread,
Sep 15, 2009, 5:21:48 PM9/15/09
to

The release notes for TraceMonkey, Mozilla's new javascript engine, do
not mention that[1], but I think if TraceMonkey is not doing that, it
would be possible.

I believe TraceVis would tell you. I'm not yet running that so I can't
say I know for sure.

There may be a potential optimization for removal of unused identifiers
in closures.

If an identifier is declared in the enclosing scope of a group of
functions, and a lexical scan of those nested functions, e.g. "look into
scope" reveals that none of those nested functions access that
identifier, do not make use of |eval| and the enclosing scope does not
use |eval| or assign to |arguments| properties and no nested scopes
access their respective |arguments|, can optimizing JS interpreter
collect them as garbage? I feel like I am missing some cases related to
|with| but can't think of them off the top of my head.

Is this possible?

This another one of those "if a tree falls in the forest, does it make a
sound?"

[1]http://hacks.mozilla.org/2009/07/tracemonkey-overview/

Stefan Weiss

unread,
Sep 15, 2009, 6:18:52 PM9/15/09
to
On 15/09/09 23:21, Garrett Smith wrote:
> There may be a potential optimization for removal of unused identifiers
> in closures.
>
> If an identifier is declared in the enclosing scope of a group of
> functions, and a lexical scan of those nested functions, e.g. "look into
> scope" reveals that none of those nested functions access that
> identifier, do not make use of |eval| and the enclosing scope does not
> use |eval| or assign to |arguments| properties and no nested scopes
> access their respective |arguments|, can optimizing JS interpreter
> collect them as garbage? I feel like I am missing some cases related to
> |with| but can't think of them off the top of my head.

You are correct, the presence of |with| makes lexical scans (static
analysis) impossible:

var obj = {};
var a = 1;

function check() {
with (obj) {
console.log(a);
}
}

check(); // 1
obj.a = 2;
check(); // 2

Depending on the current (runtime) properties of obj, |a| in |check| can
refer to two different entities.


cheers,
stefan

Garrett Smith

unread,
Sep 15, 2009, 9:37:15 PM9/15/09
to
Jeremy J Starcher wrote:
> On Tue, 15 Sep 2009 21:22:21 +0200, Thomas 'PointedEars' Lahn wrote:
>
>> Jeremy J Starcher wrote:
[...]

>>> For a while, it was common to include the line: var undefined;
>>>
>>> in your script.
>> Apparently you have not been paying attention.
>>
>> If that was so, it was as error-prone as it is now, at least in the
>> global execution context. Because variable instantiation happens before
>> execution, and variable redeclaration does _not_ reset an existing
>> properties'/already declared variable's value. Suppose the global
>> object has a property named `undefined', as in implementations of
>> ECMAScript Edition 3 Final, then [snip]
>
> I'm not saying it wasn't error prone. I am saying that if you wanted a
> variable or property with the value of undefined to check against, you
> had to create your own and 'undefined' was the popular choice.
>

Yep, and now you don't need to do that anymore, but if you do it won't
cause any problems. If you do it in a closure, the side effects would be
smaller file size and shorter scope chain to resolve the identifier.
Doesn't sound all that bad, does it?

kangax

unread,
Sep 15, 2009, 11:43:54 PM9/15/09
to
Garrett Smith wrote:
> kangax wrote:
>> RobG wrote:
>>> On Sep 14, 5:12 pm, RobG <robg...@gmail.com> wrote:
[...]

>>> So it would seem that global properties like undefined may well
>>> already be optimised and that creating a local scope for such
>>> variables has no measurable performance benefit.
>>
>> Let me guess, was it FF3.5.x you were testing with? :)
>>
>> The thing is that newer engines (especially FF3.5 which, afaik, should
>> have JIT on) are rather indifferent to these optimizations.
>>
>
> The release notes for TraceMonkey, Mozilla's new javascript engine, do
> not mention that[1], but I think if TraceMonkey is not doing that, it
> would be possible.

My FF 3.5.2 has "javascript.options.jit.content" set to true, and I
don't think I modified anything.

>
> I believe TraceVis would tell you. I'm not yet running that so I can't
> say I know for sure.
>
> There may be a potential optimization for removal of unused identifiers
> in closures.
>
> If an identifier is declared in the enclosing scope of a group of
> functions, and a lexical scan of those nested functions, e.g. "look into
> scope" reveals that none of those nested functions access that
> identifier, do not make use of |eval| and the enclosing scope does not
> use |eval| or assign to |arguments| properties and no nested scopes
> access their respective |arguments|, can optimizing JS interpreter
> collect them as garbage? I feel like I am missing some cases related to
> |with| but can't think of them off the top of my head.
>
> Is this possible?

I don't see why it wouldn't be possible (if all of the requirements you
mentioned are met). Newer engines might very well be already doing these
optimizations.

Indirect eval should *not* be allowed to execute code in a local scope
though (or just be disallowed altogether).

A classic example:

(function(){
var x = 1;
return (function(fn, arg){
return fn(arg);
});
})()(eval, 'x');

>
> This another one of those "if a tree falls in the forest, does it make a
> sound?"
>
> [1]http://hacks.mozilla.org/2009/07/tracemonkey-overview/

--
kangax

Thomas 'PointedEars' Lahn

unread,
Sep 16, 2009, 6:01:32 AM9/16/09
to

Your point being?


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

0 new messages