5

I am cloning an array of objects using slice() but when I pass that cloned array into another method the array's contents are losing their references and become undefined.

class Chooser
  constructor: (@order, @items) ->
    # do stuff

  choose: ->
    console.debug "Choosing", @order.size, "from", @items.slice()
    @process(@order.size, @items.slice())
    # do stuff

  process: (count, items) ->
    console.debug "count", count
    console.debug "items", items
    console.debug "@items", @items
    # do recursive stuff that includes an items.shift()

The first console.debug gives me, as expected:

Choosing 10 items from [Item, Item]

where Item and Item are exactly what I expected.

But then the next console.debug lines give me

count 10
items [undefined x 2]
@items [Item, Item]

I understand that @items.slice() creates a shallow copy of @items, and as such the objects within the array are references to the same Item objects. The Item objects obviously still exist as they are still in the original @items array.

Why, do the objects in the cloned array seem to lose their references once within the process method?

See this Working example of the problem converted to Javascript

Dave Sag
  • 13,266
  • 14
  • 86
  • 134
  • 2
    Please post a link to an example running on jsfiddle, jsbin, codepen, requirebin or something like that and then tell us what you see and what you expect instead. It doesn't make a lot of sense to debug a problem that you say exists but others in the comments say it doesn't. – rsp May 23 '15 at 10:40
  • 1
    I've managed to reproduce the error but could not get the coffee script site to generate a sensible url. see [this jsfiddle](http://jsfiddle.net/k0quf8v2/) however which is converted to javascript from coffee script. It reproduces the error. – Dave Sag May 23 '15 at 11:53
  • @DaveSag: I suggest copying the relevant code from the fiddle **into** the question, as the code there doesn't have the bit removing the entries from the array, which causes the problem with the console later. This ensures that questions remain useful for people in the future, as external links rot, and SO is meant to be essentially self-contained. – T.J. Crowder May 24 '15 at 14:13

1 Answers1

2

See this answer for what is happening in your code:

https://stackoverflow.com/a/24176638/635411

As you can see the slicing is working fine:

var MyClass = (function() {
  
  function MyClass(items) {
    this.items = items;
  }
  
  MyClass.prototype.fn1 = function() {
    console.log(this.items);
    this.fn2(this.items.slice());
  };
  
  MyClass.prototype.fn2 = function(items){
    console.log(items);
  };
  
  return MyClass;
})();

new MyClass([{id:1, name:'a'}, {id:2, name:'b'}]).fn1();

What you are seeing is that your array is being shifted before you expanded it in the console. If you actually stringify the object you can see that it was successfully passed in.

var MyClass = (function() {
  
  function MyClass(items) {
    this.items = items;
  }
  
  MyClass.prototype.fn1 = function() {
    console.log(this.items);
    this.fn2(this.items.slice());
  };
  
  MyClass.prototype.fn2 = function(items){
    console.log(items);
    console.log(JSON.stringify(items, null, 2));
    items.shift();
    items.shift();
  };
  
  return MyClass;
})();

new MyClass([{id:1, name:'a'}, {id:2, name:'b'}]).fn1();
Community
  • 1
  • 1
dting
  • 38,604
  • 10
  • 95
  • 114