why don't you have to declare variables in javascript?

A

Andy Fish

Hi,

can anybody put forward a sensible argument javascript's behaviour of
creating a new global variable whenever I assign to a previously undeclared
variable. I can't beleive this is just for the sake of convenience (surely
we learned this much from basic).

here's my proposal: all "global" (document scope) variables must be declared
by 'var' outside a function block.

failing that, does anyone know any patterns or tricks I can use to make sure
I don't create a new global variable when I accidentally misspell a variable
name?

Andy
 
L

Lasse Reichstein Nielsen

Andy Fish said:
failing that, does anyone know any patterns or tricks I can use to make sure
I don't create a new global variable when I accidentally misspell a variable
name?

Use JSLint on your code. It enforces pretty code and reports all local and
global variables used. Any unrecognizable global variable would be a typo.
<URL:http://www.crockford.com/javascript/jslint.html>

/L
 
Y

Yep

Andy Fish said:
can anybody put forward a sensible argument javascript's behaviour of
creating a new global variable whenever I assign to a previously undeclared
variable. I can't beleive this is just for the sake of convenience (surely
we learned this much from basic).

Well I don't know the why, ECMA offers some interesting argument with
object-orientation, I'll give some details below - see if this makes
sense, decide whether the "var" keyword is useful, and skip if bored
:)

So, Javascript is object-oriented, and variable instantiation
participates of this logic. To fully understand why you have obtained
the described behavior you need to get familiar with the the Variable
Object (10.1.3) and the Reference Object (8.7).

The "short" version is as follows. When entering a specific execution
context (global code, function code), there is a so-called Variable
Object, which holds references to all variables and functions defined
in the context. To put it another way, declaring a variable using the
"var" keyword adds the variable as a property of this Variable Object.

The Variable object in use depends on the type of code; for function
code, this is the Activation Object (of which "arguments" is a
property); for global code, this is the Global Object, i.e. an object
created before any exuction context is entered, and holding all global
variables and properties (such as Math, Date etc...) - in HTML, the
"window" object refers to this global object (you can also use the
"this" keyword); for Eval Code, it depends on the calling context.

Now, what if you don't use the "var" keyword? The answer is that you
don't really make a variable declaration. Consider the following
statement:

function f() {
a = 3;
}

We have an assignment, so according to ECMA 11.13.1 the following is
executed

1. Evaluate LeftHandSideExpression.
2. Evaluate AssignmentExpression.
3. Call GetValue(Result(2)).
4. Call PutValue(Result(1), Result(3)).
5. Return Result(3).

LeftHandsideExpression is "a", AssignmentExpression is "3". So before
putting the value "3" in "a", "a" is evaluated. This is done as
follows (Identifier Resolution, 10.1.4):

1. Get the next object in the scope chain. If there isn't one, go to
step 5.
2. Call the [[HasProperty]] method of Result(1), passing the
Identifier as the property.
3. If Result(2) is true, return a value of type Reference whose base
object is Result(1) and whose property name is the Identifier.
4. Go to step 1.
5. Return a value of type Reference whose base object is null and
whose property name is the Identifier.

As you can see, step 1 to 4 are iterated until there is no more object
in the scope chain, which could match the propertyName "a". So step 5
is executed, that is, a Reference with a "null" base is provided for
the assignment expression.

A Reference is simply a reference to a property of an object. It
consists in two components, the base object, and the property name; as
you've seen, the result of evaluating an identifier is always a value
of type Reference (either because it's found, or because it's not
found).

When in the assignement expression, JS tries to put a value to the
reference, using:

PutValue (V, W)
1. If Type(V) is not Reference, throw a ReferenceError exception.
2. Call GetBase(V).
3. If Result(2) is null, go to step 6.
4. Call the [[Put]] method of Result(2), passing GetPropertyName(V)
for the property name and W for the value.
5. Return.
6. Call the [[Put]] method for the global object, passing
GetPropertyName(V) for the property name and W for the value.
7. Return.

If you look closely at the algorithm, you'll see the step 2 will
return null, since the Reference "a" doesn't have any object behind.
Therefore, step 6 is executed, and the property is declared directly
on the Global Object - that is, declaring a variable without using the
var keyword will result in the variable being global.
here's my proposal: all "global" (document scope) variables must be declared
by 'var' outside a function block.

That makes sense, but the more you'll program in javascript, the more
you'll use advanced scoping to build your scripts, the less you'll
have global variables (in js you can even run a full script without
one global variable, using an anonymous function expression).


HTH
Yep.
 
C

Charles Banas

That makes sense, but the more you'll program in javascript, the more
you'll use advanced scoping to build your scripts, the less you'll
have global variables (in js you can even run a full script without
one global variable, using an anonymous function expression).
sorry to sound n00bish, but i've seen a script use a function() expression
to create functions as it executes. i was actually quite surprised by how
it worked. is that what you're talking about?

i don't recall the details, but its syntax was like this:

function("name", "code", var1, var2, var3, ... , varn);
where "name" was the name of the function, "code" was the complete contents
of the function as a string expression, and var1 - varn were the parameters
passed to it.

i'd appreciate finding out more about this, because i've only seen it used
once, and i wanted to take advantage of it.
 
R

Richard Cornford

sorry to sound n00bish, but i've seen a script use a function()
expression to create functions as it executes. i was actually
quite surprised by how it worked. is that what you're talking
about?

An anonymous function expression takes the form:-

function(){
. . . //function body goes here!
}

- and can be executed inline by adding a parenthesised argument list
(possibly empty) to the end of the function expression:-

(function(){
... //function body goes here!
})();

- I have parenthesised the above function expression itself, which seems
to make it clear that the contents of the first set of parentheses
resolves to a (reference to a) function object which is then executed.
Those first parentheses are not required.

I recently posted a (well, several versions of a) script that is nearly
totally anonymous in a thread with the subject: 'Netscape 7 struggling
with script' (started 2003-08-09). With the exception of one global
property that is created with the sole aim of providing fall-back for
browsers that do not understand a function reference as the first
argument to the setTimeout function (e.g. Opera 5 and IE 4), that script
has no public interface, makes no impact on the global environment and
is inaccessible to other scripts. Yet it does quite a lot within itself.
i don't recall the details, but its syntax was like this:

function("name", "code", var1, var2, var3, ... , varn);
where "name" was the name of the function, "code" was the complete
contents of the function as a string expression, and var1 - varn
were the parameters passed to it.
<snip>

That looks like the global - Function - constructor, which takes the
function body (and optional arguments/arguments list) as a string:-

new Function('arg1, arg2', 'return (arg1 * arg2);');

- and creates a new function object (with global scope). It can also be
called just after the creation of the function object:-

var valOfForty = (new Function('arg1, arg2', 'return (arg1 *
arg2);'))(8, 5);

- but the Function constructor is generally only useful if the function
body string is to be built dynamically at run time. Otherwise standard
function expressions are preferable.

Richard.
 
A

Andy Fish

well, I hear your argument but I'm not convinced by it.

I think if js programmers had been forced to declare global variables from
the beginning they would have no choice but to accept it and IMHO that would
not have hindered the uptake of js. From what I have read in other replies
there is no technical reason why this couldn't be enforced.

obviously I realise that there is no realistic chance of it changing now
though :(
 
R

Richard Cornford

There's also the case of it generating syntax errors in early
JS browsers on load, with new Function you avoid these,
(which is why the fact dynwrite uses new Function constructors).

That's not too much of a problem in reality...

I take it then that "early JS browsers" means very early and so probably
not still in use. The version 4 era browsers seem generally OK with
function expressions. Konqueror 2 doesn't like inner function
declarations (and may not like anonymous function expressions executed
inline) but it is close to impossible to get it to report errors, so at
least it fails quietly, and Konqueror 3 seems to have fixed the problem.

And then there is Avant Go, with its lack of a working Function
constructor (because it has no onboard eval).

Still, if every script is expected to fail somewhere and the
consequences of failure have been planed for and are still usable, then
either choice won't be too bad.

Richard.
 
J

Jim Ley

I take it then that "early JS browsers" means very early and so probably
not still in use.
Yes!

And then there is Avant Go, with its lack of a working Function
constructor (because it has no onboard eval).

Yep, but as long as it's not a syntax error it can be protected
through other means...
Still, if every script is expected to fail somewhere and the
consequences of failure have been planed for and are still usable, then
either choice won't be too bad.

My problem with syntax errors is that they can't be silently failed
on, so the user will likely still see an error, which is annoying, but
probably not serious now with the few browsers that have problems with
a=function() { } etc. syntax.

A rewrite of 4.15 in the FAQ with this in mind would probably be good.

Jim.
 
S

Simon Wigzell

Andy Fish said:
Hi,

can anybody put forward a sensible argument javascript's behaviour of
creating a new global variable whenever I assign to a previously undeclared
variable. I can't beleive this is just for the sake of convenience (surely
we learned this much from basic).

here's my proposal: all "global" (document scope) variables must be declared
by 'var' outside a function block.

failing that, does anyone know any patterns or tricks I can use to make sure
I don't create a new global variable when I accidentally misspell a variable
name?

Andy
I agree with Andy. As someone who started programming with Basic in 1986
where variables did not be declared it was a huge improvement to step up to
C. I could appreciate that declaring variables forced you to think more
carefully and plan out your program rather than just hacking it out.

I have 2 more gripes :

Why is the semi-colon at the end of a statement optional? Either it should
need one or not, optional makes no sense.

Why don't javascript programmers indent properly? How can they follow their
own code? I use a lot of free stuff off the internet and I appreciate it
greatly but if I ever have to modify or debug it my first task is to
re-indent the whole thing!

Yeah, javascript with a few additions could be a real language and not just
a hackers mess.
 
R

Richard Cornford

Why is the semi-colon at the end of a statement optional?
Either it should need one or not, optional makes no sense.

It is not optional to the interpreter, it is just possible for the
parser to apply rues that insert the semi-colons in the right places.
But being able to omit the semi-colons from source code is not a reason
for actually doing so.
Why don't javascript programmers indent properly? How can
they follow their own code?

JavaScript programmers do indent their code. All programmers of C-style
languages indent their code because failing to do so does make the
results difficult to follow. Amateurs and people used to languages that
cannot be indented may not do so, at first anyway. But code encountered
in association with web pages may not be development code, measures may
have been taken to reduce the download size, and a quick search and
replace to remove tabs would be very quick in return for no harmful side
effects.

Indenting "properly" is another matter entirely. There are several
styles on indenting and some of the adherents to any one may insist that
theirs is the only one that is "proper".

It is also worth noting, in relation to newsgroup postings, that my
newsreader is in the habit of collapsing tabs. Meaning that, if I post
tab-indented code the resulting post will not be indented. Being
familiar with that behaviour I usually remember to convert tabs to
spaces prior to copying code into the newsreader. But you cannot always
remember and people unfamiliar with the behaviour will be caught out at
leas the first time it happens.
I use a lot of free stuff off the internet and I appreciate
it greatly but if I ever have to modify or debug it my
first task is to re-indent the whole thing!

So it has not occurred to you that the quality of the source code you
find for free on the internet might be related to the quality of the
scripts it defines?
Yeah, javascript with a few additions could be a real language
and not just a hackers mess.

In C and Java indenting is optional (very advisable but still optional)
and a compiler for either could be written that applied automatic
semi-colon insertion. Such a compiler will not be written because no one
wants to encourage programmers to be sloppy. But being able to code
sloppily in JavaScript is not a reason for doing so.

Richard.
 
A

Andy Fish

the only reason I can think of for the semicolons is that if you made them
mandatory, you would probably have to put them at the end of a function
definition as well e.g.

function foo () {
...blah
};

as for indentation, don't forget that a lot of javascript comes from JSP or
ASP pages or even XSLT stylesheets. In the source files for these you
effectively have two languages colocating in the same file and the developer
often (rightly) gives preference to the "host" language for indentation.

Andy
 

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,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top