From: RobG on
On May 18, 3:59 am, williamc <n...(a)nowhere.net> wrote:
[...]
> Working through the example below helped me when I was reading the Zakas
> book not too long ago. From a notes page...
>
> * * *
>
> 4. Inner functions that retain values from outer functions possess the
> last value from the outer function.

Not so. The inner function has the outer function's variable object on
its scope chain, the identifier - i - will resolve to it if no local
variable shadows it. If the value of the variable changes, then its
value changes in the inner function too, e.g.


var outer = (function () {
var x;

return {

getX: function () {
return x;
},

setX: function(val) {
x = val;
}
}
})();

// Check the value of x
alert(outer.getX()); // undefined

// Set the value of x to a string
outer.setX('foo');

// Check the value of x
alert(outer.getX()); // foo

So the value isn't "set" when the function exits. The value is
whatever it is when it is read and can be changed by some other
closure (emulating a privileged method).


> This can lead to unexpected results
> as demonstrated in the first function below, which the programmer
> expected to return an array of functions which each will return the
> value of their array index. Instead, each function returns 5.

Unexpected only if the programmer isn't aware of how closures work in
ECMAScript.


> The second function creates the desired array of functions. Zakas: "The
> anonymous function has one argument, num, which is the number that the
> result function should return. Since function arguments are passed by
> value, the current value of i is copied into the argument num."

More misdirection. They are always references, but the *value* might
be a primitive or an object. Primitives are immutable, you can't
modify them, you can only assign a new one, so:

// With primitives
var a = 5,
b = a; // a and b == 5
b = 6; // b is assigned a new value, a is still == 5

// With objects
var o = {},
p = o; // o and p == object assigned to o
p = {}; // p is assigned a new object, o hasn't changed

The difference is that you can modify an object's properties, so:

var o = {},
p = o; // o and p == object assigned to o
p.x = 'foo';
alert(o.x); // foo

The the concept that "function arguments are passed by value" might be
kind of true if function arguments are always primitives, but they
aren't.


> function createFunctions() {
> var result = new Array();
> for (var i = 0; i < 5; i++) {
> result[i] = function() {
> return i;
> };
> }
> return result;
> }
> arrTest = createFunctions();
> alert(arrTest[2]()); // 5, not 2!
>
> function createFunctions2() {
> var result = new Array();
> for (var i = 0; i < 5; i++) {
> result[i] = function(num) {
> return function() {
> return num;
> };
> }(i);
> }
> return result;
> }
> arrTest = createFunctions2();
> alert(arrTest[2]()); // now it's 2

Because of the new closure with num. Variable i is still there on the
inner function's scope chain, replace:

return num;

with

return i;

and you get 5 again.


--
Rob
From: RobG on
On May 18, 3:56 am, Matt Kruse <m...(a)thekrusefamily.com> wrote:
> On May 16, 5:44 pm, Eleandor <vanbeurden.b...(a)gmail.com> wrote:
>
> > what I'm trying to achieve is to create a function that uses the
> > actual value of i, at the moment when the onclick function is created.
> > So "Display 5" should actually display 5, using the literal value of i
> > when the function is created, instead of the value of i at the time of
> > execution.
>
> elm.onclick = (function(inner_i) {
>   return function() {
>     self.shout(inner_i);
>   }
>
> })(i);
>
> Be careful for memory leaks...

Yes, forgot to mention that. They can be avoided for the most part by
setting:

elm = null;

in the function where elm is declared just before it ends.


--
Rob
From: Stefan Weiss on
On 17/05/10 00:44, Eleandor wrote:
> Person = (function() {
> return function() {
> var self = this;
....

Minor nitpick: self is not a good variable name in browser scripting;
it's usually an alias for the window object. It won't cause a problem in
your example, but it could confuse people who see a call to
"self.shout()" before they see the assignment above.


--
stefan
From: Thomas 'PointedEars' Lahn on
RobG wrote:

> On May 18, 3:59 am, williamc <n...(a)nowhere.net> wrote:
> [...]
>> The second function creates the desired array of functions. Zakas: "The
>> anonymous function has one argument, num, which is the number that the
>> result function should return. Since function arguments are passed by
>> value, the current value of i is copied into the argument num."
>
> More misdirection. They are always references,

What do you mean by "they" here?

> but the *value* might be a primitive or an object.

No, the value can be a primitive value or an object reference.
You cannot access an object directly, you need a reference to it.
As a result, there can be multiple references to the same object.
The object may be subject to garbage collection if it is no longer
referred, i.e. there are no more references to it (much like with
hardlinks).

> The the concept that "function arguments are passed by value" might be
> kind of true if function arguments are always primitives, but they
> aren't.

Zakas' premise is right here; you are not. Object references are values.
See also
<https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Functions>,
which was agreed on here.


PointedEars
--
Use any version of Microsoft Frontpage to create your site.
(This won't prevent people from viewing your source, but no one
will want to steal it.)
-- from <http://www.vortex-webdesign.com/help/hidesource.htm> (404-comp.)
From: Thomas 'PointedEars' Lahn on
Stefan Weiss wrote:

> Eleandor wrote:
>> Person = (function() {
>> return function() {
>> var self = this;
> ...
>
> Minor nitpick: self is not a good variable name in browser scripting;
> it's usually an alias for the window object. It won't cause a problem in
> your example, but it could confuse people who see a call to
> "self.shout()" before they see the assignment above.

It is not "usually an alias for the window object", it is a property of
Window instances or their prototype to refer to the instance. A Window
instance's prototype may be in the prototype chain of the ECMAScript Global
Object (this is the case with client-side JavaScript 1.8.2 in Gecko
1.9.2.3).

Since to my knowledge it is unnecessary to access the `self' property of
Window instances, I can see no cause for confusion here. Indeed, the
declaration follows the pattern of several other OOPLs, including most
notably, IIUC, Smalltalk which influenced the prototype-based Self
programming language (where you can omit `self') which influenced JavaScript
(unfortunately, Brendan Eich apparently did not see the importance of the
`self' keyword in JavaScript's predecessors).

However, in this case that assignment probably should be moved before the
`for' loop. There is no need (and perhaps no want) of the `self' identifier
to be in the scope of the returned function. But the function expression
returning a function when called is quite pointless and therefore
inefficient here to begin with; the assignment of a function expression, or
a function declaration would suffice as there are no bound variables in the
outer scope.


PointedEars
--
Prototype.js was written by people who don't know javascript for people
who don't know javascript. People who don't know javascript are not
the best source of advice on designing systems that use javascript.
-- Richard Cornford, cljs, <f806at$ail$1$8300dec7(a)nes.demon.co.uk>