0

I've tried googling this pretty extensively, but the relevant search terms are pretty vague and I haven't been able to find anything.

The object is coming from a third-party library (Jibestream).

Here's some hypothetical code:

const myObject = thirdPartyLibrary.getMyObject();

If I do console.log(myObject), I see this in my Chrome DevTools:

code screenshot

It looks like an object, but has this n key that appears to be some identifier.

When I try to copy it, like so:

const newWaypointsArray = getNewWaypoints();
const myNewObject = { ...myObject, waypoints: newWaypointsArray };

And then do console.log(myNewObject), I see this:

enter image description here

Which is the same, but without the n identifier.

Passing this new n-less object back into methods provided by the third-party library doesn't work, while using the original object does work. I have to assume it's related to that n identifier.

  1. Would that theory make sense, that their library would need to retain this identifier and that's why it's not working?
  2. Is there a way to copy the object without losing that identifier?

Thanks in advance.

3limin4t0r
  • 19,353
  • 2
  • 31
  • 52
Evan Winter
  • 373
  • 2
  • 7

1 Answers1

1

Like already stated in the comments n is the class name of the object. This is most likely the reason passing myNewObject to the third party library doesn't work. The library will most likely use one of the prototype functions available on the class of the object.

The best way to make a copy of an object is to use a provided method when available. For example array.slice() will create a shallow copy as stated in its documentation.

If the class isn't documented or there is no copy method available you can always get the prototype of the received object and use that to create a new object. Then copy over the instance properties:

const myObject = thirdPartyLibrary.getMyObject();

// create an object using the same prototype
const copy = Object.create(Object.getPrototypeOf(myObject));
// copy over properties
Object.defineProperties(copy, Object.getOwnPropertyDescriptors(myObject));

After creating the copy you can freely update its properties without effecting the original object. Note that copy is still a shallow copy. So changing postCopy.creator.username = "something_else" would change the original, since you are not mutating the copy (both the original and copy point to the same creator). See the link for more info.

// mock
class Person {
  constructor(name) {
    this.name = name;
  }
  greet() {
    return `hello ${this.name}`;
  }
}

const thirdPartyLibrary = {
  getMyObject() {
    return new Person("John Doe");
  },
  useMyObject(person) {
    return person.greet();
  },
};

// answer
const myObject = thirdPartyLibrary.getMyObject();

const copy1 = {...myObject}; // your current attempt
try {
  console.log("copy1:", thirdPartyLibrary.useMyObject(copy1));
} catch (error) {
  console.log("copy1:", error.message);
}

const copy2 = Object.create(Object.getPrototypeOf(myObject));
Object.defineProperties(copy2, Object.getOwnPropertyDescriptors(myObject));

console.log("copy2:", thirdPartyLibrary.useMyObject(copy2));

References:

3limin4t0r
  • 19,353
  • 2
  • 31
  • 52