473,666 Members | 2,334 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Variable scope and closures

Given the following working code:

function attributes() {
var attr1 = arguments[0] || '_';
var attr2 = arguments[1] || '_';
return (
function (el1, el2) {
var value1 = el1[attr1] + el1[attr2];
var value2 = el2[attr1] + el2[attr2];
if (value1 > value2) return 1;
else if (value1 < value2) return -1;
else return 0;
}
);
}

var a = [
{ a:'smith', b:'john' },
{ a:'jones', b:'bob' },
{ a:'smith', b:'jane' }
];
a.sort(attribut es('a', 'b'));
for (var i =0; i < a.length; i++) {
document.write( a[i].a + ', ' + a[i].b + '<br>');
}

My question is, are attr1 and attr2 guaranteed to exist through
the lifetime of a.sort(attribut es('a', 'b'))?

As I understand it, the anonymous inner function reference I am
returning is a property of attributes(). As such, when I return a
reference to the anonymous inner function, the outer attributes()
function must continue to exist (as must attr1 and att2) until
there are no further references to the inner anonymous function.

As a result, there is no danger of attr1 or attr2 "disappeari ng"
during the repeated calling of the anonymous inner function.

Is my explanation basically correct, or am I deluding myself and
I'm just lucky that the garbage collector hasn't recovered attr1
or attr2 while the sort is still going on? In other words, is the
behaviour I'm seeing consistent and predictable, or should I
change my approach?

--
Grant Wagner <gw*****@agrico reunited.com>
comp.lang.javas cript FAQ - http://jibbering.com/faq

Jul 23 '05 #1
3 2005
Grant Wagner <gw*****@agrico reunited.com> writes:
Given the following working code:

function attributes() {
var attr1 = arguments[0] || '_';
var attr2 = arguments[1] || '_';
return (
function (el1, el2) {
var value1 = el1[attr1] + el1[attr2];
var value2 = el2[attr1] + el2[attr2];
if (value1 > value2) return 1;
else if (value1 < value2) return -1;
else return 0;
}
);
}
G
Grant Wagner <gw*****@agrico reunited.com> writes:
iven the following working code:

function attributes() {
var attr1 = arguments[0] || '_';
var attr2 = arguments[1] || '_';
return (
function (el1, el2) {
var value1 = el1[attr1] + el1[attr2];
var value2 = el2[attr1] + el2[attr2];
if (value1 > value2) return 1;
else if (value1 < value2) return -1;
else return 0;
}
);
}

var a = [
{ a:'smith', b:'john' },
{ a:'jones', b:'bob' },
{ a:'smith', b:'jane' }
];
a.sort(attribut es('a', 'b'));
for (var i =0; i < a.length; i++) {
document.write( a[i].a + ', ' + a[i].b + '<br>');
}

My question is, are attr1 and attr2 guaranteed to exist through
the lifetime of a.sort(attribut es('a', 'b'))?

As I understand it, the anonymous inner function reference I am
returning is a property of attributes(). As such, when I return a
reference to the anonymous inner function, the outer attributes()
function must continue to exist (as must attr1 and att2) until
there are no further references to the inner anonymous function.

As a result, there is no danger of attr1 or attr2 "disappeari ng"
during the repeated calling of the anonymous inner function.

Is my explanation basically correct, or am I deluding myself and
I'm just lucky that the garbage collector hasn't recovered attr1
or attr2 while the sort is still going on? In other words, is the
behaviour I'm seeing consistent and predictable, or should I
change my approach?

--
Grant Wagner <gw*****@agrico reunited.com>
comp.lang.javas cript FAQ - http://jibbering.com/faq

var a = [
{ a:'smith', b:'john' },
{ a:'jones', b:'bob' },
{ a:'smith', b:'jane' }
];
a.sort(attribut es('a', 'b'));
for (var i =0; i < a.length; i++) {
document.write( a[i].a + ', ' + a[i].b + '<br>');
}
My question is, are attr1 and attr2 guaranteed to exist through
the lifetime of a.sort(attribut es('a', 'b'))?
Yes. That's because the *closure* you return contains references
to its free variables, in this case "attr1" and "attr2". They will
live as long as the function you return.
As I understand it, the anonymous inner function reference I am
returning is a property of attributes().
"Property" is usually used for properties of objects, and that it
isn't. The function returned is independent of the function
"attributes " *except* that it contains the variables object of
the call to attributes in its scope chain.
As such, when I return a reference to the anonymous inner function,
the outer attributes() function must continue to exist (as must
attr1 and att2) until there are no further references to the inner
anonymous function.
To be, painfully, exact:

The attributes function itself exists, as usual.

The variables object created when the attributes function was called
still exists, because it is in the scope chain of the returned
closure.

When a function *value* is created (by evaluating a function
expression or a function declaration), it contains both the
code of the body of the function *and* the scope chain that
the function expression/declaration is evaluated in. That means
that the created function value is "closed" wrt. the values of
its free variables. That's why it's called a closure.
As a result, there is no danger of attr1 or attr2 "disappeari ng"
during the repeated calling of the anonymous inner function.
Correct. Javascript is statically scoped and has first class and
nested functions.
Is my explanation basically correct, or am I deluding myself and
I'm just lucky that the garbage collector hasn't recovered attr1
or attr2 while the sort is still going on? In other words, is the
behaviour I'm seeing consistent and predictable, or should I
change my approach?


It is consistent and predictable, and entirely according to standard.

Javascript is not C++, local variables are not allocated on a stack
the dies when the function returns. They live in an object called the
"variables object" of the function call. That object is not accessible
programmaticall y (so we don't know how it's *really* implemented), but
nested functions generate closures that contain references to all
the variable objects that are in scope.

Example code:

function foo() {
var i = 0;
var bar = function() { return i; } // refers to variable i, not its value
i++
var baz = function() { return i; }
i++;
alert([bar(),baz()]); // alerts 2,2, because both refer to the same variable,
// which has value 2.
}

/L
--
Lasse Reichstein Nielsen - lr*@hotpop.com
DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleD OM.html>
'Faith without judgement merely degrades the spirit divine.'
Jul 23 '05 #2
Grant Wagner wrote:
Given the following working code:

function attributes() {
var attr1 = arguments[0] || '_';
var attr2 = arguments[1] || '_';
return (
function (el1, el2) {
var value1 = el1[attr1] + el1[attr2];
var value2 = el2[attr1] + el2[attr2];
if (value1 > value2) return 1;
else if (value1 < value2) return -1;
else return 0;
}
);
}

var a = [
{ a:'smith', b:'john' },
{ a:'jones', b:'bob' },
{ a:'smith', b:'jane' }
];
a.sort(attribut es('a', 'b'));
for (var i =0; i < a.length; i++) {
document.write( a[i].a + ', ' + a[i].b + '<br>');
}

My question is, are attr1 and attr2 guaranteed to exist through
the lifetime of a.sort(attribut es('a', 'b'))?
Should be, that is what ECMA 262 3rd edition says should happen.
As I understand it, the anonymous inner function
reference I am returning is a property of attributes().
Actually the anonymous function is not a property of anything.
As such, when I return a reference to the anonymous inner
function, the outer attributes() function must continue to
exist
No, I think it would be possible to delete the reference to the outer
function from the global object and have it garbage collected while the
inner function is being used without impact on the inner function (or
attr1 and att2).
(as must attr1 and att2) until
there are no further references to the inner anonymous function.
The outer function local variables must continue to exist while the
inner anonymous function exists, but they are not located where you seem
to think.

This becomes a matter of scope chains, [[scope]] properties and
"variable" objects, and the structures that they form in ECMAScript.

The outer function has a [[scope]] property that refers to a scope chain
that should only contain the global object. When the outer function is
called an "execution context" is entered and that execution context is
assigned a scope chain of its own. That chain is defined by the chain
referred to by the outer function's [[scope]] property, with a new
"variable" object placed at the top of the chain.

Function formal parameters, local variables and named inner function
definitions (but not anonymous function expressions) result in
correspondingly named properties of the "variable" object being created,
and assigned values (though not immediately in the case of local
variables).

When a function object is created (as would be the result of an
anonymous function expression) it is assigned a [[scope]] property that
refers to the scope chain of the "execution context" in which it was
created. So for your anonymous inner function, its [[scope]] property
refers to a chain consisting of the variable object from the "execution
context" of the call to the outer function in which it was created
(with its attr1 and att2 properties), followed by the global object.

Thus is created a structure of objects through which the anonymous inner
function object indirectly refers to the variable object from the
execution context in which it was created, with the properties named
attr1 and att2. The "variable" object cannot be garbage collected until
the inner function object is destroyed and its [[scope]] property freed.

Each call to a function creates a new "execution context" with a new
"variable" object, so not only are attr1 and att2 preserved but each
anonymous inner function created by a call to the outer function will
have access to a different set of attr1 and att2 properties on a
different "variable" object.

<URL: http://jibbering.com/faq/faq_notes/closures.html >
As a result, there is no danger of attr1 or attr2
"disappeari ng" during the repeated calling of the anonymous
inner function.
None.
Is my explanation basically correct, or am I deluding myself and
I'm just lucky that the garbage collector hasn't recovered attr1
or attr2 while the sort is still going on? In other words, is the
behaviour I'm seeing consistent and predictable, or should I
change my approach?


The behaviour you are observing is defined in ECMA 262 3rd edition and
so should be consistent across all ECMAScript (3rd ed) implementations .
And with the exception of the really poor script implementation in
Konqueror 2 (labelled "experiment al" and now abandoned) closures seem to
work 100% consistently across browsers that are likely to still be in
use (version 4 era onwards).

Richard.
Jul 23 '05 #3
Richard Cornford wrote:
The behaviour you are observing is defined in ECMA 262 3rd edition and
so should be consistent across all ECMAScript (3rd ed) implementations .
And with the exception of the really poor script implementation in
Konqueror 2 (labelled "experiment al" and now abandoned) closures seem to
work 100% consistently across browsers that are likely to still be in
use (version 4 era onwards).


Thanks Richard (and Lasse) for the explanation.

Obviously the test case I posted isn't the complete code. "attributes ()"
actually returns a function for sorting 1, 2 or 3 attributes. It also pads
the attribute values prior to concatenation, so you never end up comparing
"123SmithJo hn" to "345678Lastname Bob". You compare "123 Smith John" to
"345678Lastname Bob" (well, I actually pad each individual value to 256
characters).

I wrote the code, debugged and tested it and then realized I had no idea why
it was working. Now I do.

Thanks again.

--
Grant Wagner <gw*****@agrico reunited.com>
comp.lang.javas cript FAQ - http://jibbering.com/faq

Jul 23 '05 #4

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
2406
by: Marc Tanner | last post by:
Hello, I am currently working on a eventhandling system or something similar, and have the problem of loosing scope. I have read many interesting posts on this group and the faq article about closure, but it seems that i have still not understood everything. Below is my attempt to preserve the scope but it's not really nice and i think with the use of closure could it be done better. But at the moment i am quite confused and hope that...
5
1986
by: Greg Swindle | last post by:
Hello, I have a question about how prototyping relates to variables and their scope. Given the following code: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ var ParentObject = function() { var objectName = "ParentObject";
134
7859
by: James A. Donald | last post by:
I am contemplating getting into Python, which is used by engineers I admire - google and Bram Cohen, but was horrified to read "no variable or argument declarations are necessary." Surely that means that if I misspell a variable name, my program will mysteriously fail to work with no error message. If you don't declare variables, you can inadvertently re-use an variable used in an enclosing context when you don't intend to, or
166
8597
by: Graham | last post by:
This has to do with class variables and instances variables. Given the following: <code> class _class: var = 0 #rest of the class
2
3297
by: Funktopia | last post by:
I am trying to convert some of my javascripts into a class and am running into difficulties which i think are related to variable scope. Basically I have a constructor function for a calendarInput class that takes 4 parameters, the first is a reference name/number for this input. I also have some functions for importing my PHP classes into Javascript using AJAX (properties only. still trying to get methods working but that's another...
4
2701
by: Ray | last post by:
Hello, I think I've had JavaScript variable scope figured out, can you please see if I've got it correctly? * Variables can be local or global * When a variable is declared outside any function, it is global regardless of whether it's declared with or without "var" * When it is declared inside a function, if declared with "var", it's local, if not, it's global
9
3514
by: tai | last post by:
Hi. I'm looking for a way to define a function that's only effective inside specified function. Featurewise, here's what I want to do: bar_plugin_func = function() { ...; setTimeout(...); ... }; wrap_func(bar_plugin_func); bar_plugin_func(); // calls custom "setTimeout"
10
12787
by: John Passaniti | last post by:
(Note: This is not the same message I posted a week or so ago. The problem that prevented my previous attempt to work was a silly error in the template system I was using. This is a problem involving variable scope in JavaScript.) I have a lot of code that generates HTML on the fly. This code has tags with id attributes derived from variables. A small example: blah('<span id="' + dev + '_' + mod + '">...</span>');
2
1830
by: Andrey Fedorov | last post by:
Is the scope of a closure accessible after it's been created? Is it safe against XSS to use closures to store "private" auth tokens? In particular, in... ....can untrusted code access 'secret', or only the code inside foo? - Andrey
0
8443
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
8866
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
8781
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
8550
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
7385
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
6192
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
1
2769
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
2011
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
2
1772
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.