-1

Or can it? This may sound like a dumb question... and I'm really hoping it is because my initial Googling about lead me to believe that there is no simple way to copy an object in JavaScript.

Say you have the following:

    var allFood = ['fish', 'greens', 'fruit', 'candy', 'soda', 'cookies'];
    var moreFood = allFood;
    var diffFood = allFood;
    moreFood.splice(3, 0, "grain", "juice");
    diffFood.splice(3, 3, "tacos", "meat");
    document.write(allFood + "<br/>");
    document.write(diffFood);

Now they all equal "fish,greens,fruit,tacos,meat,soda,cookies" which is annoying, for lack of a better word.

Could you explain why JavaScript has this limitation?

And yeah, I read this: What is the most efficient way to deep clone an object in JavaScript? which seems a little cumbersome and actually failed when I tried it with the above example...

Community
  • 1
  • 1
Methodician
  • 2,396
  • 5
  • 30
  • 49
  • 2
    Possible duplicate of [Is JavaScript a pass-by-reference or pass-by-value language?](http://stackoverflow.com/questions/518000/is-javascript-a-pass-by-reference-or-pass-by-value-language) – Rex M Nov 27 '15 at 23:35
  • Your question is answered in the linked "duplicate" thread. – Rex M Nov 27 '15 at 23:35
  • Possible duplicate of [Most elegant way to clone a JavaScript object](http://stackoverflow.com/questions/728360/most-elegant-way-to-clone-a-javascript-object) – Gökay Gürcan Nov 27 '15 at 23:40
  • When @RexM 's suggestion is not enough, you can also check out this one. – Gökay Gürcan Nov 27 '15 at 23:40
  • Yeah I linked that one already in my question, @GökayGürcan and no, Rex's suggestion helps clarify the behavior but doesn't really get to the question... – Methodician Nov 27 '15 at 23:43
  • 1
    Note that you seem to be talking about copying an array in javascript, not what is considered a javascript object with key/value pairs. You can use `moreFood = allFood.slice()` to get the value of allFood without the reference to the original variable. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice – Hypaethral Nov 27 '15 at 23:43
  • I suppose they didn't want to have a language with pointers yet still wanted a "pass by value" language. So it's either have applications that run extremely slow because of all the copying, or have composite types be reference types. –  Nov 27 '15 at 23:46
  • 1
    Passing objects by copying them into the called environment would be extraordinarily complex if you think about it. Like, exactly how would that work? What would be the semantics? Would you do a deep copy? How would you copy references to closures? Performance would be atrocious and the semantics would be insanely complicated. – Pointy Nov 27 '15 at 23:55
  • Also, now that I re-read the question, *this has absolutely nothing to do with parameter passing.* – Pointy Nov 28 '15 at 00:02
  • @Methodician What language are you most familar with? I may help inform how best to answer. – Ben Aston Nov 28 '15 at 00:59
  • @BenAston I'm most familiar with C#. There, it seems you have a lot of control over how variables are assigned or copied, by reference or value, etc... which makes it much easier to juggle data. I came across this limitation while learning JavaScript and I just wanted to create one array one time, then test a variety of array functions on it... My question shows a little piece of this process and how it fell apart and lead me to Googling and Foruming. – Methodician Nov 29 '15 at 19:17
  • @Methodician The behavior of JavaScript is the same as for C# though. Objects are "passed by value of the reference" and certain built-in types are passed by value for the purposes of performance and meeting programmer expectation. Where does it differ? You use the word "limitation". There is no limitation in JavaScript in this regard. – Ben Aston Nov 29 '15 at 19:52

3 Answers3

2

For your specific example, i.e. for arrays with simple elements, the slice method can do it:

var allFood = ['fish', 'greens', 'fruit', 'candy', 'soda', 'cookies'];
var moreFood = allFood.slice();
var diffFood = allFood.slice();

This method creates a so-called shallow copy of the array. So it does the job for arrays with primitives, such as strings, numbers and booleans.

If an array element is an object, that object reference is copied, and so the arrays share the original object:

var a = [{x: 1}];
var b = a.slice();
// both arrays reference the same object:
console.log(a[0] === b[0]); // output: true
// so...
b[0].x = 2;
console.log(a[0].x); // output: 2 
trincot
  • 317,000
  • 35
  • 244
  • 286
1

You can read about Javascript's pass-by-reference and pass-by-value behaviour here.

For cloning javascript object you can use lodash library.

var allFood = ['fish', 'greens', 'fruit', 'candy', 'soda', 'cookies'];
var moreFood = lodash.cloneDeep(allFood);

Now changes you make to allFood wouldn't affect moreFood and vice versa.

Community
  • 1
  • 1
Kunal Kapadia
  • 3,223
  • 2
  • 28
  • 36
-1

A simple way to clone objects available in es6, though current supported by most browsers is Object.assign

var original = [1, 2, 3];
var copy = [];

Object.assign(copy, original);

copy.push(2);
//=> [1, 2, 3, 2]

console.log(original);
// => [1, 2, 3];
Jonah Williams
  • 20,499
  • 6
  • 65
  • 53