[newbie] Q on var declaration

T

Takehiko Abe

I wrote this function, and it did not work [went into
infinite loop]

function map_node (root, f)
{
f(root);
for (i = 0; i < root.childNodes.length; i++) {
map_node(root.childNodes, f);
}
}

Then, I put the 'var' in front of 'i', and it worked
as expected.

function map_node (root, f)
{
f(root);
for (var i = 0; i < root.childNodes.length; i++) {
map_node(root.childNodes, f);
}
}


It appears to me that, without 'var' keyword, 'i' behaves
like a global variable inside the function. I searched on
the net regarding the usage of 'var' and found that some
docs says 'var' is optional, but I couldn't find any
info about the possible difference when 'var' is ommited
and when 'var' is used. I appreciate if someone can shed
a light on the difference.

TIA
Takehiko Abe
 
M

Michael Winter

Takehiko Abe wrote:

[snip]
It appears to me that, without 'var' keyword, 'i' behaves like a
global variable inside the function.

Indeed it does.
I searched on the net regarding the usage of 'var' and found that
some docs says 'var' is optional, [...]

The var keyword isn't necessary when creating a global variable.
Simply assigning to an identifier that doesn't appear in the scope
chain (explained later) will create and initialise a property on the
global object. However, the var keyword is mandatory when creating
local variables. I'm of the opinion that the var keyword should always
be used, whether a local or a global variable is being declared.
I couldn't find any info about the possible difference when 'var'
is ommited and when 'var' is used.

A variable declaration behaves in two ways, based on where it is
encountered. A declaration at global scope creates a property on the
global object, whereas a declaration within a function creates a
property on the variable object of that function's execution
context[1] (in other words, a local variable).

When an identifier is encountered, the ECMAScript implementation must
resolve the location of that identifier. It does this by searching the
scope chain - a list of objects beginning at the global object, and
extended through the creation of functions[2]. If the identifier
cannot be found in the variable object (so it's not a local variable),
the next object in the scope chain is searched. If that object doesn't
contain the identifier, the next object is searched. This continues
until finally the global object is reached. If it's still not found,
then either a new property is created on the global object (for
assignments), or an error occurs (for value look-ups).
I appreciate if someone can shed a light on the difference.

Hopefully, there's something useful in there. The first three
paragraphs contain most of the information you're looking for. The
paragraph above, and the footnotes below, go into much more depth and
complete the description.

Mike


[1] Whenever a function is called, a new execution context is created.
The execution context can be thought of as the state of that
function as it holds various bits of information used during
execution, including: the scope chain, used to resolve
identifiers; the activation/variable object, containing the
arguments object, formal arguments (parameters) defined by the
function, local variables, and nested function declarations; and
the this operator value.

[2] When functions are declared, an internal [[Scope]] property is
created. When the function is called, and its execution context
entered, the activation/variable object is added to the [[Scope]]
property, and this chain of objects becomes the scope chain for
the function.
A function declared at global scope will only have the global
object in its [[Scope]] property. This means that only the
local variables, functions, and formal arguments of its
activation/variable object, and the properties of the global
object will be accessible.
A function declared within another function will have the
complete scope chain of the outer function in its [[Scope]]
property. This will include not only the global object, but
also all of the local variables, functions, and formal
arguments of its parent. For example,

function A(arg) {
var local = 'bar';

function B() {
alert(arg); // 'foo'
alert(local); // 'bar'
}

B();
}
A('foo');

When A is called with argument 'foo', the ECMAScript
implementation will create the function object for B, and the
variable, local, with value 'bar'. When B is called, it will
have access to these local variables as the activation/variable
object of A is part of its scope chain.
 
M

Mick White

Takehiko said:
I wrote this function, and it did not work [went into
infinite loop]

function map_node (root, f)
{
f(root);
for (i = 0; i < root.childNodes.length; i++) {
map_node(root.childNodes, f);
}
}

Then, I put the 'var' in front of 'i', and it worked
as expected.

function map_node (root, f)
{
f(root);
for (var i = 0; i < root.childNodes.length; i++) {
map_node(root.childNodes, f);
}
}


It appears to me that, without 'var' keyword, 'i' behaves
like a global variable inside the function. I searched on
the net regarding the usage of 'var' and found that some
docs says 'var' is optional, but I couldn't find any
info about the possible difference when 'var' is ommited
and when 'var' is used. I appreciate if someone can shed
a light on the difference.


The "var" identifier is not required (nor do I recommend it) for global
variable assigment.
M
 
M

McKirahan

[snip]
The "var" identifier is not required (nor do I recommend it) for global
variable assigment.
M

So you wouldn't use "var " in the following?

<script type="text/javascript">
var i = 0;
function test() {
alert(i++);
}
</script>

Why don't you recommend it?

I prefer to declare (with "var ") all my variables.
 
T

Takehiko Abe

Michael Winter said:
[...] However, the var keyword is mandatory when creating
local variables.

Aha! I saw some JavaScript codes that doesn't use 'var' for local
variables. (I guess they are old.)
[...]

When an identifier is encountered, the ECMAScript implementation must
resolve the location of that identifier. It does this by searching the
scope chain - a list of objects beginning at the global object, and
extended through the creation of functions[2]. If the identifier
cannot be found in the variable object (so it's not a local variable),
the next object in the scope chain is searched. If that object doesn't
contain the identifier, the next object is searched. This continues
until finally the global object is reached. If it's still not found,
then either a new property is created on the global object (for
assignments),

I see. I misunderstood the last part. I thought there were three kind
of variables: 1. global 2. local (to function) 3. local-global hybrid
(created by an assignment to an identifier inside a function definition
without 'var' keyword.) The third one is the one I imagined wrongly.
or an error occurs (for value look-ups).


Hopefully, there's something useful in there.

Yes, it is very helpful.
[...]

A function declared within another function will have the
complete scope chain of the outer function in its [[Scope]]
property. This will include not only the global object, but
also all of the local variables, functions, and formal
arguments of its parent.

Actually I wanted this feature. Very nice.

Thanks a lot.
Takehiko Abe
 

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,764
Messages
2,569,564
Members
45,039
Latest member
CasimiraVa

Latest Threads

Top