Re: pseudo-namespacing in JavaScript



dhtml wrote:
On Feb 23, 10:03 am, Richard Cornford wrote:
dhtml wrote:
On Feb 22, 5:31 am, Richard Cornford wrote:
Peter Michaux wrote:
I've been thinking about this more for a library API.

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:-

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.)

- 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.

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.

Outputting 'undefined here is an IE bug, because ...
<snip>
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
<snip>
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.

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.

<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.

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.

The locations of SCRIPT elements within a document has no baring on the
presence or absence, or relative location of, global variable declarations.

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.

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.

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()

Maybe, but it is pretty closed for a quick summation of the situation.

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();

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).

<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.

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]


What's that?

function getMyObject() {

}

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.


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

Link?

Advances search on google groups?

How many files?

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 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.
--
"Compression should be used as the final step, just before putting your code
into production, as your code will frequently become obfuscated beyond
recognition." - John Resig: Pro JavaScript Techniques. 2006


.



Relevant Pages

  • Re: Function not defined problem
    ... thought that once a function is called, the script will find it ... While resolution proceeds from top top bottom ... declarations are resolved before any code is executed. ... processed first, then execution begins. ...
    (comp.lang.javascript)
  • Go ahead. Stop programming. This ensures you from any mistakes.
    ... declarations, ... All normal languages obey it ... right away from simplicity. ... of instruction execution. ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: IE javascript bug: global variable
    ... Global variable declarations result in properties of the ... actual execution of code in that context. ... That's another aspect of this bug that puzzles me; ... both variable instantiation and actual code ...
    (comp.lang.javascript)
  • Re: =function(){...}
    ... function identifier() { ... are parsed into function objects before execution begins. ... Function expressions are different in that they only create function objects /if/ they are evaluated. ... That is, global function declarations are parsed immediately, but inner functions are only parsed when their outer function is called. ...
    (comp.lang.javascript)
  • Re: One-time variable definition
    ... make this assignment at the first opportunity of having the value ... Public strProbNo as String ... Microsoft IT Academy Program Mentor ... I would rather declare it once in the Declarations section or ...
    (microsoft.public.access.formscoding)

Loading