Block-level variables in JavaScript

V

VK

Just wanted to clear it out.
AFAICT ECMA 3rd ed. JavaScript has at least one classical block level
variable: the one generated for the catch{} block

<html>
<head>
<title>Untitled Document</title>
<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1">
<script type="text/javascript">

function init() {
// no "var" so creating new global variable "a"
// from within the function:
a = new Object;

try {
throw new Error('foobar');
}
// no "var" so should be the same schema
// for "b" as for "a"
catch(b) {
window.alert(typeof b); // 'object'
/*NOP*/
}
window.setTimeout('demo()', 100);
}

function demo() {
window.alert(typeof a); // 'object'
window.alert(typeof b); // 'undefined'
}
window.onload = init;
</script>
</head>
<body>
</body>
</html>
 
P

Peter Michaux

Just wanted to clear it out.
AFAICT ECMA 3rd ed. JavaScript has at least one classical block level
variable: the one generated for the catch{} block

If a "block" is a series of statements that can go in braces then the
arguments to a function and the "arguments" object are "block level"
and so are all the variables declared with "var" inside the function
body.

Peter
 
V

VK

If a "block" is a series of statements that can go in braces then the
arguments to a function and the "arguments" object are "block level"
and so are all the variables declared with "var" inside the function
body.

With such broad interpretation of "block-level scope" indeed. I would
prefer more narrow and lesser - IMHO - confusing definition of a block-
level variable as a variable with lifetime within the inner execution
block, same what rather ugly has been tried to implement in
JavaScript1.7 over let:

Yes, we can consider function(){ } as an execution block and then "a"
in
function f() {
var a = 'foo';
}
as a case of block-level variable. Such terminology would confuse
though many programmers because stating that JavaScript has "block-
level variables" would may them ask about "i" in say
function f() {
for (var i=0;;) {
break;
}
alert(typeof i); // 'number'
}
// as it is a block-level variable as well, but it is visible withing
the whole function block, not only inside its own inner for() block.
This is why I do agree with the current Wiki text saying that
"Javascript has function level scoping rather than block level
scoping" http://en.wikipedia.org/wiki/JavaScript

Going back to my original question I see that I misinterpreted the
engine behavior for the argument in catch(){} block.

<script type="text/javascript">
function init() {
a = new Object;
try {
throw new Error('foobar');
}
catch(b) {
window.alert(typeof b); // 'object'
/*NOP*/
}
/* Catch block argument remains even after
exiting from the catch block:*/
window.alert(typeof b); // 'object'
window.setTimeout('demo()',100);
}

/* Catch block argument gets released
only after exiting the function block:*/

function demo() {
window.alert(typeof a); // 'object'
window.alert(typeof b); // 'undefined'
}
window.onload = init;
</script>

So no, "b" in this sample is not a block-level variable in the sense I
described.
 
R

RobG

Just wanted to clear it out.
AFAICT ECMA 3rd ed. JavaScript has at least one classical block level
variable: the one generated for the catch{} block

I think you are wrong - catch is defined in ECMAScript Language
Specification, section 12.14. There is no mention what-so-ever of
"block level scope".

Scope in javascript is associated with an execution context and its
scope chain, not with block statements per se other than the fact that
block statements are used to define function objects and hence affect
the scope chain.

The catch statement has no scope of its own, nor does it have one by
virtue of its body being enclosed in a block.

From the ECMAScript spec:

The production TryStatement : try Block Catch is evaluated as
follows:

1. Evaluate Block.
2. If Result(1).type is not throw, return Result(1).
3. Evaluate Catch with parameter Result(1).
4. Return Result(3).

[...]

The production Catch : catch (Identifier ) Block is evaluated as
follows:

1. Let C be the parameter that has been passed to this production.
2. Create a new object as if by the expression new Object().
3. Create a property in the object Result(2). The property's name is
Identifier, value is C.value, and attributes are { DontDelete }.
4. Add Result(2) to the front of the scope chain.
5. Evaluate Block.
6. Remove Result(2) from the front of the scope chain.
7. Return Result(5).

So the effect is that the identifier in a catch statement *appears* to
have block scope, that term is never used in the specification.

<html>
<head>
<title>Untitled Document</title>
<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1">
<script type="text/javascript">

function init() {
// no "var" so creating new global variable "a"
// from within the function:
a = new Object;

try {
throw new Error('foobar');

An error is thrown and the catch block (if there is one) is executed.
The error object is passed as a parameter.
}
// no "var" so should be the same schema
// for "b" as for "a"
catch(b) {

If the catch block is executed, a reference to the error object
created in the try block is assigned to the indetifier b. After the
catch block is executed, the result is returned.

window.alert(typeof b); // 'object'

Which shows that an object was assigned to the variable b as a result
of the try block causing the catch block to executed.

/*NOP*/
}
window.setTimeout('demo()', 100);

}

function demo() {
window.alert(typeof a); // 'object'

A wasn't declared, so when init was executed, a reference to an Object
was assigned to a global property a.
window.alert(typeof b); // 'undefined'}

Which shows that the scope of the indetifier b was constrained to the
execution object created when init was called. Although b may well be
constrained further, your code doesn't show that. I guess you are
trying to say something like "but b wasn't declared with var so
therefore it should have become a global variable", but the excerpt
above from the spec shows why that doesn't happen and also explains it
without resorting to descriptions of "block scope". I must admit
though that the fact that b does not slip into the global space is not
stated explicitly, you have to work it out for yourself.

You may say it's just semantics, along the lines of "javascript does/
doesn't have associative arrays", but it's hard to see any point in
claiming javascript has block level scope simply because one (little
used) feature of the language happens to exhibit behaviour that might
be considered to demonstrate it.

Another way to explain it is that there is an implicit declaration of
the identifier and is effectively:

catch (var b) {...}

but I would not extend that to say javascript has implicit declaration
of local variables just because it appears to do so for catch
statements.
 
J

John G Harris

On Sat, 24 Nov 2007 at 18:16:33, in comp.lang.javascript, RobG wrote:

Another way to explain it is that there is an implicit declaration of
the identifier and is effectively:

catch (var b) {...}

but I would not extend that to say javascript has implicit declaration
of local variables just because it appears to do so for catch
statements.

Another way to describe it is to say it's like a 'with' statement :

with ( <unnamed object with a property named "b"> )
{ ... }

What can happen when you reach the closing } is different of course.

John
 
R

RobG

By searching all another info I've got this by occasion:

http://www.ecmascript.org/es4/spec/incompatibilities.pdf
see:
"1.5. Bindings for catch Variables and Named function Expressions"

Which (to my understand, which may well be wrong) doesn't support the
notion that block scope exists in ES3.

It notes that introducing block scope in ES4 for catch (i.e. ES4 will
use let-like binding instead of ES3's with-like scoping for the object
passed to the catch statement) will fix the apparently abberant
behaviour of catch in ES3.
 
V

VK

Which (to my understand, which may well be wrong) doesn't support the
notion that block scope exists in ES3.

Absolutely correct: see my second post in this thread where I'm saying
"So no, "b" in this sample is not a block-level variable in the sense
I
described." The linked resource sustains my second interpretation of
"e" in catch(e) as a kind of weird function-level variable
declaration. Programmatically nt a big deal anyway, just wanted to
clear it up for myself.
 

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,769
Messages
2,569,582
Members
45,066
Latest member
VytoKetoReviews

Latest Threads

Top