clone object with functions inside
Asked Answered
C

3

7

I am creating a game with many objects, these objects all have their own functions that get called. I have one object that does not do anything and is just for cloning, when this object is cloned everything but the functions get cloned. the x-y gets cloned as well as other this like weight and strength. but the functions don't get cloned. The method I use for cloning is this.

objects[1] = JSON.parse(JSON.stringify(objects[0]))

This is not the only clone method I have tried, but all of them gave me the same result. I expect this to clone the object from objects[0] to objects[1] with everything including functions. (they are in an array so I can execute their functions). But only everything but functions are cloned.

Here is an example I made in node.js. (I don't have the anything solid in code as I like to test if it will work before putting it all together).

var original = {};
original.a = true;
original.b = null;
original.c = 82;
original.d = "a string LOL";
original.e = function() {
  console.log("everything does not work?");
}
original.f = [0, "a", true, false];
console.log(original)
console.log(JSON.stringify(original));
console.log(JSON.stringify(JSON.parse(JSON.stringify(original))));
Chilt answered 3/4, 2021 at 23:41 Comment(6)
You can't keep functions once converted to JSON, as JSON is a string.Heartfelt
@Heartfelt the string is not important, just that the objects don't get cloned, and I showed that what I tried did not work.Chilt
What do you mean the string is not important? It's the reason why using JSON does not work...Heartfelt
What I mean by the string is not important is that I don't have to use JSON strings, If there was another way, I could do it.Chilt
ah I see. Hopefully the given answers will help you thereHeartfelt
Yeah I did, its working well now.Chilt
E
3

It's not possible to stringify functions using JSON.stringify. Only a subset of primitives are valid JSON. For completeness, function source code can be retrieved with toString and rebuilt with the Function constructor, but that's messy and unnecessary.

You can use Object.assign or spread syntax:

var original = {};
original.a = true;
original.b = null;
original.c = 82;
original.d = "a string LOL";
original.e = function() {
  console.log("everything does not work?");
}
original.f = [0, "a", true, false];

var copy = Object.assign({}, original);
var spread = {...original};
copy.f = [42, 45];
spread.f = [1, 2];
copy.e();
console.log(original.f, copy.f, spread.f);

Note that this isn't a deep (recursive) copy, so if you have nested objects, you'll have a shared alias. See What is the most efficient way to deep clone an object in JavaScript? if you want to deep copy.

You also mention you "have one object that does not do anything and is just for cloning". It sounds like you want a class or constructor of some sort. Absent more information, I prefer a function that returns an object and acts as a closure on any hidden properties you might want (you could also use a traditional constructor with this as described here):

const makeFoo = () => ({
  a: true,
  b: null,
  c: 82,
  d: "a string LOL",
  e: function () {
    console.log("everything does not work?");
  },
  f: [0, "a", true, false],
});

const foos = [...Array(3)].map(makeFoo);
foos[0].c = 42;
console.log(foos);

You can parameterize some or all of these attributes with optional default values:

const makeFoo = props => {
  const defaults = {
    a: true,
    b: null,
    c: 82,
    d: "a string LOL",
    e: function () {
      console.log("everything does not work?");
    },
    f: [0, "a", true, false],
  };
  return {...defaults, ...props};
};

const foos = [...Array(3)].map(() => makeFoo({a: false, b: 5}));
foos[0].c = 42;
console.log(foos);

...but I'm speculating a lot on your use case.

Erdman answered 3/4, 2021 at 23:51 Comment(0)
S
1

The best option out there is the cloneDeep method offered by lodash. This will clone all primitives and all nested objects, and ofc you won't loose functions declarations

Scales answered 4/4, 2021 at 0:13 Comment(1)
cloneDeep based on lodash.com/docs/4.17.15#clone, it will return empty object for functionsProcession
R
-2

You can use the same structured clone mechanism that the HTML standard includes for sending data between realms: structuredClone

const clone = structuredClone(original);
Romeoromeon answered 11/5, 2022 at 18:12 Comment(1)
no you cannot b/c OP specifically asked for cloning an object that may have functions as values. structuredClone() will throw an error when it encounters a function.Kitchenette

© 2022 - 2024 — McMap. All rights reserved.