Closure bug

Discussion in 'Javascript' started by Eleandor, May 16, 2010.

  1. Eleandor

    Eleandor Guest

    Well, I realise it's not so much a bug as it is a feature.

    I've written a quick testpage:

    <html>
    <head>
    <script type="text/javascript">
    Person = (function() {
    return function() {
    var self = this;

    this.messages = function() {
    for(var i = 0; i < 10; i++) {
    var elm = document.createElement("div");
    elm.innerHTML = "Display " + i;
    elm.onclick = function() {
    self.shout(i);
    };
    document.body.appendChild(elm);
    }
    };

    this.shout = function(number) {
    alert(number);
    };
    };
    }());

    function LoadPage() {
    var p = new Person();
    p.messages();
    }

    </script>
    </head>

    <body onload="LoadPage()">
    </body>
    </html>

    The html page shows "Display x" with x a number from 0 to 9. However,
    as I click it, it displays 10 regardless of which element I clicked. I
    can understand why, since the value of i is 10 when the loop ends. But
    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.

    How can I achieve something like this?

    Thanks,

    - Bart
     
    Eleandor, May 16, 2010
    #1
    1. Advertising

  2. Eleandor

    RobG Guest

    On May 17, 8:44 am, Eleandor <> wrote:
    > Well, I realise it's not so much a bug as it is a feature.
    >
    > I've written a quick testpage:
    >
    > <html>
    >         <head>


    When posting code, indent using 2 (preferred) or 4 spaces and manually
    wrap at about 70 characters, see below.

    <head>
    <script type="text/javascript">

    Person = (function() {
    return function() {
    var self = this;
    this.messages = function() {

    for(var i = 0; i < 10; i++) {
    var elm = document.createElement("div");
    elm.innerHTML = "Display " + i;
    elm.onclick = function() {
    self.shout(i);
    };
    document.body.appendChild(elm);
    }
    };
    this.shout = function(number) {
    alert(number);
    };
    };
    }());

    function LoadPage() {
    var p = new Person();
    p.messages();
    }
    </script>
    </head>
    <body onload="LoadPage()"></body>

    >
    > The html page shows "Display x" with x a number from 0 to 9. However,
    > as I click it, it displays 10 regardless of which element I clicked. I
    > can understand why, since the value of i is 10 when the loop ends. But
    > 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.
    >
    > How can I achieve something like this?


    You need to break the closure. One way is to use new Function, but
    scope becomes a bit tricky. Another is to use a setter for the onclick
    property rather than a function expression, e.g.

    elm.onclick = setOnclick(self, i);


    then add:

    function setOnclick(self, i) {
    return function() {
    self.shout(i);
    }
    }

    as a global function, or inside the outer Person function (the
    Cornified one[1]).

    Another is to set it with a function expression:

    elm.onclick = (function(number) {
    return function() {
    self.shout(number);
    };
    })(i);


    But this whole thing seems quite convoluted. The i property doesn't
    seem to belong to a "person", it belongs to the listener attached to
    the element, so probably shouldn't be inside the person constructor at
    all. Perhaps you are better to create a message cache and use an
    attribute of the HTML element to associate with a message (e.g. its
    ID). If HTML 5 was widely implemented, you could add the index as a
    data property of the element directly (but it will be a long time
    before that is viable on the web).

    There are many other solutions, hard to say what is better or worse
    without knowing what you are really trying to do, I doubt that either
    of the above suggestions are the best you can do in your circumstance.

    1. <URL: http://groups.google.com/group/comp.lang.javascript/browse_frm/thread/c6fec4b30a4e2811#
    >



    --
    Rob
     
    RobG, May 17, 2010
    #2
    1. Advertising

  3. RobG wrote:

    > Eleandor wrote:
    >> I've written a quick testpage:
    >>
    >> <html>
    >> <head>

    >
    > When posting code, indent using 2 (preferred) or 4 spaces and manually
    > wrap at about 70 characters, see below.


    ACK

    > <head>


    That HTML document needs a DOCTYPE declaration and a TITLE element to be
    Valid. <http://validator.w3.org/>

    > <script type="text/javascript">
    >
    > Person = (function() {


    Should be declared a (global) variable, otherwise there can be fatal
    side-effects with MSHTML (fatal as in "breaking").

    var Person = ...

    > return function() {
    > var self = this;
    > this.messages = function() {
    >
    > for(var i = 0; i < 10; i++) {
    > var elm = document.createElement("div");
    > elm.innerHTML = "Display " + i;
    > elm.onclick = function() {
    > self.shout(i);
    > };
    > document.body.appendChild(elm);


    You should avoid combining DOM Level 2+ and 0, especially when without
    feature test. In particular, you do not need or want `innerHTML' here:

    var elm = document.createElement("div");
    if (elm)
    {
    elm.appendChild(document.createTextNode("Display " + i));
    // ...
    }

    > }
    > };
    > this.shout = function(number) {
    > alert(number);
    > };
    > };
    > }());
    >
    > function LoadPage() {


    This is not used as a constructor or factory, so the identifier should start
    lowercase.

    > [...] or inside the outer Person function (the Cornified one[1]). [...]

    ^^^^^^^^^
    Please don't. I thought it was only a joke back then :-/


    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.)
     
    Thomas 'PointedEars' Lahn, May 17, 2010
    #3
  4. Eleandor

    Matt Kruse Guest

    On May 16, 5:44 pm, Eleandor <> 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...

    Matt Kruse
     
    Matt Kruse, May 17, 2010
    #4
  5. Eleandor

    RobG Guest

    On May 18, 3:59 am, williamc <> 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 = 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 = 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
     
    RobG, May 18, 2010
    #5
  6. Eleandor

    RobG Guest

    On May 18, 3:56 am, Matt Kruse <> wrote:
    > On May 16, 5:44 pm, Eleandor <> 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
     
    RobG, May 18, 2010
    #6
  7. RobG wrote:

    > On May 18, 3:59 am, williamc <> 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.)
     
    Thomas 'PointedEars' Lahn, May 18, 2010
    #7
  8. 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$>
     
    Thomas 'PointedEars' Lahn, May 18, 2010
    #8
  9. Eleandor

    David Mark Guest

    williamc wrote:
    > On 5/18/2010 6:52 AM, Thomas 'PointedEars' Lahn wrote:
    >> RobG wrote:
    >>
    >>> On May 18, 3:59 am, williamc <> 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.
    >>

    >
    > I wondered what people in c.l.j would say about the Zakas' point that
    > function arguments are always passed by value. He kind of stresses it,
    > in the sense that he repeats it several times. I didn't really feel
    > comfortable with it at the time, and I still don't feel comfortable with
    > it. In most languages doesn't the concept of pass by value vs. pass by
    > reference refer to passing an independent copy vs. passing a reference
    > to the thing itself?
    >
    > I have a "something I'm missing here" feeling...
    >
    > obj = {
    > propX: "foo"
    > };
    > num = 27;
    >
    > function test(argNum, argObj) {
    > argNum = 28;
    > argObj.propX = "bar";
    > }
    >
    > test(num, obj);
    >
    > console.log(num); // still 27
    > console.log(obj.propX); // "bar", so why isn't this called a pass
    > by reference?
    >
    > In the link Thomas cited it says...
    >
    > "The parameters of a function call are the function's arguments.
    > Arguments are passed to functions by value. If the function changes the
    > value of an argument, this change is not reflected globally or in the
    > calling function. However, object references are values, too, and they
    > are special: if the function changes the referred object's properties,
    > that change is visible outside the function, ... "
    >
    > So, I guess I'm having a hard time with the "they are special". Wouldn't
    > this specialness simply be called a pass by reference in most languages?
    >


    No. The value passed is a reference to an object. That might sound
    like a contradiction in terms, but consider:-

    function test(o) {
    o = null;
    }

    var p = {};
    test(p);
    window.alert(p); // Not null
     
    David Mark, May 18, 2010
    #9
  10. williamc wrote:

    > David Mark wrote:
    >> No. The value passed is a reference to an object. That might sound
    >> like a contradiction in terms, but consider:-
    >>
    >> function test(o) {
    >> o = null;
    >> }
    >>
    >> var p = {};
    >> test(p);
    >> window.alert(p); // Not null

    >
    > Yikes! Well, that's certainly a good example, as I would have expected p
    > to be null after the function call. But I can't say that I've succeeded
    > in understanding why it isn't.


    As `o' is but a variable (sort of) that is assigned a value, a reference to
    an object, as execution enters the context of the function [ES3/5, 10.4] --

    p
    ||
    ref ---> [object Object]
    ||
    o

    -- then changing the value of the (local) "variable" in the function does
    not change the object, of course:

    p
    ||
    ref ---> [object Object]

    o = null

    That is where object references are special. As long as a property (here:
    of the function context's Variable Object) stores a reference value, you can
    use that property to change the referred object's properties.

    > So, the right way to think about is the object "supplies the value to
    > the function"?


    No, `p' did not store the object in the first place; it only stored the
    reference (value) to it. As does `q' below:

    var p = {};

    /*
    * p
    * ||
    * ref ---> [object Object = {}]
    */

    var q = p;

    /*
    * p
    * ||
    * ref ---> [object Object = {}]
    * ||
    * q
    */

    q.a = 42;

    /*
    * p
    * ||
    * ref ---> [object Object = {a: 42}]
    * ||
    * q
    */

    /* 42 */
    p.a;

    BTW, it's the same in Java and other OOPLs.

    You want to fix your `From' header.


    HTH

    PointedEars
    --
    realism: HTML 4.01 Strict
    evangelism: XHTML 1.0 Strict
    madness: XHTML 1.1 as application/xhtml+xml
    -- Bjoern Hoehrmann
     
    Thomas 'PointedEars' Lahn, May 18, 2010
    #10
  11. williamc wrote:

    > [...] Fix my 'From' header in the sense of supplying a valid e-mail
    > address?


    In the sense of supplying an e-mail address in the first place. You have
    something there that looks like one but is not, thereby bothering potential
    respondents with bounces and 216.8.179.23 with futile connection attempts.

    And please trim your quotes to the relevant minimum next time.


    PointedEars
    --
    realism: HTML 4.01 Strict
    evangelism: XHTML 1.0 Strict
    madness: XHTML 1.1 as application/xhtml+xml
    -- Bjoern Hoehrmann
     
    Thomas 'PointedEars' Lahn, May 18, 2010
    #11
  12. Stefan Weiss wrote:

    > Thomas 'PointedEars' Lahn wrote:
    >> 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).

    >
    > Very verbose, but technically correct. That doesn't affect the point I'm
    > trying to make, however: in browser scripting, the "self" identifier
    > usually already refers to _something_ -


    Usually, granted, but I would not count on that it always does.

    > just like "document" and "window" do. You're free to assign something else
    > to them,


    This reads like the built-in value would be overwritten then; it is not.

    > but this can cause confusion for readers.


    But that is not a good argument, see below. *Anything* can cause confusion
    for the reader, particular uninitiated ones. 100% of the technical
    discussions and proper code posted here (like, closures by called function
    expressions, Array initialization with leading comma, `~+s', `new Date() -
    new Date(2000, 0, 1)') would confuse at least someone.

    >> 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).

    >
    > Neither do I. As a reference to the current context (or instance),
    > "self" feels more natural to me than "that" or "me" (some conventional
    > alternatives), but reusing it has the potential for confusion and should
    > therefore be avoided, IMHO.


    You are confusing cause and effect, though. Wouldn't it be great if you
    could forget about the

    var that = this;

    or

    var self = this;

    etc. and simply write only:

    > For example: I didn't read the original code posted by Eleandor, mostly
    > because of the formatting. The first thing I saw was Matt's example:
    >
    > elm.onclick = (function(inner_i) {
    > return function() {
    > self.shout(inner_i);
    > }
    > })(i);
    >
    > I wondered why he would call shout() as self.shout(), so I checked
    > whether self had been redefined (it was), but from that snippet alone,
    > it looked like shout() was a global function.


    You have learned something, then. That confusion can only occur because
    someone (I'm afraid, Brendan Eich, too) had the (not-so-)great idea to
    provide Window instances with a self-referring `self' property and put a
    Window instance in the prototype chain of the Global Object (or before the
    Global Object in the scope chain, depends on the implementation), to mix
    language and browser object model (that was fixed in JavaScript 1.4, but
    it was too late by then).

    So that people became accustomed to writing `alert' when they meant
    `window.alert', and seeing `window.self' when someone was writing only
    `self'. And Netscape's competitors copied that mistake in order to be
    compatible.

    That does not mean this misconception needs to be catered by not declaring
    a `self' variable in browser scripting.


    PointedEars
    --
    Danny Goodman's books are out of date and teach practices that are
    positively harmful for cross-browser scripting.
    -- Richard Cornford, cljs, <cife6q$253$1$> (2004)
     
    Thomas 'PointedEars' Lahn, May 18, 2010
    #12
  13. Stefan Weiss wrote:

    > Thomas 'PointedEars' Lahn wrote:
    >> Stefan Weiss wrote:
    >>> As a reference to the current context (or instance),
    >>> "self" feels more natural to me than "that" or "me" (some conventional
    >>> alternatives), but reusing it has the potential for confusion and should
    >>> therefore be avoided, IMHO.

    >>
    >> You are confusing cause and effect, though. Wouldn't it be great if you
    >> could forget about the
    >>
    >> var that = this;
    >>
    >> or
    >>
    >> var self = this;
    >>
    >> etc. and simply write only:

    > [ self.shout(inner_i); ]
    >
    > It would sure be convenient, but I doubt there's a way for a JS engine
    > to determine which of the (potentially many) nested "this values" the
    > "self" identifier should point to.


    A definition can be found. (Didn't ES5 specify something similar?)

    >> So that people became accustomed to writing `alert' when they meant
    >> `window.alert', and seeing `window.self' when someone was writing only
    >> `self'. And Netscape's competitors copied that mistake in order to be
    >> compatible.
    >>
    >> That does not mean this misconception needs to be catered by not
    >> declaring a `self' variable in browser scripting.

    >
    > You could apply the same argument to any other property of the window
    > object. Why not redefine alert, for example? I'm not calling
    > window.alert in my script, so I might as well reuse the name. But I
    > don't - and the reason is, as before, to avoid confusion for others.


    Then we have to agree to disagree here. If I always needed to write code so
    that it could not possibly stir some neophyte's confusion, so that it
    catered and helped cultivating their many misconceptions instead, I would
    not only be writing much less efficient code, but also my development
    process itself would be much less efficient then. And I would deprive them
    of the singular opportunity that is being granted to me, to learn about
    creating something better than the usual junk out there, just by reading
    other's code and trying to understand it.


    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.)
     
    Thomas 'PointedEars' Lahn, May 19, 2010
    #13
  14. Eleandor

    RobG Guest

    On May 18, 10:56 pm, williamc <> wrote:
    > On 5/18/2010 6:52 AM, Thomas 'PointedEars' Lahn wrote:
    > > RobG wrote:

    >
    > >> On May 18, 3:59 am, williamc <> 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?


    The values that are assigned by the calling function.


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

    >
    > > No, the value can be a primitive value or an object reference.


    To me, the values can be considered references for both (see below).


    > > 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 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.


    Yes, fair enough, if references are considered values. But that
    concept seems to be confusing, I find it simpler to think if it my
    way.


    > I wondered what people in c.l.j would say about the Zakas' point that
    > function arguments are always passed by value.


    He is right if references are considered values, which seems to be the
    majority opinion.


    > He kind of stresses it,
    > in the sense that he repeats it several times. I didn't really feel
    > comfortable with it at the time, and I still don't feel comfortable with
    > it. In most languages doesn't the concept of pass by value vs. pass by
    > reference refer to passing an independent copy vs. passing a reference
    > to the thing itself?


    I think in both cases their values are references because, to me, it
    is less confusing. As I posted eariler, given:

    var a = 5,
    b = a;

    You can think of a and b as refering to the same instance of 5. Since
    that instance can't be modified, the only way to change the value of a
    or b is to assign a new value. That is consistent with the equivalent
    scenerio using ojbects:

    var o = {},
    p = a;

    Here p references the same object as o. If you assign a new value to
    either o or p, they now reference different objects or primitives
    depending on what was assigned. So the concept of reference and
    assignment is consistent regardless of whether an object or primitve
    is assigned.

    Special behaviour is now kept to objects: when an object is modifed,
    everything that references it "sees" the modifications. You can't
    modify primitives, so they don't have the same behaviour:

    o.property1 = 'one';

    Here a value is assigned to a property of the object referenced by o,
    i.e. the object was modified, no new value was assigned to o. So o and
    p still reference the same object and:

    alert( p.property1 ); // shows 'p'


    Anyhow, that's my way of understanding it.


    > I have a "something I'm missing here" feeling...
    >
    > obj = {
    > propX: "foo"
    > };
    > num = 27;
    >
    > function test(argNum, argObj) {
    > argNum = 28;
    > argObj.propX = "bar";
    > }
    >
    > test(num, obj);
    >
    > console.log(num); // still 27


    Yes, because a new value was assigned to argNum, not to num.


    > console.log(obj.propX); // "bar",


    Because no new value was assigned to either obj or argObj, the object
    they reference was modified (something that is impossible with
    primitives). David shows what happens if you assign a new value to one
    of them, which is consisent whether you assign a primitve, object,
    null, whatever.


    > so why isn't this called a pass by reference?


    I don't think of it as "passing" but assigning. The variables in the
    parameter list are assigned values depending on what is in the calling
    parameter list.


    > In the link Thomas cited it says...
    >
    > "The parameters of a function call are the function's arguments.
    > Arguments are passed to functions by value. If the function changes the
    > value of an argument, this change is not reflected globally or in the
    > calling function. However, object references are values, too, and they
    > are special: if the function changes the referred object's properties,
    > that change is visible outside the function, ... "
    >
    > So, I guess I'm having a hard time with the "they are special". Wouldn't
    > this specialness simply be called a pass by reference in most languages?


    Which is why I limit the specialness to objects, not assignment.

    I hope I've helped, not confused. :)


    --
    Rob
     
    RobG, May 19, 2010
    #14
  15. RobG wrote:

    > williamc wrote:
    >> Thomas 'PointedEars' Lahn wrote:
    >> > RobG wrote:
    >> >> williamc 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?

    >
    > The values that are assigned by the calling function.


    How can *you* know for sure what *he* meant?

    >> >> but the *value* might be a primitive or an object.
    >> >
    >> > No, the value can be a primitive value or an object reference.

    >
    > To me, the values can be considered references for both (see below).


    You are wrong.

    >> >> 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.

    >
    > Yes, fair enough, if references are considered values. But that
    > concept seems to be confusing, I find it simpler to think if it my
    > way.
    >
    >> I wondered what people in c.l.j would say about the Zakas' point that
    >> function arguments are always passed by value.

    >
    > He is right if references are considered values, which seems to be the
    > majority opinion.


    That is not an opinion, it is a fact. RTFM.

    >> He kind of stresses it, in the sense that he repeats it several times. I
    >> didn't really feel comfortable with it at the time, and I still don't
    >> feel comfortable with it. In most languages doesn't the concept of pass
    >> by value vs. pass by reference refer to passing an independent copy vs.
    >> passing a reference to the thing itself?

    >
    > I think in both cases their values are references because, to me, it
    > is less confusing. As I posted eariler, given:
    >
    > var a = 5,
    > b = a;
    >
    > You can think of a and b as refering to the same instance of 5.


    But you should not. While Smalltalk undoubtedly is an ancestor of
    JavaScript/ECMAScript, by contrast `5' is _not_ an object in ECMAScript
    implementations (it is only being implicitly converted to a Number instance
    sometimes).

    So, in your words, `b' "refers" to _another_ `5' than `a'. Indeed, the
    variables `a' and `b' would very likely be implemented as two pointers
    pointing to different heap addresses.

    > Since that instance can't be modified, the only way to change the value of
    > a or b is to assign a new value. That is consistent with the equivalent
    > scenerio using ojbects:
    >
    > var o = {},
    > p = a;
    >
    > Here p references the same object as o.


    If you assigned the value of `o', and not `a'.

    > If you assign a new value to either o or p, they now reference different
    > objects


    Only if the new value is an object reference.

    > or primitives


    Primitives are _not_ being referred to (as references are understood in
    these languages.)

    > depending on what was assigned. So the concept of reference and
    > assignment is consistent regardless of whether an object or primitve
    > is assigned.


    No, it is not.

    > Anyhow, that's my way of understanding it.


    Well, misconceptions are quite common in this field.


    PointedEars
    --
    Danny Goodman's books are out of date and teach practices that are
    positively harmful for cross-browser scripting.
    -- Richard Cornford, cljs, <cife6q$253$1$> (2004)
     
    Thomas 'PointedEars' Lahn, May 19, 2010
    #15
  16. Stefan Weiss wrote:
    > On 18/05/10 15:05, David Mark wrote:
    >> The value passed is a reference to an object. That might sound
    >> like a contradiction in terms, but consider:-
    >>
    >> function test(o) {
    >> o = null;
    >> }
    >>
    >> var p = {};
    >> test(p);
    >> window.alert(p); // Not null

    >
    > I think that's a perfect illustration. It's all you need to see to
    > understand that there is no pass-by-reference in JS. Incidentally,
    > that's also the way it works in Java, and Java is also the source of the
    > expression "reference types" that has been thrown around here a couple
    > of times.


    The same behavior is seen in Java, however, Java's "reference types" has
    different meaning that Reference type in ECMAScript.

    Java Reference Types, from JLS, 3rd Edition, Chapter 4:
    | The reference types (§4.3) are class types, interface types, and
    | array types.
    http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html


    ECMAScript Reference Type, from ECMAScript Edition 3, s 8.7
    | The internal Reference type is not a language data type. It is defined
    | by this specification purely for expository purposes. An
    | implementation of ECMAScript must behave as if it produced and
    | operated upon references in the manner described here. However, a
    | value of type Reference is used only as an intermediate result of
    | expression evaluation and cannot be stored as the value of a variable
    | or property.

    Elsewhere:
    http://dmitrysoshnikov.com/ecmascript/chapter-8-evaluation-strategy/
    --
    Garrett
    comp.lang.javascript FAQ: http://jibbering.com/faq/
     
    Garrett Smith, May 19, 2010
    #16
  17. Eleandor

    RobG Guest

    On May 19, 10:43 am, Thomas 'PointedEars' Lahn <>
    wrote:
    > RobG wrote:
    > > williamc wrote:
    > >> Thomas 'PointedEars' Lahn wrote:
    > >> > RobG wrote:
    > >> >> williamc 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?

    >
    > > The values that are assigned by the calling function.

    >
    > How can *you* know for sure what *he* meant?


    You asked what *I* meant, I've explained that.


    [...]
    > > I think in both cases their values are references because, to me, it
    > > is less confusing. As I posted eariler, given:

    >
    > > var a = 5,
    > > b = a;

    >
    > > You can think of a and b as refering to the same instance of 5.

    >
    > But you should not. While Smalltalk undoubtedly is an ancestor of
    > JavaScript/ECMAScript, by contrast `5' is _not_ an object in ECMAScript
    > implementations (it is only being implicitly converted to a Number instance
    > sometimes).
    >
    > So, in your words, `b' "refers" to _another_ `5' than `a'.


    No, in my words, 'b' and 'a' refer to the same '5'. Since that '5'
    can't be modified, the value of 'b' can only be changed by assigning a
    new value, even if it's another '5'.

    > Indeed, the
    > variables `a' and `b' would very likely be implemented as two pointers
    > pointing to different heap addresses.


    Maybe, but implementation details are irrelevant.


    > > Since that instance can't be modified, the only way to change the value of
    > > a or b is to assign a new value. That is consistent with the equivalent
    > > scenerio using ojbects:

    >
    > > var o = {},
    > > p = a;

    >
    > > Here p references the same object as o.

    >
    > If you assigned the value of `o', and not `a'.


    Yes, a typo.

    [...]

    > > Anyhow, that's my way of understanding it.

    >
    > Well, misconceptions are quite common in this field.


    Apparently - I'll keep this one to myself. BTW, do you have a link to
    where it was discussed here previously?


    --
    Rob
     
    RobG, May 19, 2010
    #17
  18. Eleandor

    Ry Nohryb Guest

    On May 19, 3:14 am, Stefan Weiss <> wrote:
    > On 18/05/10 15:05, David Mark wrote:
    >
    > > The value passed is a reference to an object.  That might sound
    > > like a contradiction in terms, but consider:-

    >
    > > function test(o) {
    > >   o = null;
    > > }

    >
    > > var p = {};
    > > test(p);
    > > window.alert(p); // Not null

    >
    > I think that's a perfect illustration. It's all you need to see to
    > understand that there is no pass-by-reference in JS. (...)


    The same example slightly modified can be used to show that it's a
    pass-by-reference:

    function test (o) { o.j= "Simpson" }
    var p= {};
    test(p);
    p.j
    --> "Simpson"

    The question is, when you say "it's been passed by reference", what
    exactly did you expect *it* to be ?

    1.- var p ?
    2.- the value of var p (which is a reference to an object) ?

    And the answer is in the ES3 specs, 10.1.8, "The initial value (... of
    an argument ...) is *the*value* of the corresponding actual parameter
    supplied by the caller."

    So, while in JS you can't pass a reference to a var, you can't avoid
    to pass objects by reference.
    --
    Jorge.
     
    Ry Nohryb, May 19, 2010
    #18
  19. RobG wrote:

    > Thomas 'PointedEars' Lahn wrote:
    >> RobG wrote:
    >> > williamc wrote:
    >> >> Thomas 'PointedEars' Lahn wrote:
    >> >> > RobG wrote:
    >> >> >> williamc 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?
    >> > The values that are assigned by the calling function.

    >> How can *you* know for sure what *he* meant?

    >
    > You asked what *I* meant, I've explained that.


    Right. Sorry. But in that case, you are dead wrong.

    > [...]
    >> > I think in both cases their values are references because, to me, it
    >> > is less confusing. As I posted eariler, given:

    >>
    >> > var a = 5,
    >> > b = a;

    >>
    >> > You can think of a and b as refering to the same instance of 5.

    >>
    >> But you should not. While Smalltalk undoubtedly is an ancestor of
    >> JavaScript/ECMAScript, by contrast `5' is _not_ an object in ECMAScript
    >> implementations (it is only being implicitly converted to a Number
    >> instance sometimes).
    >>
    >> So, in your words, `b' "refers" to _another_ `5' than `a'.

    >
    > No, in my words, 'b' and 'a' refer to the same '5'. Since that '5'
    > can't be modified, the value of 'b' can only be changed by assigning a
    > new value, even if it's another '5'.


    That's nonsense. Have you subscribed to VK101 by now?

    >> Indeed, the variables `a' and `b' would very likely be implemented as two
    >> pointers pointing to different heap addresses.

    >
    > Maybe, but implementation details are irrelevant.


    No, implementation details are at the core of the issue.

    >> > Anyhow, that's my way of understanding it.

    >> Well, misconceptions are quite common in this field.

    >
    > Apparently - I'll keep this one to myself. BTW, do you have a link to
    > where it was discussed here previously?


    I might have a Message-ID.


    PointedEars
    --
    var bugRiddenCrashPronePieceOfJunk = (
    navigator.userAgent.indexOf('MSIE 5') != -1
    && navigator.userAgent.indexOf('Mac') != -1
    ) // Plone, register_function.js:16
     
    Thomas 'PointedEars' Lahn, May 19, 2010
    #19
  20. Garrett Smith wrote:

    > Stefan Weiss wrote:
    >> On 18/05/10 15:05, David Mark wrote:
    >>> The value passed is a reference to an object. That might sound
    >>> like a contradiction in terms, but consider:-
    >>>
    >>> function test(o) {
    >>> o = null;
    >>> }
    >>>
    >>> var p = {};
    >>> test(p);
    >>> window.alert(p); // Not null

    >>
    >> I think that's a perfect illustration. It's all you need to see to
    >> understand that there is no pass-by-reference in JS. Incidentally,
    >> that's also the way it works in Java, and Java is also the source of the
    >> expression "reference types" that has been thrown around here a couple
    >> of times.

    >
    > The same behavior is seen in Java, however, Java's "reference types" has
    > different meaning that Reference type in ECMAScript.
    >
    > Java Reference Types, from JLS, 3rd Edition, Chapter 4:
    > | The reference types (§4.3) are class types, interface types, and
    > | array types.
    > http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html
    >
    >
    > ECMAScript Reference Type, from ECMAScript Edition 3, s 8.7
    > | The internal Reference type is not a language data type. It is defined
    > | by this specification purely for expository purposes. An
    > | implementation of ECMAScript must behave as if it produced and
    > | operated upon references in the manner described here. However, a
    > | value of type Reference is used only as an intermediate result of
    > | expression evaluation and cannot be stored as the value of a variable
    > | or property.
    >
    > Elsewhere:
    > http://dmitrysoshnikov.com/ecmascript/chapter-8-evaluation-strategy/


    And neither one has anything to do with reference values, as established
    recently.


    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.)
     
    Thomas 'PointedEars' Lahn, May 19, 2010
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. JezB

    Page Closure

    JezB, Dec 3, 2003, in forum: ASP .Net
    Replies:
    1
    Views:
    437
    Cowboy \(Gregory A. Beamer\)
    Dec 3, 2003
  2. Ivan Sutton
    Replies:
    0
    Views:
    359
    Ivan Sutton
    Oct 1, 2003
  3. Simon
    Replies:
    3
    Views:
    5,256
    John C. Bollinger
    Jan 12, 2005
  4. Scott_Marks

    sys.settrace closure interaction bug

    Scott_Marks, Oct 1, 2006, in forum: Python
    Replies:
    0
    Views:
    296
    Scott_Marks
    Oct 1, 2006
  5. Julian Mehnle
    Replies:
    0
    Views:
    240
    Julian Mehnle
    Jul 17, 2003
Loading...

Share This Page