Easy Variable Scope question...

Discussion in 'Javascript' started by Mike P, Oct 28, 2005.

  1. Mike P

    Mike P Guest

    I have, what should be, a simple scope problem. Can you help me fix this?

    I'm trying to end up like this:
    originalArray = [1,2,7] and newArray = [6,7,12].

    Instead I wind up like this:
    originalArray = [6,7,12] and newArray = [6,7,12].

    Here's my code:

    var originalArray = [1,2,7]; /* I'm pulling this from a form and want
    to keep it as is, but the function modifies it */
    var newArray = createNewArray( originalArray ); /* I want to wind up
    with newArray = [6,7,12] */

    function createNewArray( x ) {
    for ( var i = 0; i < x.length; i++ ) { x += 5 }
    return x;
    }

    I've also tried this:

    function createNewArray( x ) {
    var y = x;
    for ( var i = 0; i < y.length; i++ ) { y += 5 }
    return y;
    }

    and this:

    var originalArray = [1,2,3];
    var tmpArray = originalArray;
    var newArray = createNewArray( tmpArray );

    function createNewArray( x ) {
    for ( var i = 0; i < x.length; i++ ) { x += 5 } return x;
    }

    all with the same disasterous results.

    Thanks!

    Mike
     
    Mike P, Oct 28, 2005
    #1
    1. Advertising

  2. Mike P

    web.dev Guest

    Mike P wrote:
    > I have, what should be, a simple scope problem. Can you help me fix this?
    >
    > I'm trying to end up like this:
    > originalArray = [1,2,7] and newArray = [6,7,12].
    >
    > Instead I wind up like this:
    > originalArray = [6,7,12] and newArray = [6,7,12].
    >
    > Here's my code:
    >
    > var originalArray = [1,2,7]; /* I'm pulling this from a form and want
    > to keep it as is, but the function modifies it */
    > var newArray = createNewArray( originalArray ); /* I want to wind up
    > with newArray = [6,7,12] */
    >
    > function createNewArray( x ) {
    > for ( var i = 0; i < x.length; i++ ) { x += 5 }
    > return x;
    > }
    >
    > I've also tried this:
    >
    > function createNewArray( x ) {
    > var y = x;
    > for ( var i = 0; i < y.length; i++ ) { y += 5 }
    > return y;
    > }
    >
    > and this:
    >
    > var originalArray = [1,2,3];
    > var tmpArray = originalArray;
    > var newArray = createNewArray( tmpArray );
    >
    > function createNewArray( x ) {
    > for ( var i = 0; i < x.length; i++ ) { x += 5 } return x;
    > }
    >
    > all with the same disasterous results.
    >
    > Thanks!
    >
    > Mike


    Hi Mike,

    You were very close to the solution, taking one of your solutions from
    above and modified it as follows will work:

    function createNewArray(x)
    {
    var y = new Array();

    for (var i = 0; i < x.length; i++)
    {
    y = x + 5
    }

    return y;
    }

    var originalArray = [1, 2, 7];
    var newArray = createNewArray(originalArray);

    You were missing the following:

    var y = new Array();

    It was because you were referencing the same Array that was causing the
    problem. If you explicitly created a new array, that will solve your
    problem.
     
    web.dev, Oct 28, 2005
    #2
    1. Advertising

  3. Mike P

    Lee Guest

    Mike P said:
    >
    >I have, what should be, a simple scope problem. Can you help me fix this?
    >
    >I'm trying to end up like this:
    > originalArray = [1,2,7] and newArray = [6,7,12].
    >
    >Instead I wind up like this:
    > originalArray = [6,7,12] and newArray = [6,7,12].
    >
    >Here's my code:
    >
    > var originalArray = [1,2,7]; /* I'm pulling this from a form and want
    >to keep it as is, but the function modifies it */
    > var newArray = createNewArray( originalArray ); /* I want to wind up
    >with newArray = [6,7,12] */
    >
    > function createNewArray( x ) {
    > for ( var i = 0; i < x.length; i++ ) { x += 5 }
    > return x;
    > }


    No matter how you assign an array variable to another variable,
    you are only assigning a reference to the original array.
    You need to create an entirely new array:

    function createNewArray(x) {
    var y=new Array(x.length);
    for(var i=0;i<x.length;i++) {
    y=x+5;
    }
    return y;
    }
     
    Lee, Oct 28, 2005
    #3
  4. Mike P

    Mike P Guest

    Thanks... got it :)

    Mike
     
    Mike P, Oct 28, 2005
    #4
  5. Mike P

    RobG Guest

    Mike P wrote:
    > Thanks... got it :)
    >


    The fastest way to copy an array is to use its concat() method:

    var A = [1, 2];
    var B = A.concat();

    Done.

    concat() was introduced with JavaScript 1.2, so maybe some 'version 4'
    browsers won't have it, but any even remotely modern browser will.

    The usual caveat applies - elements of A that are objects (arrays or
    whatever) are 'copied' as references. The other solutions offered do
    the same.

    --
    Rob
     
    RobG, Oct 29, 2005
    #5
  6. Mike P

    Mike P Guest

    Thanks RobG.... you're quickly becoming my best friend :)

    Mike
     
    Mike P, Oct 29, 2005
    #6
  7. Mike P

    Mike P Guest

    array's by reference revisited?

    "RobG" <> wrote in message
    news:4362c0d0$0$21679$...
    > The fastest way to copy an array is to use its concat() method:
    >
    > var A = [1, 2];
    > var B = A.concat();


    I got this... tried it with a simple array, and it worked. Now, I've
    restructured things a bit by mixing arrays and objects. And, it's broken.
    Is there something that I need to do to make sure this complex mix of
    objects and arrays is copied, not referenced with an object?

    Here's my code:

    var A = {name: "name", contents: [{a:1, b:1},{a:6, b:3}]};
    var B = {name: "newname"};
    B.contents = A.contents.concat();
    B.contents[0].a = 99;
    document.write("This should be 1, but it equals " + A.contents[0].a);

    Thanks again, for the assist!

    Mike
     
    Mike P, Nov 8, 2005
    #7
  8. Mike P

    RobG Guest

    Re: array's by reference revisited?

    Mike P wrote:
    > "RobG" <> wrote in message
    > news:4362c0d0$0$21679$...
    >> The fastest way to copy an array is to use its concat() method:
    >>
    >> var A = [1, 2];
    >> var B = A.concat();

    >
    > I got this... tried it with a simple array, and it worked. Now, I've
    > restructured things a bit by mixing arrays and objects. And, it's broken.


    Only types that are passed by value (strings, numbers) will be copied,
    anything passed by reference (e.g. objects, arrays, functions) will have
    a referenced passed.


    > Is there something that I need to do to make sure this complex mix of
    > objects and arrays is copied, not referenced with an object?


    Yes, look at what the thing is then do the right thing. The more
    complex you make the stuff you put in there, the more complex the
    operation becomes.

    At some point you realise it is easier to create your own custom objects
    (probably using a constructor) and give them the methods they need to
    pass values.

    >
    > Here's my code:
    >
    > var A = {name: "name", contents: [{a:1, b:1},{a:6, b:3}]};
    > var B = {name: "newname"};
    > B.contents = A.contents.concat();


    For A, you may want to give it a getContents() method so you can do
    something like:

    B.contents = A.getContents();

    or similar. You need to learn a bit about designing classes (although
    JavaScript doesn't have classes, the concept of constructor functions
    for objects is very similar) and interfaces to know how to do this properly.

    Anyhow, a quick 'n dirty copy function (sorry, you'll have to tidy this
    up yourself...):

    function copyThing(x)
    {
    if ( 'number' == typeof x) return x;
    if ( 'string' == typeof x) return x;
    if ( 'object' == typeof x){
    if (x.constructor && Array == x.constructor) {
    var z = [];
    for (var i=0, len=x.length; i<len; ++i){
    z = copyThing(x);
    }
    return z;
    }
    if (x.constructor && Object == x.constructor) {
    var z = {};
    for (prop in x){
    z[prop] = copyThing(x[prop]);
    }
    return z;
    }
    }
    return 'Fell through: ' + x.constructor;
    }

    // Call using:
    B.contents = copyThing(A.contents);

    // Just to prove we did copy B:
    alert(
    'A.contents[1][\'a\']: ' + A.contents[1]['a']
    + '\n' +
    'B.contents[1][\'a\']: ' + B.contents[1]['a']
    );

    B.contents[1]['a'] *= 3;

    alert(
    'A.contents[1][\'a\']: ' + A.contents[1]['a']
    + '\n' +
    'B.contents[1][\'a\']: ' + B.contents[1]['a']
    );



    Note that it doesn't deal with functions, booleans, etc. so if you want
    to stuff those into objects then copy them you'll need to add more if
    statements. You can write a similar function that gets the contents of
    the objects and prints them out so you can check the properties/contents.




    --
    Rob
     
    RobG, Nov 8, 2005
    #8
  9. Mike P

    VK Guest

    Re: array's by reference revisited?

    Besides RobG answer in the above posting:

    If you are interested in a versatile data serialization media you may
    also check JSON way:
    <http://www.crockford.com/JSON/>
     
    VK, Nov 8, 2005
    #9
  10. Re: array's by reference revisited?

    RobG wrote:

    > Mike P wrote:
    >> "RobG" <> wrote in message
    >> news:4362c0d0$0$21679$...
    >>> The fastest way to copy an array is to use its concat() method:
    >>> var A = [1, 2];
    >>> var B = A.concat();

    >>
    >> I got this... tried it with a simple array, and it worked. Now, I've
    >> restructured things a bit by mixing arrays and objects. And, it's
    >> broken.

    >
    > Only types that are passed by value (strings, numbers) will be copied,
    > anything passed by reference (e.g. objects, arrays, functions) will have
    > a referenced passed.


    There is no such thing as "pass by reference" in JS/ECMAScript,
    object references are values.


    PointedEars
     
    Thomas 'PointedEars' Lahn, Nov 8, 2005
    #10
  11. Mike P

    Mike P Guest

    Re: array's by reference revisited?

    "Thomas 'PointedEars' Lahn" <> wrote in message
    news:...

    > There is no such thing as "pass by reference" in JS/ECMAScript,
    > object references are values.
    >
    > PointedEars


    PE,

    Thank God you're here! Without your valued assistance, I would be learning
    and accomplishing wonderful work, yet simultaneously falling victim to these
    tragic faux pas. Keep up the good work.

    :)

    Mike
     
    Mike P, Nov 8, 2005
    #11
  12. Mike P

    Mike P Guest

    Re: array's by reference revisited?

    "RobG" <> wrote in message
    news:jmXbf.1370$...

    > At some point you realise it is easier to create your own custom objects
    > (probably using a constructor) and give them the methods they need to pass
    > values.


    Very good point. It's clearly an area I need to study a bit more... so I'm
    doing just that.

    > For A, you may want to give it a getContents() method so you can do
    > something like:
    >
    > B.contents = A.getContents();


    Thanks... and thanks for the code sample. I get the sense that my code will
    be a lot cleaner, easier to work with, and easier to follow if I take
    advantage of custom objects and their methods.

    Mike
     
    Mike P, Nov 8, 2005
    #12
  13. Re: array's by reference revisited?

    In article <>, Thomas 'PointedEars'
    Lahn <> writes
    >RobG wrote:
    >

    <snip>
    >> Only types that are passed by value (strings, numbers) will be copied,
    >> anything passed by reference (e.g. objects, arrays, functions) will have
    >> a referenced passed.

    >
    >There is no such thing as "pass by reference" in JS/ECMAScript,
    >object references are values.


    Object references are values, yes, and are what's passed, yes, but the
    things referenced are passed by reference.

    What's confusing P.Ears is that the programmer has no choice in
    javascript about how anything is passed. As a result, "passed by value"
    and "passed by reference" are phrases that don't have much use when
    talking about javascript. However, if you're comparing javascript with
    other languages or with general computer principles then they are useful
    (and there is such a thing).

    John
    --
    John Harris
     
    John G Harris, Nov 8, 2005
    #13
  14. Re: array's by reference revisited?

    John G Harris <> writes:

    > Object references are values, yes, and are what's passed, yes, but the
    > things referenced are passed by reference.


    The confusement here comes from "pass by reference" having an existing
    meaning that is different from how you are using it. Passing by
    reference means passing an l-value, so it makes no sense to say that
    an object is being passed by reference.

    > What's confusing P.Ears is that the programmer has no choice in
    > javascript about how anything is passed. As a result, "passed by value"
    > and "passed by reference" are phrases that don't have much use when
    > talking about javascript.


    They do, in describing how Javascript passes its arguments of
    functions: by value, *not* by reference.

    /L
    --
    Lasse Reichstein Nielsen -
    DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html>
    'Faith without judgement merely degrades the spirit divine.'
     
    Lasse Reichstein Nielsen, Nov 8, 2005
    #14
    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. Hazzard
    Replies:
    2
    Views:
    663
    Hazzard
    Apr 6, 2004
  2. Bruno Desthuilliers
    Replies:
    5
    Views:
    401
    Bruno Desthuilliers
    Aug 29, 2007
  3. bwv549
    Replies:
    1
    Views:
    113
    Carlos
    Sep 6, 2007
  4. David Filmer
    Replies:
    19
    Views:
    257
    Kevin Collins
    May 21, 2004
  5. Andrew Falanga
    Replies:
    2
    Views:
    205
    Andrew Falanga
    Nov 22, 2008
Loading...

Share This Page