pseudo-namespacing in JavaScript

P

Peter Michaux

[from <URL: http://groups.google.com/group/comp.lang.javascript/msg/825bb682f5f456a5>]

But if you have hundreds of targets instead of one, then the
probability of collisions is increased. I do see your point that
"FORKINGLEAVETHISALONE" would be a less likely candidate for an
overwrite.

I've been thinking about this more for a library API.

prefix namespacing

FORK_addListener

vs.

object namespacing

FORK.addListener

It seems only one level of namespacing is every necessary for a
library. If that is the case why use an object for this namespacing
than just a prefix? Are there any useful benefits?

Accessing FORK_addListener is faster than accessing FORK.addListener.
I did do some tests on this sort of thing and I can resurrect the
results if anyone is interested. The important impression I was left
with was that doing tens or hundreds of thousands of identifier
resolutions were in the range of 40 to 60 ms. I would say speed is not
really a deciding factor.

Looping over the API properties of the library is easier but I don't
know why I would need to do that. I never have done that. With the
prefix version it is possible to loop over the properties of the
global object and do a regexp test on the property name. It wouldn't
be quite as fast but it wouldn't be brutal.

I suppose it does simulate Java namespacing syntax but that is hardly
a reason to do anything.

How did the object namespacing become so popular? Is it because the
MM_ functions were so badly written and prefix namespacing got a bad
reputation?

Peter
 
R

RobG

[from <URL:http://groups.google.com/group/comp.lang.javascript/msg/825bb682f5f456a5>]

But if you have hundreds of targets instead of one, then the
probability of collisions is increased. I do see your point that
"FORKINGLEAVETHISALONE" would be a less likely candidate for an
overwrite.

I've been thinking about this more for a library API.

prefix namespacing

FORK_addListener

vs.

object namespacing

FORK.addListener

It seems only one level of namespacing is every necessary for a
library. If that is the case why use an object for this namespacing
than just a prefix? Are there any useful benefits?

Probably none, it just looks neater to me to use myNs.foo than
MYNS_foo.

I have typically used a two character prefix to signify a project, for
small stuff for myself everthing goes into rX. But as you point out,
that doesn't give any better protection (probably less) than a prefix
of rX_.

Using a prefix may also make life easier when referencing other parts
of a library, e.g. in the following:

var FORK = {
foo: function(){},
bar: function(){
this.foo();
}
}

I am always left with the dilema of whether to use this.foo so that I
can easily change the namespace, or use FORK.foo so that I can assign
bar to other objects and not worry about where it is called from. If
a prefix is used instead:

var FORK_foo = function(){}
var FORK_bar = function(){FORK_foo();}

the full qualifier is always used and since it will be unique, a
global find/replace can probably be used safely if the function name
needs to change.

One downside is having to type and transmit more characters, but I
guess that can be attenuated by using local variables as temporary
references where it's an issue.
 
P

Peter Michaux

[snip]
prefix namespacing


object namespacing

It seems only one level of namespacing is every necessary for a
library. If that is the case why use an object for this namespacing
than just a prefix? Are there any useful benefits?

Probably none, it just looks neater to me to use myNs.foo than
MYNS_foo.

I agree the dot does look a little nicer but...

It seems appealing to separate the concepts of namespacing with an
underscore verses message passing with objects that are truly being
used as objects with the dot.

By "objects truly being used as objects" I mean that the concepts of
some methods of an object sharing some state variables and all working
on those state variables.

Namespacing is just avoiding collisions and in functional-style
programming using the dot system and "this" to access the same
namespace doesn't really sit too well.

I have typically used a two character prefix to signify a project, for
small stuff for myself everthing goes into rX. But as you point out,
that doesn't give any better protection (probably less) than a prefix
of rX_.

Using a prefix may also make life easier when referencing other parts
of a library, e.g. in the following:

var FORK = {
foo: function(){},
bar: function(){
this.foo();
}
}

I am always left with the dilema of whether to use this.foo so that I
can easily change the namespace, or use FORK.foo so that I can assign
bar to other objects and not worry about where it is called from.

It is a dilemma.

Borrowing functions like you describe makes many things tricky and it
isn't just solved by using FORK.foo

var FORK = {
foo: function() {
alert('alpha');
FORK.foo = function() {
alert('beta');
};
}
}

var f = FORK.foo;


FORK.foo() // 'alpha' and reassigns FORK.foo
FORK.foo() // 'beta'
f() // 'alpha' and reassigns FORK.foo
f() // 'alpha' and reassigns FORK.foo
f() // 'alpha' and reassigns FORK.foo


If a prefix is used instead:

var FORK_foo = function(){}
var FORK_bar = function(){FORK_foo();}

the full qualifier is always used and since it will be unique, a
global find/replace can probably be used safely if the function name
needs to change.

I count easier search and replace as a big benefit when the clients
seem to change their minds at least seven times before the project is
over.
One downside is having to type and transmit more characters, but I
guess that can be attenuated by using local variables as temporary
references where it's an issue.

I suppose this doesn't work for global variables but if these were
local variables, I believe that compression can do the following

FORK_foo ---> $a

FORK.foo ---> $a.foo

Peter
 
D

David Mark

[snip]




prefix namespacing
FORK_addListener
vs.
object namespacing
FORK.addListener
It seems only one level of namespacing is every necessary for a
library. If that is the case why use an object for this namespacing
than just a prefix? Are there any useful benefits?
Probably none, it just looks neater to me to use myNs.foo than
MYNS_foo.

I agree the dot does look a little nicer but...

It seems appealing to separate the concepts of namespacing with an
underscore verses message passing with objects that are truly being
used as objects with the dot.

By "objects truly being used as objects" I mean that the concepts of
some methods of an object sharing some state variables and all working
on those state variables.

Namespacing is just avoiding collisions and in functional-style
programming using the dot system and "this" to access the same
namespace doesn't really sit too well.

Absolutely. It doesn't stand well either. I don't think using "this"
to reference a "namespace object" is ever a good idea. Personally, I
almost never reference such an object internally.

[snip]
I suppose this doesn't work for global variables but if these were
local variables, I believe that compression can do the following

FORK_foo ---> $a

Yes, but it doesn't seem like that identifier would ever be local,
else it wouldn't need the prefix.
FORK.foo ---> $a.foo

Right. That's one reason that I avoid referencing methods like this
internally. The "foo" example doesn't have a huge cost, but for long,
descriptive names, the additional weight piles up quickly.
 
R

Richard Cornford

Peter Michaux wrote:
I've been thinking about this more for a library API.

prefix namespacing

FORK_addListener

vs.

object namespacing

FORK.addListener

There is a strongly implied assumption here that these are the only two
possible strategies when it comes to avoiding name collisions on the global
object. That assumption is one of the reasons that "namespacing" is given
the credence it gets (there is an (understandable) revulsion at the idea of
stuffing everything into global variables).

You know that for objects providing multiple method interfaces I have a
tendency to use another strategy entirely. Specifically, providing a global
function that is called in order to get a reference to the object providing
the interface and then storing that reference in either object properties or
privately scoped variables. This avoids putting any more than needs to be
globally accessible into the global namespace and allows the pertinent
interfaces to be used without their property accessors ever needing get to
the global object while being resolved. And it is nice and flexible in terms
of swapping interface providers.
It seems only one level of namespacing is every necessary
for a library. If that is the case why use an object for
this namespacing than just a prefix? Are there any useful
benefits?

In many cases there is even no need for a prefix. If the name used is
precise and unambiguous about what it (the Identifier, the object/function
referred to) does/is for then naming collisions become indicative of having
redundant objects in the system. If you find yourself with two
objects/functions that do/are for the same job/thing then one of them should
not be there. If people seriously think that giving a function/method the
name, for example, "S" is a good idea (outside of a small/self contained
function local scope) then they should not be jumping through hoops in order
to avoid the consequences, they should be changing their ideas about what
constitutes a sensible name.
Accessing FORK_addListener is faster than accessing
FORK.addListener.

Inevitably in direct comparison, But having FORK_addListener as a property
of the global object implies also having FORK_removeListener as a property
of the global object. It has been demonstrated that having more properties
of the global object does slow down the resolution of single identifiers in
some environments.
I did do some tests on this sort of thing and I can
resurrect the results if anyone is interested. The
important impression I was left with was that doing
tens or hundreds of thousands of identifier resolutions
were in the range of 40 to 60 ms. I would say speed is
not really a deciding factor.

Well, that may depend quite a bit on the total size of the system. IE 6 is a
particular problem (IE 7 is much better in this regard) because it executes
scripts markedly slower if there are a lot of objects in the system. If, in
IE 6, you create a loop that places 20,000 new (so distinct) objects into an
array and then execute your speed tests in the resulting environment then
you may observe an interesting degradation in the performance.

Thus as systems get bigger (and importing a sizeable library is a good
initial step in that direction) performance can degrade. So the minor
details, like how property accessors are resolved, may become more
significant.

I know this because I work on a system that has become so big that it is
pushing up against the limits of what IE 6 can cope with at all. And that is
one of the reasons that I am so cynical about "namspacing"; 150,000 odd
lines of client-side code and still nowhere near having any concerns about
name conflicts on the global object.
Looping over the API properties of the library is easier
but I don't know why I would need to do that. I never
have done that. With the prefix version it is possible
to loop over the properties of the global object and do
a regexp test on the property name.

IE (or rather JScript) has a bug where when variable instantiation in the
global execution context adds properties to the variable object (the global
object in that context) it sets their - DontEnum - attribute when it should
not (according to ECMA 262). So enumerating your global Identifiers may not
be that practical. It is a good thing that you don't see the need to do so.
It wouldn't be quite as fast but it wouldn't be brutal.

Hopefully, of you did see a reason for doing that you would not want to do
it more than once pre execution of the total application.
I suppose it does simulate Java namespacing syntax but
that is hardly a reason to do anything.

It is actually more of a reason for not doing it. My experience suggests
that any actions taken to make javascript look more like Java act to inhibit
the rate at which Java programmes can transition to an understanding of
javascript, because they make them more resistant to abandoning their
Java-originated preconceptions about what javascript is.
How did the object namespacing become so popular?

Strong resistance to the idea of stuffing many things into the global
namespace (possibly as a knee-jerk overgeneralization of the injunction
against using global variables that follows from the axiomatic "no variable
should ever be given more scope than it absolutely needs", which does not
really apply to "namespaces" as - FORK_addListener - doesn't really have any
different scope than - FORK.addListener -).

It is also possible that in the sort of uncritical environments where these
things propagate any proposed 'solution' to a perceived problem may easily
become 'the solution', and simultaneously terminate any questioning of the
problem as originally perceived by transforming it into 'the problem'.
Is it because the MM_ functions were so badly written
and prefix namespacing got a bad reputation?

I cannot see that as an explanation. Not least because I don't think that
many of the individuals who I have seen advocating namespaces would have
been in a position appreciate how very bad the MM_ functions were.

Richard.
 
D

dhtml

It's something I'm thinking about too.

Identifiers conflicting with identifiers is usually less of a problem
as identifiers conflict with element ids. The problem is these global
elementID properties seem to be ReadOnly in IE.

<div id='out'></div>

alert(out); // object.

var out = function() {

};

alert(out); // object.

IE allows these variables to bind to the global object if they are
used in a var or function declaration.

function out() { }
alert( out ); // function(){}

I'm not sure why it works this way. I know that it's the opposite in
Webkit. In webkit, if you use var, it doesn't bind, but if you declare
w/o var, it does assign to the global object. I'd actually like to
know why this is.

This can be a problem if, for example, there were an element on a page
with the ID that matches something in your library. You'll probably
look at the page and wonder why it doesn't work in either Safari or
IE. Maybe you've already had this problem once or twice. I know I
have.

Another problem. I remember when Mozilla was java enabled. I wrote a
function named getClass(). (I'd been programming for about a year). My
getClass() caused a conflict with the java method getClass() and it
triggered a javascript error. I realized the problem and renamed my
function.
You know that for objects providing multiple method interfaces I have a
tendency to use another strategy entirely. Specifically, providing a global
function that is called in order to get a reference to the object providing
the interface and then storing that reference in either object properties or
privately scoped variables. This avoids putting any more than needs to be
globally accessible into the global namespace and allows the pertinent
interfaces to be used without their property accessors ever needing get to
the global object while being resolved. And it is nice and flexible in terms
of swapping interface providers.

What's that?

function getMyObject() {

}
pushing up against the limits of what IE 6 can cope with at all. And that is
one of the reasons that I am so cynical about "namspacing"; 150,000 odd
lines of client-side code and still nowhere near having any concerns about
name conflicts on the global object.

150k. That's a lot of lines of code. How many files?
 
R

Richard Cornford

dhtml said:
It's something I'm thinking about too.

Identifiers conflicting with identifiers is usually less
of a problem as identifiers conflict with element ids.
The problem is these global elementID properties seem
to be ReadOnly in IE.

<div id='out'></div>

alert(out); // object.

Did you actually try this? If I load this simple HTML page:-

<html>
<head>
<title></title>
</head>
<body>
<div id='out'></div>
<pre>
<script type="text/javascript">

document.write(out+'\n\n'); //undefined.

var out = function() {

};

document.write(out+'\n'); // function(){ ... }

</script>
</pre>
</body>
</html>

- into IE the - document.write - that corresonds with your first alert
outputs 'undefined'.

Outputting 'undefined here is an IE bug, because the global object (which is
the Variable object for the global execution context) had an 'out' property
before variable instantiation here and so variable instantiation here should
not have altered its value. But that bug is not significant to the inability
to assign to host created properties of the global object that do not
correspond with declared variables/functions.
var out = function() {
^^^
You declared it!
};

alert(out); // object.

And when I load my above HTML version of your code I get the string
representation of the assigned function object at this point not 'object'
(or even '[object]').

But even if I remove the - var - from before the - out - above and load the
page into IE this second alert does not output what you suggest; it never
gets executed as the preceding assignment throws an exception.
IE allows these variables to bind to the global object if
they are used in a var or function declaration.

function out() { }
alert( out ); // function(){}

I'm not sure why it works this way.

It might help your understanding to try executing the code you post rather
than assuming you know what it will do without executing it.

For years now it has been a recommended browser scripting 'best practice' to
explicitly declare all of the global variables that are going to be used
(and do so prior to any attempts to refer to them).
I know that it's the opposite in Webkit. In webkit, if you
use var, it doesn't bind, but if you declare w/o var, it
does assign to the global object.

I think that one of the reasons that you are not very good analysing
browsers and their behaviour when scripted (beyond your not really
understanding the pertinent standards or their implications and your
apparent willingness to make assertions about how code will behave without
verifying that it actually dose by executing it) is your lax use of
terminology.

In IE, if an Identifier happens to correspond with the ID of an element and
is never declared as the name of a global variable or function any attempt
to assign a value to the corresponding property of the global object throws
and exception. And if the property is declared then assignments do not throw
exceptions.

The "opposite" of that would be a situation where declaring a global
variable/function with an Identifier that corresponds with the ID of a DOM
node resulted in exceptions being thrown when attempts were made to assign
to the corresponding property of the global object. And when not declared
the assignment would only then be successful.

The latter is not what happens (and would be a very serious bug if it did).
The distinction here is simply that in one case a host assigned property of
the global object cannot be assigned new values under some circumstances and
in the other case it may have a new value assigned regardless. Both
situations can be accommodated within the pertinent specifications and so
this situation should be expected.

Incidentally, "bind" has no technical meaning in ECMAScript (it may acquire
a very precise technical meaning in ES4, but at present ES4 does not even
exist on paper). The term "bind" is usually used to suggest some sort of
fixing of the association of an object with the - this - keyword, and that
is an irrelevance in this context. If you want to talk about properties
being created on the global object, and values being assigned to those
properties, then there is no need for any other terminology to be used; just
say what you mean.
I'd actually like to know why this is.

If you want to know why two different sets of developers made different
decisions while exercising the freedom allotted to them by the
specifications then you would have to ask them, and hope that both sets are
willing to explain.

From the point of view of someone writing browser scripts it is just a
manifestation of the fact that when implementation decisions are left to the
implementers (rather than being explicitly specified) different implementers
will make different decisions. It is just something that should be expected,
and particularly when it is so easily demonstrated to have happened
historically.
This can be a problem if, for example, there were an element
on a page with the ID that matches something in your library.

Not if the javascript code explicitly declares the variable/function (which
it should).
You'll probably look at the page and wonder why it doesn't
work in either Safari or IE. Maybe you've already had this
problem once or twice. I know I have.

Certainly lots of people have encountered these issues. Others, as a
consequence following the 'best practice' advice have gone a long way while
never encountering them.

What's that?

function getMyObject() {

}

Pretty much, except that conceptually the thing being gotten is an
Interfaces not Objects.

Peter knows precisely what I am talking about. He has even questioned it in
the past.
150k. That's a lot of lines of code.

You don't think I have noticed that?
How many files?

In development just under 260. They get amalgamated into a dozen or so
between the first and second phases of QA.

Richard.
 
P

Peter Michaux

Peter Michaux wrote:
[snip]
I've been thinking about this more for a library API.
prefix namespacing


object namespacing
FORK.addListener

There is a strongly implied assumption here that these are the only two
possible strategies when it comes to avoiding name collisions on the global
object. That assumption is one of the reasons that "namespacing" is given
the credence it gets (there is an (understandable) revulsion at the idea of
stuffing everything into global variables).

You know that for objects providing multiple method interfaces I have a
tendency to use another strategy entirely. Specifically, providing a global
function that is called in order to get a reference to the object providing
the interface and then storing that reference in either object properties or
privately scoped variables. This avoids putting any more than needs to be
globally accessible into the global namespace and allows the pertinent
interfaces to be used without their property accessors ever needing get to
the global object while being resolved. And it is nice and flexible in terms
of swapping interface providers.

For the purposes of a namespace collision discussion, I don't see much
difference between getting the appropriate function using

FORK.addListener

or using a function

FORK('addListener')

Both use a single global variable as the first step in getting the
required object.

The second version can do more when it gets the function because it
can execute some code to choose or build that function. But for
namespace considerations both are equally likely to have collisions.


[snip]
I know this because I work on a system that has become so big that it is
pushing up against the limits of what IE 6 can cope with at all. And that is
one of the reasons that I am so cynical about "namspacing"; 150,000 odd
lines of client-side code and still nowhere near having any concerns about
name conflicts on the global object.

I can understand that there are no problems if the 150,000 lines are
all yours. That is the situation I am in for work also. If some of the
lines belong to someone else then problems can start. Mashups create a
problem where two libraries could likely define "addListener" and
collide. As computers get faster and connections improve, this sort of
waste will become more common place because it saves developer time:
much like writing in a high level language vs assembly is wasteful in
some ways but better in others.

[snip]

Thanks for the other information as well, Richard.

Peter
 
D

dhtml

On Feb 22, 5:31 am, "Richard Cornford" <[email protected]>
[snip]

FORK.addListener

or using a function

FORK('addListener')

Both use a single global variable as the first step in getting the
required object.

The second version can do more when it gets the function because it
can execute some code to choose or build that function. But for
namespace considerations both are equally likely to have collisions.

So in the second one, you'd need a factory method to return (possibly
create) an addListener method.

[snip]
I can understand that there are no problems if the 150,000 lines are
all yours. That is the situation I am in for work also. If some of the
lines belong to someone else then problems can start. Mashups create a
problem where two libraries could likely define "addListener" and
collide. As computers get faster and connections improve, this sort of
waste will become more common place because it saves developer time:
much like writing in a high level language vs assembly is wasteful in
some ways but better in others.

I have come to the opinion that owning code is generally a bad aspect
of the project.

From what I rember about hashtables is that they get a hashcode off
the object, then maintain buckets based on the hashcodes. A hashtable
with similarly named keys can, depending on the hash impl, degrade
performance I do not know how IE implements object as a hashtable
behind the scenes, but if it puts keys in buckets based on the key
value, and you had a very large number of keys that all started with
the same set of characters (FORK_), it could result in all those keys
going into the same bucket, which would slow down [[Get]]. I can't
speak for any real implementations and none of this means anything w/o
a perf test.

Garrett
 
D

dhtml

Did you actually try this? If I load this simple HTML page:-

The example I provided was not complete HTML.

The example you provided was more detailed, but misconstrued my point
(which had to do with namespacing).

Ok, so you want to talk about it in depth...

<div id="out">
<script type="text/javascript">
document.write(out+'\n\n');
</script>
Result is "[object]"


<script type="text/javascript">
document.write(out+'\n\n'); //undefined.
try {
var out = function() {};
} catch(ex) { alert( ex.message); }
document.write(out+'\n');
</script>

Result:
"undefined"

"function(){}"

- into IE the - document.write - that corresonds with your first alert
outputs 'undefined'.
When the execution context is entered in that script tag, the var out
statement declares a property named |out| with the value undefined.

Next, there is an assigment to out. a functionExpression.
Outputting 'undefined here is an IE bug, because the global object (which is
the Variable object for the global execution context) had an 'out' property
before variable instantiation here and so variable instantiation here should
not have altered its value. But that bug is not significant to the inability
to assign to host created properties of the global object that do not
correspond with declared variables/functions.

IE has a bug here, that much is true.

If you're saying that
if there's an element id that IE should create a property of the
global object, and subsequently declaring var
[insert_elements_id_here] should throw an error, well, I would
disagree with that statement.

I think IE's behavior has been wrong the whole time. Variable
instantiation should alter the value of the window property.

Example:

<html>
<head>
<title></title>
</head>
<body onload="alert(out);">
<div id='out'></div>
<pre>
<script type="text/javascript">
window.inn = 1;

var inn = 2;
document.write(out+'\n\n');
try {
this.out = function() {
};
} catch(ex) { alert( ex.message); }
document.write(out+'\n');
document.write(inn+'\n');
</script>
</pre>
</body>
</html>

Result (in IE):
[object]

[object]
2
alert => "function(){}"


Result in FF/Safari/Opera:
[object HTMLDivElement]

function () {
}
2

var out = function() {

^^^
You declared it!


alert(out); // object.

And when I load my above HTML version of your code I get the string
representation of the assigned function object at this point not 'object'
(or even '[object]').

But even if I remove the - var - from before the - out - above and load the
page into IE this second alert does not output what you suggest; it never
gets executed as the preceding assignment throws an exception.

Right. The second write() does not execute because of the error, so
it's still "[object]".

It might help your understanding to try executing the code you post rather
than assuming you know what it will do without executing it.
<script type="text/javascript">
document.write(out+'\n\n'); //undefined.
try {
function out() {
};
} catch(ex) { alert( ex.message); }
document.write(out+'\n'); // function(){ ... }
</script>


IE:
function out() {
}

function out() {
}

FF:
[object HTMLDivElement]

function out() {
}

For years now it has been a recommended browser scripting 'best practice' to
explicitly declare all of the global variables that are going to be used
(and do so prior to any attempts to refer to them).

A bottom script makes the page load faster.
I think that one of the reasons that you are not very good analysing
browsers and their behaviour when scripted (beyond your not really
understanding the pertinent standards or their implications and your
apparent willingness to make assertions about how code will behave without
verifying that it actually dose by executing it) is your lax use of
terminology.

Not very good at analyzing, huh?

We'll see a test case here that I made not too long ago. I don't have
to know the details of browser bugs to know that global variables can
conflict with element ids.
In IE, if an Identifier happens to correspond with the ID of an element and
is never declared as the name of a global variable or function any attempt
to assign a value to the corresponding property of the global object throws
and exception. And if the property is declared then assignments do not throw
exceptions.
That's not entirely true, IE allows:

window.out = function()

The "opposite" of that would be a situation where declaring a global
variable/function with an Identifier that corresponds with the ID of a DOM
node resulted in exceptions being thrown when attempts were made to assign
to the corresponding property of the global object. And when not declared
the assignment would only then be successful.

The latter is not what happens (and would be a very serious bug if it did).
The distinction here is simply that in one case a host assigned property of
the global object cannot be assigned new values under some circumstances and
in the other case it may have a new value assigned regardless. Both
situations can be accommodated within the pertinent specifications and so
this situation should be expected.

When a reference error occurs in webkit:

<html>
<head><title>test element</title>
</head>
<body>
<input name="usevar" id="usevar"/>
<pre>
<script>
try
{
_referenceError();
var usevar = 12;
}
catch (ieNeedsCatch)
{
}
finally {
document.write("usevar: " + usevar);
}
</script>
</pre>
</body>
</html>

usevar: [object HTMLInputElement]

Which is not exactly what you'd expect (undefined).

[snip about properties being created on the global object]
I'd actually like to know why this is.
[snip]

This can be a problem if, for example, there were an element
on a page with the ID that matches something in your library.

Not if the javascript code explicitly declares the variable/function (which
it should).
So-

Menu = function() {

}

-
would be something you would have to avoid.

Because it could be that theres'

<div id="Menu"></div>

on the page.



<snip>

[snip]

Pretty much, except that conceptually the thing being gotten is an
Interfaces not Objects.

Strategy/Adapter, huh?

I use strategy in a different code style. That's subject matter for
another thread.

Peter knows precisely what I am talking about. He has even questioned it in
the past.
Link?


In development just under 260. They get amalgamated into a dozen or so
between the first and second phases of QA.

Avg 560 lines/file, which is not too unreasonable, but building
javascript between QA phases? Why?
 
R

Richard Cornford

Peter said:
On Feb 22, 5:31 am, Richard Cornford wrote:

For the purposes of a namespace collision discussion, I
don't see much difference between getting the appropriate
function using

FORK.addListener

or using a function

FORK('addListener')

Both use a single global variable as the first step in
getting the required object.

From the point namespace point of view there is not much difference. Which
is precisely why all supposed naming collision problems that might be solved
by the first will also be solved by the second. Hence my pointing out that
there are not just two possible approaches (and it would be a mistake to
think that seeing a third possibility meant that there where then only
three).

The biggest impact of the way in which the two are used is in how the
interface is employed after a reference for it has been acquired.
Specifically in the areas of flexibility/maintenance and runtime
performance. In a (exaggerated for effec*t) namespace example you might
have:-

uk.co.example.dom.utils.xInterface.someMethod(y);

- where resolving the property accessor involves working up the scope chain
to the global object in order to find - uk - and then working down the chain
for object references until you get to the method that is to be called.
While having the reference to the interface stored locally implies using:-

this.xInterface.someMethod(y);

- in pure OO contexts and something like:-

localXInterface.someMethod(y);

- where the interface reference is sore in a containing scope.

Not climbing all the way up the scope chain, and particularly not doing the
lookup on the global object, does improve performance (maybe not by that
much, but relative performance and differing significance in different
contexts).

(* The exaggeration in the 'namespaced' example is not actually that great
if you consider what is done in some javascript libraries.)

The flexibility (and the consequent impact on maintenance) comes when you
realise that you want to change interface providers. To change to one that
is more efficient in context, has become more appropriate as a result of
other changes effetely changing the context, to an interface that extends
the original with method that you want to use, or to an interface that does
not provide facilities that you no longer need (or have realised that you
never needed).

So, suppose the new interface was:-

com.example.dom.utils.xInterface

- you might get away with a search and replace on all the code in question,
and then you might not. While using a local reference to the interface you
only have to visit the point of assignment in order to swap the interface,
and would then know that for all the relevant code the interface
implementation had changed (and that for all other code it had not). In the
event that the interface had been swapped for one with fewer
methods/properties it may still be necessary to go an search for individual
occurrences of, say, "xInterface.someMethod" in order to verify that there
were not any (since you have decided that it was not needed at this point)
but the process is still less involved, and less error prone than the global
search and replace necessary in the 'namespaced' version.

Of course the interchangeably of low level interfaces is an important aspect
of my design strategy, and so the architectures I design are heavily
influenced by that.
The second version can do more when it gets the function
because it can execute some code to choose or build that
function.

Yes, but initial calls to interface methods can also do 'one-time'
configuration, so while useful that facility alone could not be decisive.
Though one-time configuration is certainly simple with a single entry point.
But for namespace considerations both are equally likely
to have collisions.

Which is more 'equally unlikely' here.
[snip]
I know this because I work on a system that has become
so big that it is pushing up against the limits of what
IE 6 can cope with at all. And that is one of the reasons
that I am so cynical about "namspacing"; 150,000 odd lines
of client-side code and still nowhere near having any
concerns about name conflicts on the global object.

I can understand that there are no problems if the 150,000
lines are all yours.

They are not all mine. Though I do dictate (some would heavily emphasise
that word ;-) the rules that get applied to that code that is written.
That is the situation I am in for work also. If some of the
lines belong to someone else then problems can start.

Well the whole thing 'belongs' to my employers.
Mashups create a problem where two libraries could likely
define "addListener" and collide.

That is a very different story. If people are designing things with the
intention that they be imported into environments alongside any amount of
arbitrary code from unknown and variable sources then the onus is on them to
address the resulting issues.

It has been demonstrated in the past that quite complex functionality can be
added web pages with a between zero and one single Identifier impact on the
global namespace. So it should be practical to create functionality for
arbitrary inclusion in web pages in a way that renders any namespacing
issues manageable. Granted, anyone who thinks that it is a good idea to be
importing a large and different library with each and (possibly) every
facility included in a 'mashup' is probably not the person needed to address
the issues involved.
As computers get faster and connections improve, this sort of
waste will become more common place because it saves developer
time:

While traditionally more software production costs go towards maintenance
time?
much like writing in a high level language vs assembly is
wasteful in some ways but better in others.
<snip>

A compiler that has the time to do it can get pretty close to assembly
language efficiency executables from higher level source. But there are
trade-offs. Though I think that as far as the Internet is concerned the rate
of trade-off has been far too great. In terms of the experience of web
browsing the situation 8 years ago, using a modem and a dial-up connection,
is not radically different from the experience today with broadband and
computer hardware that is at least 10 times as fast. And that with 'Web 2.0'
and AJAX promising a more responsive user interface
("loading ... ... ... ... ... ... ... ").

Richard.
 
R

Richard Cornford

dhtml said:
The example I provided was not complete HTML.

I know that, yet it purported to support an assertion about the relationship
between HTML and scripts executing the same browsers. That makes it quite
important to show the mark-up concerned. Party to allow the reader to verify
that the effect described is not an artefact following from the use of
structurally invalid mark-up and partly to render the significant aspects of
the context unambiguous. For example, if the order of the mark-up in my
example is modified such that the DIV element's declaration follows the
SCRIPT element the outcome becomes very different. If you try that you can
observe that the assignment to an undeclared Identifier during the execution
of global code in a proceeding script element is not modified by the later
parsing of a DOM element with an ID that corresponds with the Identifier
used.
The example you provided was more detailed,

Only in the sense that it put the code you posted into an HTML mark-up
context and changed the alerts you used (which are problematic when used for
this type of analysis as they shift focus in the GUI and are not always
obvious about the sequence of events) into - document.write - calls. The
result demonstrated that the outcomes you asserted were not observed using
the code that contained them.
but misconstrued my point
(which had to do with namespacing).

If you don't clearly sate what your point is (or answer that question when
asked) you are going to get judged on the material you do post.
Ok, so you want to talk about it in depth...

I don't want to talk about it much, and I can think of many better People to
talk about it with in the event that I did (and some worse, e.g. VK).
<div id="out">
<script type="text/javascript">
document.write(out+'\n\n');
</script>
Result is "[object]"

In IE.
<script type="text/javascript">

What happened to the DIV element this time. Are we taking this example as
providing a SCRIPT element to be substituted for the SCRIPT element in the
previous example or is this one intended to be executed without a IDed DIV
element in the mark-up?
document.write(out+'\n\n'); //undefined.
try {
var out = function() {};
} catch(ex) { alert( ex.message); }
document.write(out+'\n');
</script>

Result:
"undefined"

"function(){}"

So what is it that this code is supposed to illustrate. It shows that if you
declare the variable you don't have problems with exceptions being thrown at
assignment, and if the DIV element had been shown to proceed the SCRIPT
element it would have illustrated the IE bug where variable installation for
declared Identifiers is modifying the Variable object in the global
execution context where the spec says it should not. (though that bug has no
real baring on the issues that follow from IE throwing exceptions in some
circumstances when IDed DOM elements correspond with undeclared global
variables.)
When the execution context is entered in that script tag, the
var out statement declares a property named |out| with the
value undefined.

No, the spec says that, for a variable declaration, a property is only to be
created and undefined assigned to that property in the event that the
Variable object does not already have such a property. That is quite
important as is specifies behaviour in the event that formal parameters,
function decollations and variable declarations attempt to use the same
Identifiers. Specifically, that function declarations will replace the
values of formal parameters but variable declarations will not replace the
values of either formal parameters or function declarations. But because the
specification is in terms of the interaction with the Variable object (and
pre-existing properties of the Variable object) it should apply to whichever
object is the Variable object, even when it is the global object.
Next, there is an assigment to out. a functionExpression.

No, the assignment of the result of evaluating a FunctionExpression to -
out -, The assignment itself is an ExpressionStatment.
IE has a bug here, that much is true.

And not significant to the question of whether exceptions will be thrown.
If you're saying that
if there's an element id that IE should create a property
of the global object, and subsequently declaring var
[insert_elements_id_here] should throw an error, well,
I would disagree with that statement.

I didn't even imply that. The actions taken in response to variable
declarations during variable instantiation should not modify pre-existing
properties of the Variable object. In the global execution context the
global object is used as the variable object, so the values of its
properties should not be modified. If they are then that is a bug, though
not a particularly important one (as when you declare a variable the odds
are pretty good that you will assign a new value to it prior to using it, so
whatever value it had up to that point would not be significant).
I think IE's behavior has been wrong the whole time.

Which behaviour specifically?
Variable instantiation should alter the value of the
window property.

Did you mean "should" there or 'should not'. The spec unambiguously says
'should not', and it is considered definitive when it comes to this type of
question.
Example:

<html>
<head>
<title></title>
</head>
<body onload="alert(out);">
^^^^^^^^^^^^^^^^^^

Very dubious. The functions that IE creates in response to intrinsic event
attribute declarations are quite aberrant in ECMAScript terms. They have
partly dynamically determined scope chain augmentations (that is, if you
move them form one element to another some, but not necessarily all, of the
scope chain reacts to their new context), they use a completely different
mechanism for determine their - this - value (such that such functions
originating in some contexts, if executed in isolation (not as methods of
any object) can even exhibit a - this - value that is not an object
reference (by definition an impossibility in ECMAScript). If you use this in
your analysis you risk drawing conclusions about one thing based upon an
artefact of another dubious system in IE.

For example, replace that event handler with -
onload="setTimeout('alert(out);', 1);" - and the alerted output will be
'[object]', so whichever object on the dynamically augmented scope chain of
the browser-created onload handler has an - out - property that had ended up
referring to the function object either it did not hang around for long, or
it was not the global object.

<div id='out'></div>
<pre>
<script type="text/javascript">
window.inn = 1;

var inn = 2;
document.write(out+'\n\n');
try {
this.out = function() {
};
} catch(ex) { alert( ex.message); }
document.write(out+'\n');
document.write(inn+'\n');
</script>
</pre>
</body>
</html>

Result (in IE):
[object]

[object]
2
alert => "function(){}"


Result in FF/Safari/Opera:

Don't fall victim of the delusion that something that happens in all of
these three browsers is therefor correct. Even if their behaviour is correct
is not correct by virtue of them all behaving the same.
[object HTMLDivElement]

function () {
}
2
But even if I remove the - var - from before the - out -
above and load the page into IE this second alert does
not output what you suggest; it never gets executed as
the preceding assignment throws an exception.

Right. The second write() does not execute because of
the error, so it's still "[object]".

As execution has stopped at that point is there meaning in assertions about
the nature of the values in the stopped system? In any event, it does not
actually take that many more words to turn an ambiguous comment at the end
of a line of code that will never be executed into a clear statement that
can be judged entirely on its own merits.
<script type="text/javascript">
document.write(out+'\n\n'); //undefined.
try {
function out() {
};

In ECMAScript terms this is a syntax error. A Block statement may one
contain a list of statements and no statement may commence with the
'function' keyword according to the language's syntax rules.

Here you are employing a syntax extension, or rather at least two different
syntax extensions. The specification explicitly allows for syntax
extensions, but they are of very little practical interest or use because no
two syntax extensions are likely to be identical so any attempt to use one
is very likely to have inconsistent, unpredictable and unreliable outcomes
(and that is assuming it does not come across an environment where no
equivalent syntax extension exists and the result is just a syntax error
being (more or less) reported and the script that contains it never being
executed).

} catch(ex) { alert( ex.message); }
document.write(out+'\n'); // function(){ ... }
</script>


IE:
function out() {
}

function out() {
}

FF:
[object HTMLDivElement]

function out() {
}

Your point being?

So IE and Fierfox have very different syntax extensions covering what
ECMAScript would regard as an out of context FunctionDeclaration? And as a
result the outcomes are different in those two environments. I notice that
you did not include Opera or Safari here.
A bottom script makes the page load faster.

The locations of SCRIPT elements within a document has no baring on the
presence or absence, or relative location of, global variable declarations.
Not very good at analyzing, huh?

Yes, not very good. Indeed in some respects you remind me of VK in that
regard (VK being the nadir of script analysis). For example, you have
published a page showing interactions with string objects (or rather the
objects resulting form type-converting string primitives into objects, which
may not be quite the same thing in some environments) where you describe
JScript behaving 100% in accordance with the language specification, and
then declare its behaviour to be incorrect. Then there was your recent
banning on about JScript's - propertyIsEnumerable - method being broken
without a single line of code that demonstrated anything of the kind, when
if it were true that should be the simplest thing in the world to
demonstrate. And then there was that time you wasted arguing that objects in
the DOM that implemented the NodeList and HTMLCollection interfaces were not
allowed to be function objects.
We'll see a test case here that I made not too long ago.

Will we see a clear statement bout what is being tested, and how the outcome
demonstrates the conclusions?
I don't have to know the details of browser bugs to know
that global variables can conflict with element ids.

So does everyone else, along with which reasonable steps can be taken to
avoid the issue.
That's not entirely true, IE allows:

window.out = function()

Maybe, but it is pretty closed for a quick summation of the situation.
When a reference error occurs in webkit:

<html>
<head><title>test element</title>
</head>
<body>
<input name="usevar" id="usevar"/>
<pre>
<script>
try
{
_referenceError();

Presumably it is the absence of any sort of definition for - _referenceError
- that provokes the throwing of an exception at this like of code,
preventing the evaluation of the assignment in the next line?
var usevar = 12;
}
catch (ieNeedsCatch)
{
}
finally {
document.write("usevar: " + usevar);
}
</script>
</pre>
</body>
</html>

usevar: [object HTMLInputElement]

Which is not exactly what you'd expect (undefined).

No, that is precisely what I would expect in an ECMA 262 conforming script
engine implementation running in a browser where named form controls were
being referred to by like-named properties of the global object. The spec
says that when variable instantiation acts on the variable declaration in -
var usevar = 12; - it must not alter the value of any pre-existing property
of the Variable object named 'usevar', the global object is the Variable
object in the global execution context, the - usevar - property it has
already has a value which refers to the form control's DOM element, and the
exception being thrown prevent the evaluation of the assignment to the -
usevar - variable. The observed outcome corresponds 100% with the expected
outcome in the environment in question.

So your point was? That is; what was this supposed to demonstrate, and how
did the outcome demonstrate it?

(Well that did not modify my opinion of your analytical abilities when it
comes to browser scripting).

So-

Menu = function() {

}

-
would be something you would have to avoid.

No of course not. Either the variable should be declared or the whole thing
should be a function declaration. The latter would be my choice here, as
there is a great deal to be said for doing the simple and obvious in scripts
whenever you have the choice.
Because it could be that theres'

<div id="Menu"></div>

on the page.

Which won't make one jot of difference to a FunctionDeclaration. Even the
question of modifying pre-existing properties of the Variable object does
not arise in the case of the FunctionDeclaration as they are supposed to
re-assign values to any pre-existing properties their names conflict with.
<snip>

[snip]

Pretty much, except that conceptually the thing being gotten
is an Interfaces not Objects.

Strategy/Adapter, huh?
What?

I use strategy in a different code style.

Just the one?
That's subject matter for another thread.



Link?

Advances search on google groups?
Avg 560 lines/file, which is not too unreasonable,

But not that representative given the range.
but building
javascript between QA phases? Why?

Because it is not uncommon for things to cycle back into development from
the fist QA phase, so there smaller, more desecrate, chunks have advantages.
(There is also the version control system to be contended with as if a bug
fix or an enhancement has a client-side script file attached to it that file
is locked out for any unrelated modification until QA have OKed it. If there
were only a few large files in the development environment it would be every
easy for them all to become locked out at once, and leave far too many
people sitting around twiddling their thumbs. (or, heaven forbid, catching
up with the documentation backlog ;-))

It is essential that the client-side code goes through full QA regression
testing following any global modification in its structure. As phase two is
regression testing of builds, between phase one and two is the last
opportunity to amalgamate the client-side code files.

Richard.
 
D

dhtml

[snip]
I don't want to talk about it much,

Uh huh.

and I can think of many better People to
talk about it with in the event that I did (and some worse, e.g. VK).

What makes a person better than another? Feel free to base your answer
on criterion of your choice, e.g. existential, ethical.

[snip]

We've got at least three different things in this thread, including
namespacing, variable declaration, and your project (150k lines js).
I'll come back to those.

Garrett
 
R

Richard Cornford

dhtml said:
On Feb 24, 11:51 am, Richard Cornford wrote:
[snip]
I don't want to talk about it much,

Uh huh.

and I can think of many better People to
talk about it with in the event that I did (and
some worse, e.g. VK).

What makes a person better than another?

The likely hood that something substantial or conclusive will come out of
the exchange. Some people can make observations, devise tests and apply
reasoning, in which interesting truths are revealed, while at the other end
of the spectrum there a people who will just make a noise to no purpose.
Feel free to base your answer
on criterion of your choice, e.g. existential, ethical.
<snip>

My criteria are the likelihood that I (or at least somebody) will learn
something in the process, and the entertainment value that is the return for
the effort put in.

Richard.
 
D

dhtml

dhtml said:
On Feb 24, 11:51 am, Richard Cornford wrote:
[snip]
I don't want to talk about it much,
and I can think of many better People to
What makes a person better than another?

The likely hood that something substantial or conclusive will come out of
the exchange. Some people can make observations, devise tests and apply
reasoning, in which interesting truths are revealed, while at the other end
of the spectrum there a people who will just make a noise to no purpose.

All positive traits for a javascript-group-poster.

I did find odd that you chose to mention and even capitalize People.
The emphasis came through and I think I got it.

The other one - function decollation. Strange. Decollation means
'beheading', in case you didn't know. And yeah, that was my mistake -
I wrapped the 'thing that chopped my head off' in a try-catch. Thanks.

I want to get back to the other stuff in the thread. I think there's
more to the global Variable object and properties. I'll need some
tests, which don't come free - that will take time.

Regarding strategy and interfaces - I'd like to talk about that too.
I'd like to see the code technique for critique. I can share how I use
strategy/adapter, too, but maybe in another thread.

Garrett
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,905
Latest member
Kristy_Poole

Latest Threads

Top