0

Can someone please explain me how to change template.portNumber value ?

var template = {
  portNumber: null,
  stuff: ""
}

myfunc(template, 3);

function myfunc(template, count) {
  var ports = {}
  for (var i = 0; i < count; i++) {
    var portNumber = i + 1;
    ports[portNumber.toString()] = template;
    ports[portNumber.toString()].portNumber = portNumber;
  }
  console.debug(JSON.stringify(ports, null, 4));
  return ports;
}

Result:

"{
    "1": {
        "portNumber": 3,
        "stuff": ""
    },
    "2": {
        "portNumber": 3,
        "stuff": ""
    },
    "3": {
        "portNumber": 3,
        "stuff": ""
    }
}"

Expected:

"{
    "1": {
        "portNumber": 1,
        "stuff": ""
    },
    "2": {
        "portNumber": 2,
        "stuff": ""
    },
    "3": {
        "portNumber": 3,
        "stuff": ""
    }
}"

Sorry for the stupid question but i really stuck with it. Same code works well in python. Thanks.

Kventin
  • 13
  • 1

5 Answers5

3

Your array ends up having three references to the same object so each time you mutate it the change is visible in all array elements.

Writing ports[0].port = "99" will in other words change also ports[1].port because ports[0] and ports[1] are the very same object.

You need to create a copy of the object instead...

6502
  • 112,025
  • 15
  • 165
  • 265
3

The reason all array object are reference type so point to only one instance.

Try using constructor function like this.

var template = function(portno, stf){
  this.portNumber = portno;
  this.stuff = stf;
}

myfunc(template, 3);

function myfunc(template, count) {
  var ports = {}
  for (var i = 0; i < count; i++) {
    var portNumber = i + 1;
    ports[portNumber.toString()] = new template(portNumber , template.stuff);
  }
  console.debug(JSON.stringify(ports, null, 4));
  return ports;
}
Jenish Rabadiya
  • 6,708
  • 6
  • 33
  • 62
  • `new template(portno, template.stuff);` should be `new template(portNumber, template.stuff);`. Also, since you're passing `portNumber` to `template`, you can remove the line `ports[portNumber.toString()].portNumber = portNumber`. – sloth Jan 23 '15 at 07:51
1

The template object is passed by reference, so all the items refer to the same object. It ends up looking a little like this:

template = {portNumber: 3, stuff: ""};
return {ports: {1:template, 2: template, 3: template}}

You need to clone the object, and then set it.

var template = {
  portNumber: null,
  stuff: ""
}

myfunc(template, 3);

function myfunc(template, count) {
  var ports = {}
  for (var i = 0; i < count; i++) {
    var portNumber = i + 1;
    ports[portNumber] = JSON.parse(JSON.stringify(template));
    ports[portNumber].portNumber = portNumber;
  }
  console.debug(JSON.stringify(ports, null, 4));
  return ports;
}

Also, you don't need to manually stringify a numerical key, it's done automatically.

Community
  • 1
  • 1
Scimonster
  • 32,893
  • 9
  • 77
  • 89
0

This is a reference problem.

console.log(myFunc(template, 3));

function myFunc(template, count) {
  var ports = {}
  for (var i = 0; i < count; i++) {
    var portNumber = i + 1;
    ports[portNumber.toString()] = {portNumber:null, stuff:""};
    ports[portNumber.toString()].portNumber = portNumber;
  }
  // console.debug(JSON.stringify(ports, null, 4));
  return ports;
}
0

It's because template variable in your function holds the reference of the template object outside your function. Try this:

 function myFunc (template, count) {
var ports = {};
for(var i = 0; i < count; i++) {
    var portNumber = i + 1;
    var tmplt = JSON.parse(JSON.stringify(template));
    tmplt.portNumber = portNumber;
    ports[portNumber + ''] = tmplt;
}
return ports;
    }