0

Coming from a C++ background, and new to JS, I want to do a deep copy of an object.

Here is what I want to do in OOP language (still learning JS language).

I pass a dummy object of foo class into the constructor of doSomething class.

And each time doSomething needs to do something with foo, it deep copies the dummy foo object, customizes it and stores the new copy into an array.

The array of foo objects should have different foo objects in it. However, all the objects stored in the array "references" the last foo object processed.

It seems to me it stores the reference to the dummy object.

I have tried the approaches suggested in the post What is the most efficient way to deep clone an object in JavaScript? , but did not get what I want. I'd use _.cloneDeep() as example in my code sample below.

========================= code ===========================

I have a foo.js

define(["jquery", "react", "react-dom", "react-components"], 
function($, React, ReactDOM, ReactComponents) {
  "use strict";

  function foo(x, y, z) {
    var $x = x,
        $y = y,
        $z = z;

    function f1 () {}
    function f2 () {}
    function setX(x) {}
    function setY(y) {}
    function whichFoo() {//prints to the console to identify which object it is}

    return {
      f1: f1,
      f2: f2,
      setX: setX,
      setY: setY,
      whichFoo: whichFoo
    };
  }

  return foo;
});

I have an index.html that creates foo and pass it to doSomething.js:

<script>
require(['doSomething', 'foo'], function(doSomething, foo) {
  var aFoo = foo(null, null, null);
  doSomething(aFoo);
}
</script>

Here is the doSomething.js:

define([various libraries], function(various libraries) {
  "use strict";
  function doSomething(aFoo) {

    var dummyFoo = _.cloneDeep(aFoo), // I understand aFoo is a reference so deepcopy it here to create a different object.
        fooList = [];

    // other functions; 

    function run() {
      // an object of ids is created here.
      _.each(ids, callback);
    }

    function callback(k, v) {
      var newX = getX(v),
          newY = getY(v);

      var newFoo = _.cloneDeep(dummyFoo); // creates a copy of object for customization
      // customize newFoo
      newFoo.setX(newX);
      newFoo.setY(newY);

      newFoo.whichFoo(); //verified different foo each time.

      fooList.push(newFoo);
    }

    function loopFooList() {
      for (var i = 0; i < fooList.length; i++) {
        fooList[i].whichFoo(); // every item in the list references the foo created in the last callback...
      }
    }
    return {...};
  }
  return doSomething;
}

In my understanding, _.cloneDeep() creates an object in a different memory location a new object of the cloned one, and returns the reference to the new object. So even though fooList stores references (not the actual object), they should reference to their respective object, why in the end they reference to the last object created?

I somehow feel deepcopy in JS sense is different from that of C++. Could anyone educate me why my code did not work the way it is intended and point out a way in JS to achieve what I want (deep copy the object in C++ sense)?

P.S: The reason I used this weird approach of customizing dummy object instead of, say, creating a new instance of foo in doSomething each time I need it, is because I need to avoid react components being loaded with doSomething which would cause timeout in test (but it does not load the index.html for test), which I cannot change.

So this is a hack:) Yet it does not affect the result of deep copy.

aa51
  • 75
  • 1
  • 9
  • Why do you think that each element in the list is the last object that was created? How do you test that? What does `whichFoo`? But they share the same `$x`, `$y` and `$z`, that can create the impression, that they are all the same object. – t.niese Mar 17 '18 at 17:47
  • Here is what I want to do: 1) I have a dummy object. 2) I want to create five new objects from the dummy object by deepcopying the dummy object. 3) I store the five new objects in an array for later use. I thought the five new objects stored in the array should be the different, because I deepcopied them and after which they are different objects, but in fact they all referenced to the last object created out of dummy object.@NinaScholz – aa51 Mar 17 '18 at 17:51
  • @t.niese I tested them by running loopFooList(), and whichFoo() has console.log() in it which always prints the signature properties of the last object created. – aa51 Mar 17 '18 at 17:53
  • `$x`, `$y` and `$z` are shared accross all the cloned object because they are not part of the object, but part of the closures that are created. If you do `fooList[0] === fooList[1]` you will see that those objects are different. But you cannot clone those variables that are accessed through the closure. This pattern is often used as a hack to emulate private members, but that's exactly the downside of that hack. – t.niese Mar 17 '18 at 17:57
  • @t.niese Ok, I see what you are saying. It's about closure. So is there a way (not necessarily through closure) to construct foo that $x, $y, $z can be cloned as well? – aa51 Mar 17 '18 at 18:04
  • You can only make `$x`, `$y` and `$z` clonable if they are properties of the object, and as of that accessable from everywhere. – t.niese Mar 17 '18 at 18:07
  • @t.niese I may have to go this way. Thanks for your inputs! – aa51 Mar 18 '18 at 16:27

0 Answers0