-1

I have the following problem:

A library is returning a reference on an object. Now I don‘t want to modify just single parts of the object, I want completely override the object.

My code looks like the following:

var options=getOptions();
options=newOptions;
// now do something with the new options.

But when I’m running this code, the reference will be removed and a new one will be set.

So how can I copy a whole new object to the reference?

Jesse
  • 3,522
  • 6
  • 25
  • 40

4 Answers4

0

You're replacing the object you're referring to with options, but that has no effect on any reference to the original object the library has. There's nothing you can do with the return value of getOptions that will replace the object the lib has with an entirely new object; all you can do is change the state of the object it gives you (adding, changing, and/or removing properties).

Unless the library provides you a way to change the object it refers to internally, you can't completely replace that object (without modifying the library).

Here's an example to illustrate:

// Emulating the library:
var lib = (function() {
  var libOptions = {
    name: "original"
  };
  
  return {
    // The operation you said it has
    getOptions: function() {
      return libOptions;
    },
    // The operation it would need to have
    setOptions: function(newOptions) {
      libOptions = newOptions;
    }
  };
})();

var options = lib.getOptions();
options = {
  name: "replaced"
};

console.log(options.name);          // "replaced"
console.log(lib.getOptions().name); // "original"

lib.setOptions(options);

console.log(options.name);          // "replaced"
console.log(lib.getOptions().name); // "replaced"

When the library gives you a reference to its object, you have something like this in memory:

libOptions−−+
            |
            |   +−−−−−−−−−−−−−−−−−−+
            +−−>|     (object)     |
            |   +−−−−−−−−−−−−−−−−−−+
            |   | name: "original" |
options−−−−−+   +−−−−−−−−−−−−−−−−−−+

Then when you set options to something else:

                +−−−−−−−−−−−−−−−−−−+
libOptions−−−−−>|     (object)     |
                +−−−−−−−−−−−−−−−−−−+
                | name: "original" |
                +−−−−−−−−−−−−−−−−−−+

                +−−−−−−−−−−−−−−−−−−+
options−−−−−−−−>|     (object)     |
                +−−−−−−−−−−−−−−−−−−+
                | name: "replaced" |
                +−−−−−−−−−−−−−−−−−−+

As you can see, setting options doesn't have any effect on the library's reference in libOptions.

That's why the lib would have to provide setOptions.

Of course, again, you can change the state of the object (provided the library isn't giving you a defensive copy or a frozen object);

options.name = "updated";

which does this:

libOptions−−+
            |
            |   +−−−−−−−−−−−−−−−−−−+
            +−−>|     (object)     |
            |   +−−−−−−−−−−−−−−−−−−+
            |   | name: "updated"  |
options−−−−−+   +−−−−−−−−−−−−−−−−−−+
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
0

What I understand from your question is that you want to deep copy the object so that original object is intact and you can modify its copy. Correct me if wrong.

var options=getOptions();

var copyOfObject = JSON.parse( JSON.stringify( options ));
mukesh.kumar
  • 1,100
  • 16
  • 30
0

From what I understand, you are getting an object from a library and you want to change some keys while keeping the rest of the object the same.

If it's only a few properties that you want to change, you can just assign the values on the object you recieve form the library:

function getLibObject() {
  return {
    constantKey: 'constant',
    overridenKey: 'to be overriden',
  };
}
var libObject = getLibObject();
libObject.overridenKey = "has been overriden";
libObject.newKey = "A new key has been added";
console.log(JSON.stringify(combinedObject)); //{"constantKey":"constant","overridenKey":"has been overriden","newKey":"A new key has been added"}

If the keys in the object you want to change is only one level deep, you can use Object.assign to create a new 'shallow merged' object. (Depending on the browsers you want to support, you may need a polyfill)

function getLibObject() {
  return {
    constantKey: 'constant',
    overridenKey: 'to be overriden',
  };
}
var libObject = getLibObject();
var newOptions = {
  overridenKey: 'has been overriden',
  newKey: 'A new key has been added'
};
var combinedObject = Object.assign({}, libObject, newOptions);
console.log(JSON.stringify(combinedObject)); //{"constantKey":"constant","overridenKey":"has been overriden","newKey":"A new key has been added"}

If you want your merge to be deeper than just one level, Object.assign won't work. You can use utility functions like [Lodash merge] or use some of the SO answers which solve this

function getLibObject() {
  return {
    constantKey: 'constant',
    nestedKey: {
      deepConstantKey: 'This is nested at the second level and should not change',
      deepOverrideKey: 'This is nested at the second level and should be overriden'
    }
  };
}
var libObject = getLibObject();
var newOptions = {
  nestedKey:{
     deepOverrideKey: 'This value has been overriden'
  }
};
var combined = _.merge({}, libObject, newOptions);
console.log(JSON.stringify(combined))
//{"constantKey":"constant","nestedKey":{"deepConstantKey":"This is nested at the second level and should not change","deepOverrideKey":"This value has been overriden"}}
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.5/lodash.min.js"></script>
Chirag Ravindra
  • 4,760
  • 1
  • 24
  • 35
0

Thank for your help. I understand the problem.

I fixed now the problem in a really dirty way... When i have modifikated options i destroy the lib object and create a new one. It’s not the fine way but a solution.