essay on jibbering says that variable instantiation is done for all local variables of a function?

J

Jake Barnes

I saw this sentence:

"The last stage of variable instantiation is to create named properties
of the Variable object that correspond with all the local variables
declared within the function."

here:

http://jibbering.com/faq/faq_notes/closures.html


How can that sentence be right? Javascript is an interpreted language
that executes one line at a time. But that sentence sound like all the
variables in a function get set up before the function begins to
execute.
 
V

VK

Jake said:
I saw this sentence:

"The last stage of variable instantiation is to create named properties
of the Variable object that correspond with all the local variables
declared within the function."

here:

http://jibbering.com/faq/faq_notes/closures.html


How can that sentence be right? Javascript is an interpreted language
that executes one line at a time.

You need to rethink your concept as it is not true.
But that sentence sound like all the
variables in a function get set up before the function begins to
execute.

And this is true.
 
V

VK

VK said:
You need to rethink your concept as it is not true.


And this is true.

After reading it once over: I was wrong.

That article puts together two very different processes: memory
allocation and variable instantiation, this is where the confusion
arises (because in the article it's always called "instantiation").

Memory allocation takes place during the initial script load. Script
source is being passed through the parser and divided on tokens. All
declared functions, objects and variables are being found, memory heaps
are being prepared, references to memory heaps are being forwarded to
the script context. It all happens during the script load, not during a
function call.
When the allocation process is finished, JScript fires "load" event
which is very nice of it :) I'm missing it terribly in Firefox
JavaScript.

Memory allocation mechanics ("on load", not "on call") can be
demostrated on this DOA (Dead On Arrival) dummy function:

<html>
<head>
<title>Allocation != Instantiation</title>
<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1">
<script type="text/javascript">
void function dummy(args) {
alert('Booh!');
}

window.onload = dummy;
</script>
</head>

<body>
</body>
</html>


Function dummy is being parsed and allocated on script load, but void
operator prevents the script context to get a reference on the
allocated memory heap. So it becomes garbage collector ready right
away.

Allocation happens on script load.

Function arguments instantiation happens on function call, before
executing function body.

Function variables instantiation happens in the execution order.

With these adjustments the article is perfectly correct.
 
L

Lasse Reichstein Nielsen

Jake Barnes said:
Javascript is an interpreted language that executes one line at a
time.

While execution of code does happen one *statement* at a time, just as
any other language without parallel threads, it doesen't mean that
everything else in the language doe the same, nor that the statements
are always taken from top to bottom (that's why we have control flow
operators like "while" and "continue").
But that sentence sound like all the variables in a function get set
up before the function begins to execute.

It is correct that when a function is called, the specification calls
for all variables declared in the function body (and not inside bodies
of nested functions, just to be pedantic) must be created as properties
of the variable object, before execution of the statements in the body
begins (and after all function declarations have been processed).

The pertienent part of the specification (ECMAScript standard -
ECMA262 3ed) is section 10.1.3 ("Variable Instantiation").

/L
 
L

Lasse Reichstein Nielsen

VK said:
Memory allocation mechanics ("on load", not "on call") can be
demostrated on this DOA (Dead On Arrival) dummy function: ....
void function dummy(args) {
alert('Booh!');
}

window.onload = dummy; ....
Function dummy is being parsed and allocated on script load,

The script block is being executed, not just parsed. You can do
anything in the block, including creating a billion objects,
assuming your computer has the memory to hold that many.
but void operator prevents the script context to get a reference on
the allocated memory heap.

It is not the void operator that prevents anything. The function
expression that provides its operand is just that: a function
expression. The name, "dummy", only has scope inside the function's
body, so there is no way the "dummy" variable being read later
in the global scope can refer to the function by that name.
You would get the same effect by writing:
(function dummy(args){}); // you miss a ; after the void expression
window.onload = dummy;
or even
(function notdummy(args){});
window.onload = dummy;

So it becomes garbage collector ready right away.

Sure it does, just as if you had written:

new Object();
window.onload = dummy;

The object being created has no reference pointing to it, so
it cannot be referred to again by any other part of the script.
So, nobody will notice if it isn't there, so you can garbage
collect it.
Allocation happens on script load.

I am sure that some memory allocation happens while the script is
being parsed, but the memory allocation you seem to be talking
about happens when the script is *executed*.
Function arguments instantiation happens on function call, before
executing function body.
Yes.

Function variables instantiation happens in the execution order.

Not sure what that means.

/L
 
V

VK

Lasse said:
You would get the same effect by writing:
(function dummy(args){}); // you miss a ; after the void expression
window.onload = dummy;

It wouldn't give this effect: parenthesis simply define *operator
execution precedence* like (1+2)*3

(function dummy(args){}); means "execute function definition first,
then the rest". As the "rest" is not presented, parenthesis usage here
is not really necessary.

Function "dummy" is still properly parsed, allocated and *referenced*.

For some reason it breaks though the proper execution on FF and (as it
seems) on Opera. They don't see "dummy" if parenthesis are used. There
is nothing in ECMAScript specifications to endorse it, so it must be a
bug to report (if it's not reported yet). IE acts properly:

<html>
<head>
<title>Allocation != Instantiation</title>
<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1">

<script type="text/javascript">

(function dummy(args){alert('OK');});

function init() {
dummy(); // shows "OK" alert
}

window.onload = init;
</script>
</head>
<body>
</body>
I am sure that some memory allocation happens while the script is
being parsed, but the memory allocation you seem to be talking
about happens when the script is *executed*.

My bad!
Not sure what that means.

Something like:

function f() {
alert(foo); // undefined
var foo = 'bar';
alert(foo); // 'bar'
}
 
V

VK

VK said:
It wouldn't give this effect: parenthesis simply define *operator
execution precedence* like (1+2)*3

(function dummy(args){}); means "execute function definition first,
then the rest". As the "rest" is not presented, parenthesis usage here
is not really necessary.

Function "dummy" is still properly parsed, allocated and *referenced*.

For some reason it breaks though the proper execution on FF and (as it
seems) on Opera. They don't see "dummy" if parenthesis are used. There
is nothing in ECMAScript specifications to endorse it, so it must be a
bug to report (if it's not reported yet). IE acts properly:

Yes, very interesting. Somehow Mozilla engine chokes on parenthesis.
Maybe bacause it cannot hadle properly a statement where "operator
precedence parenthesis" and "function formal arguments parenthesis" are
used together (just my speculation).

I'm going to look at Bugzilla if it was reported. If not you'll use the
code I posted here as testcase for this bug.
 
L

Lasse Reichstein Nielsen

VK said:
It wouldn't give this effect: parenthesis simply define *operator
execution precedence* like (1+2)*3

Did you try it?

But you are right. Parentheses are used to override precendence of
operators in expressions.
And that's the point. By adding them, the result becomes an expression,
not a function declaration. Function expressions does not expose
their function names to the surrounding scope, and since the value
isn't captured anywhere either, there is no reference to the function
object created.

(function dummy(args){}); means "execute function definition first,
then the rest". As the "rest" is not presented, parenthesis usage here
is not really necessary.

It means "evaluate function expression". Had they not been there, the
parser would have parsed it as a function declaration, an entirely
different syntactic category, with quite a different semantics.
Function "dummy" is still properly parsed, allocated and *referenced*.

No reference is created to the anonymous (well, anonymous on the
outside) function. It is free to be garbage collected.

Had it been a function declaration, it would have created a property
of the variable object of the same name, referencing the function
object.
For some reason it breaks though the proper execution on FF and (as it
seems) on Opera. They don't see "dummy" if parenthesis are used. There
is nothing in ECMAScript specifications to endorse it,

Oh, absolutely. You don't think I came up with the idea myself, do you?

But for completeness:

FunctionDeclaration and FunctionExpression are defined in section 13.
Checking the semantics, you can see that only a FunctionDeclaration
adds a property to the current variable object, whereas
FunctionExpression with an identifier creates a new level on the scope
chain to hold the identifier, one that is only visible for the body
of the function, not outside. This is spelled out in the "NOTE".
so it must be a bug to report (if it's not reported yet).

No, it's behavior consistent with the ECMAScript standard.

Typically, when Gecko and Opera agree on something, and IE doesn't,
it's a safe bet that it's IE that isn't in compliance with the
standard.
IE acts properly:

.... as usual, when properly is defined as "what IE does" :)
Something like:

function f() {
alert(foo); // undefined

Uninitialized, but already existing! Had you written "alert(bar)", you
would have gotten an exception for using a non-existing variable.
var foo = 'bar';
alert(foo); // 'bar'
}

It is as if all variable declarations (i.e., the "var variablename")
in the function body were at the top of it. Assignments to the
variables, including those part of a variable declaration statement,
are executed in the order they are reached. So, the above function
is equivalent to:

function f() {
var foo;
alert(foo);
foo = 'bar';
alert(foo);
}

or even

function f() {
alert(foo);
foo = 'bar';
alert(foo);
var foo;
}


/L
 
V

VK

Lasse said:
Parentheses are used to override precendence of
operators in expressions.
And that's the point. By adding them, the result becomes an expression,
not a function declaration. Function expressions does not expose
their function names to the surrounding scope, and since the value
isn't captured anywhere either, there is no reference to the function
object created.

Oooh... Just read ECMA-262, chapter 13. Thank you for pointing and
explaining. That's deep...
Not sure what the original purpose of it was (first attempt to
implement private/protected scopes?) but now I understand this recent
parenthized stuff I've seen here and there.

Unfortunately JScript goes by its own more primitive schema: "function
foo() {}" is defined as *statement*. The result of this statement
execution is function reference forwarded to the surrounding scope. No
amount of parenthesis affects on it.

I see some interesting usage for FunctionDeclaration vs.
FunctionStatement behavior... as soon as the number of IE users will be
negligeable small :)
FunctionDeclaration and FunctionExpression are defined in section 13.
Checking the semantics, you can see that only a FunctionDeclaration
adds a property to the current variable object, whereas
FunctionExpression with an identifier creates a new level on the scope
chain to hold the identifier, one that is only visible for the body
of the function, not outside. This is spelled out in the "NOTE".

Thanks again for pointing and explaining it so nicely and clearly.
 
J

Joaquin Cuenca Abela

VK said:
Not sure what the original purpose of it was

The purpose is to be able to make a recursive function expression. When
you don't need recursivity, you usually use an anonymous function
expression.

Cheers,
 
T

Thomas 'PointedEars' Lahn

Joaquin said:
The purpose is to be able to make a recursive function expression. When
you don't need recursivity, you usually use an anonymous function
expression.

Non sequitur. The `arguments.callee' property allows recursion even for
anonymous functions.


PointedEars
 
J

Joaquin Cuenca Abela

Non sequitur. The `arguments.callee' property allows recursion even for
anonymous functions.

Having a named function expression allows much more readable recursive
function expressions than using arguments.callee. That's the purpose of
named function expressions.

The arguments property also allows access to the arguments in the
function, but nobody would dispute that traditional named function
arguments are there to allow access to the function arguments, even if
they're not the only mean to access them.
 
T

Thomas 'PointedEars' Lahn

Joaquin said:
Having a named function expression allows much more readable
recursive function expressions than using arguments.callee.

That is debatable; I think it is merely a matter of getting used
to it. However, source code using arguments.callee is definitely
easier to maintain as you only have to change the identifier once
there.
That's the purpose of named function expressions.

It is certainly /one/ purpose. However, your argument was that the
identifier for the FunctionExpression is required to make recursive
calls:

,-[news:[email protected]]
|
| VK wrote:
| > Not sure what the original purpose of [named FunctionExpressions] was
|
| The purpose is to be able to make a recursive function expression. When
^^^^^^^^^^^^^
| you don't need recursivity, you usually use an anonymous function
| expression.

That was refuted by me.
The arguments property also allows access to the arguments in the
function, but nobody would dispute that traditional named function
arguments are there to allow access to the function arguments, even
if they're not the only mean to access them.

I am sure someone would. For example, using the arguments object (and
its `length' property) allows for processing an "infinite" number of
arguments of a method, while using named arguments only does not as you
cannot name (or would probably resist to name), and (to) code for, this
many arguments.

BTW: Please provide attribution of quoted material.


PointedEars
 

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

No members online now.

Forum statistics

Threads
473,996
Messages
2,570,238
Members
46,826
Latest member
robinsontor

Latest Threads

Top