HiDefLoLife HiDefLoLife - 9 days ago 6
Node.js Question

Why does a new object constructor overwrite a previous object?

I used the following question as a guide for my application's Device object: Node.js - use of module.exports as a constructor, but it appears that the first object created is overwritten by a subsequent object constructor.

My object file (MyDevice.js) is as follows:

function Device(port) {
// Load the default device model from JSON file
var model = require(SomeJSONFile);

// Update port in the model
model.port = port;

// Update object's model
this.model = model;
}

Device.prototype.GetPort = function () {
return this.model.port;
}

module.exports = Device;// Export


In my application (test.js), I do create the objects and print the results:

var Device = require("./devices/MyDevice.js");
var device1 = new Device(1);
console.log("device1 port=" + device1.GetPort());
var device2 = new Device(2);
console.log("device2 port=" + device2.GetPort());
console.log("device1 port=" + device1.GetPort());


I'm not sure why I get the following output:

> node test.js
device1 port=1
device2 port=2
device1 port=2 <--????


It appears that the device1 object is overwritten - why would this happen?




Here is the modified code based on @undefined's answer:

My object file (MyDevice.js):

function Device(port) {
// Load the default device model from JSON file
var model = require(SomeJSONFile);
this.model = JSON.parse(JSON.stringify(model));// 'Unique-ify' model
this.model.port = port;// Set model parameter(s)
}

Device.prototype.GetPort = function () {
return this.model.port;
}

// Export factory function
module.exports = function(port) {
return new Device(port)
}


My application (test.js):

var device1 = require("./devices/MyDevice.js")(1);// Call factory function with port=1
console.log("device1 port=" + device1.GetPort());
var device2 = require("./devices/MyDevice.js")(2);// Call factory function with port=2
console.log("device2 port=" + device2.GetPort());
console.log("device1 port=" + device1.GetPort());


device2 no longer overwrites device1 - the output is:

device1 port=1
device2 port=2
device1 port=1


device1 != device2 and because of cloning of the model, device1.model != device2.model.

Answer

Node modules work like singletons. When you require a module, node doesn't create a new object, it returns the same object, so in this case both instances use the same model.

You can test this by using the following conditions:

device1.model === device2.model // should return `true`   
device1 === device2 // should return `false`, 2 different instances

How would I get around this?

For having unique models (objects), you have several options:

Export a factory function

You can define a function that returns an object:

module.exports = function() {
   return { ... };
}

Now you can require the module and call the exported function.

var newModel = require('path/to/module')();

Clone the object

Another option is cloning the object. The following snippet uses ECMAScript2015's Object.assign which creates a shallow copy of the object.

var clonedModel = Object.assign({}, model);
Comments