Deep spread operator (Bilal Abdullah)

# Ahad Cove (6 years ago)

Hello Scripters,

I really appreciate everything you all have done for the language and have no complaints over here. I do have a suggestion though :)

At work we’ve almost got rid of lodash, except we still need it for DeepCopy vs rolling our own. It’s the same with my side projects. I don’t use lodash because the main times that I need deep copy is when I’m either digging into the Redux store using React, or copying an observable in the Angular world.

I believe ES Script users would appreciate having a deep copy spread operator tremendously.

My proposal is to go off of the current spread operator we currently have in ES and make it 4 dots for a deep spread. This can be used on Objects or Arrays.

‘’’js const oldDeepObj = { InnerObj: { func: () => return ‘wow’ } }

const obj = {....oldDeepObj} obj.innerObj.func = () => return ‘nice’

oldDeepObj.innerObj.func()

wow ‘’’

Thank you! Looking forward to hearing back from you all. If there’s any other questions let me know

  • Bilal Abdullah
# Henrique Barcelos (6 years ago)

IMO, this would be very problematic.

  1. 4 dots are visually almost identical to 3 dots. This could introduce severe bugs because of a simple hard to spot typo.

  2. Deep traversing will always have performance problems in some cases. Dealing with circular references can take this issue even further.

I believe such functionality should be used in very specific situations, where object shape is well-known, not very deep and definitely not circular. So, supporting this at the core of the language will probably be frowned upon by the community.

Em ter, 23 de out de 2018 08:57, Ahad Cove <ahadcove at gmail.com> escreveu:

# Naveen Chawla (6 years ago)

Is there any real problem with circular reference cloning? I don't see any, Please let me know in the simplest case e.g. { a: a } (obviously contrived syntax here)

Otherwise, I agree completely about the 4 dots being the wrong syntax for this, precisely for the reason you gave

# Naveen Chawla (6 years ago)

Correction, suppose const b = { a : b } . Circular references can be cloned trivially, as far as I can tell

# kai zhu (6 years ago)

there’s no reliable way to deep-copy arbitrary js-objects. the most practical “general” solution is two-step:

  1. deep-copy JSON-data first, e.g. var bb = JSON.parse(JSON.stringify(aa))
  2. custom-copy non-JSON-data in a second-pass, e.g. bb.innerObj.func = aa.innerObj.func

like this real-world example [1]:

local.jsonCopy = function (obj) {
/*
 * this function will [JSON] deep-copy obj
 */
    return obj === undefined
    ? undefined
    : JSON.parse(JSON.stringify(obj));
};
...
// update apiDict
self = local.apiDict[key.join('.')] = local.apiDict[self._methodPath] =
    local.jsonCopy(self); // step 1 - deep-copy JSON-data first
// init ajax
self.ajax = function (swaggerJson, onError) { // step 2 - custom-copy/add non-JSON-data in second-pass
    return local.apiAjax(self, swaggerJson, onError);
};

[1] deep-copy swagger client-object with functions kaizhu256/node-swgg/blob/2018.9.8/lib.swgg.js#L2181

kai zhu kaizhu256 at gmail.com

# Jamie (6 years ago)

4 dots is already valid syntax when it has a number after it

let o = { ....4 }

# kai zhu (6 years ago)

digressing a bit, but once you get used to the idea of deep-copying objects using JSON.parse(JSON.stringify(x)), you also realize web-projects are alot simpler if you keep many non-JSON-datatypes in string-form by default (BigInt, Date, CivilXxx, etc.), since the use-case to copy/serialize data between web-components is far more common than the need to actually revive data for use in low-level business-logic.

kai zhu kaizhu256 at gmail.com

# Andrea Giammarchi (6 years ago)

both CircularJSON (deprecated) and flatted (the successor) easily deal with circular references while serializing / unserializing objects, yet you need to keep stored data simple.

This is usually a common case for postMessage / workers though, so it shouldn't be a big deal.

stringifiers and revivers can give you extra power to serialize / unserialize RegExps, Date, as well as BigInt too, storing values via {new:'RegExp',args:['value', 'gi']} simplifying the case for {new:'Array', args:[...the-actual-array]} and {new: 'Object', args: [..the-actual-object...]}

Well, I'm sure you got there are many ways to deep copy and also with circular references.

# Cyril Auburtin (6 years ago)

I think a combination of Object.entries, .flatMap and Object.fromEntries could do the job