Clarifying scope of literals

O

ociardhp

Hi

I've seen some code similar to the following and would like to confirm
my understanding. I assume the object literal created in the return
has access to the enclosing scope which includes the variable age,
effectively creating a closure over it when created, and that this is
what enables the assignment to moon.age? Is this considered good style
and is there any particular reason for using that approach as opposed
to the clearer (in my opinion) declaration of age within the object
literal?

Many thanks

Paul

<html>
<body>
<div id="holder"></div>
<script>

moon = function() {
var age;

return {
// age: 4000000000,

showDarkSide: function() {
return false;
}
}
}();

moon.age = 42;

document.getElementById("holder").innerHTML = "Age: " + moon.age +
"<br/> ShowDarkSide: " + moon.showDarkSide();

</script>
</body>
</html>
 
D

David Golightly

I've seen some code similar to the following and would like to confirm
my understanding. I assume the object literal created in the return
has access to the enclosing scope which includes the variable age,
effectively creating a closure over it when created, and that this is
what enables the assignment to moon.age? Is this considered good style
and is there any particular reason for using that approach as opposed
to the clearer (in my opinion) declaration of age within the object
literal?

<html>
<body>

<script>
moon = function() {
var age;

return {
// age: 4000000000,

showDarkSide: function() {
return false;
}
}
}();

moon.age = 42;

document.getElementById("holder").innerHTML = "Age: " + moon.age +
"<br/> ShowDarkSide: " + moon.showDarkSide();


Couple of points to start:
1. using <script> tags in the <body> of the document is nonstandard
and should be avoided.
2. you should always use the "var" keyword to declare your variables
("moon" in your example), and it's a good practice to automatically do
this, even if the variable is global.

There, now to your question.

One thing that's perhaps confusing in the discussion of closure and
scope in JavaScript is that scope is much simpler than you would think
from a classical OOP language. Your confusion probably comes from mis-
associating a concept of "private" variables in JavaScript. JS
doesn't have a "private" concept. Your example effectively creates
two distinct "things" with the name "age": one is a variable that is
local to the anonymous function that returns the object that gets
assigned to "moon"; this object literal has no "age" property until
you assign it on the next line ("moon.age = 42"). Since "moon" is an
object, you can always assign values to properties on the object -
there's no such thing as a "private" property in JavaScript. But the
"age" property you've created through assignment shouldn't be confused
with the "age" local variable in the anonymous function's scope.

Remove that line assigning a value to "moon.age" and re-run your code;
you'll see what actually happens.

-David
 
T

Thomas 'PointedEars' Lahn

David said:
Couple of points to start: 1. using <script> tags in the <body> of the
document is nonstandard and should be avoided.

Utter nonsense.
2. you should always use the "var" keyword to declare your variables
("moon" in your example), and it's a good practice to automatically do
this, even if the variable is global.

If the identifier is not declared, the assignment it will end up as an
assignment to an enumerable property of an object in the scope chain.
That does not have to be the Global Object, hence this recommendation.


PointedEars
 
R

RobG

Hi

I've seen some code similar to the following and would like to confirm
my understanding. I assume the object literal created in the return
has access to the enclosing scope which includes the variable age,
effectively creating a closure over it when created, and that this is
what enables the assignment to moon.age?

No (see below).

Is this considered good style
and is there any particular reason for using that approach as opposed
to the clearer (in my opinion) declaration of age within the object
literal?

The pattern is used to emulate the behaviour of private variables that
can be read or set by priveliged functions:

<URL: http://www.crockford.com/javascript/private.html >


[...]
<script>
moon = function() {
var age;

This variable is local to the anonymous function assigned to moon. It
can't be directly accessed from outside the function.

return {
// age: 4000000000,

Had you not commented out that line, the object returned by the
function and assigned to moon would have an age property with a value
of 4000000000. It is a different thing to the local age variable
declared earlier - they both exist independently.

showDarkSide: function() {
return false;
}

This function has access to the activation object created by executing
the "outer" anonymous function, so you could make it a priveliged
function that gets or sets the value of the private age variable. It
can also modify the public moon.age property.

}
}();

moon.age = 42;

Here you create a property of moon called age (if it doesn't already
exist) and assign it a value of 42.
 

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,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top