3
\$\begingroup\$

My goal was to create a single-line function that produces a deep copy of a javascript object.

Requirements:

  • Executable on a single line without the use of semicolons (exception: last character of the line)
  • Nested objects should not be references to the originals

Function:

let copiedObjct = (copy = (obj) => (Object.keys(obj).reduce((v, d) => Object.assign(v, {[d]: (obj[d].constructor === Object) ? copy(obj[d]) : obj[d]}), {})))(obj);

Usage (expanded):

let obj = { /*...*/ }
let copiedObjct = (copy = (obj) => (
  Object.keys(obj).reduce((v, d) => Object.assign(v, {
    [d]: (obj[d].constructor === Object) ? copy(obj[d]) : obj[d]
  }), {})
))(obj);

My questions are:

  1. Is this code efficient?
  2. Are there any reasons this shouldn't be used in the wild?
  3. Is there a way I can make it shorter?
\$\endgroup\$
3
  • 1
    \$\begingroup\$ JSON.parse(JSON.stringify(obj)) with some caveats may work for you. \$\endgroup\$
    – sineemore
    Jun 20, 2018 at 8:56
  • \$\begingroup\$ Is there a way I can make it shorter?: 163b -> 144b: let copiedObjct=(copy=(obj)=>(Object.keys(obj).reduce((v,d)=>Object.assign(v,{[d]:(obj[d].constructor===Object)?copy(obj[d]):obj[d]}),{})))(obj) \$\endgroup\$
    – Ivan
    Jun 20, 2018 at 9:45
  • 1
    \$\begingroup\$ const copy = obj => typeof obj == 'object' ? Object.entries(obj).reduce((r, [k, v]) => (r[k] = copy(v), r), {}) : obj, still somewhat readable... though Joseph really has the right answer here. \$\endgroup\$
    – Gerrit0
    Jun 21, 2018 at 2:43

1 Answer 1

3
\$\begingroup\$

Is this code efficient?

Probably... not.

Efficiency can mean different things. Efficiency could mean "fast running code" or "use the least amount of memory" - this can only be determined by running the code through a profiler. Efficiency could also mean "I can use it easily" or "works reliably" or "handles edge cases well" - this can only be determined by having other people use it.

Are there any reasons this shouldn't be used in the wild?

Yes.

Does the code really run on a variety of objects? What if I put things like Arrays, Dates, RegExps, Maps, Sets, etc. in my object? Does it handle circular references? This is a naive implementation of deep-copy which is fine in small apps and prototypes where you know what the data looks like. But in more general cases, this will probably not hold.

If you'd like to see how a general-purpose deep-copy function looks like, see how jQuery.extend or lodash.assign is implemented.

Is there a way I can make it shorter?

Wrong question. Code size is irrelevant in JS, you have minifiers for that.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.