Proposal: Add a deep, recursive merge function

#1

It’s a small function, but I think the popularity of libraries like deepmerge (3.4 million weekly downloads) and Jquery.extends with “deep” option makes me think if this function were built into the browser, it would have a statistically significant impact on how much JavaScript is shipped.

It also solves problems with using Object.assign for DOM elements, where properties like dataset and style are read only.

It allows a pipeline of property setting to take place.

0 Likes

#2

Unfortunately the merge package, just like jQuery, is pretty ancient. :slight_smile: You can do this in the language without using any libraries. Take a look at object spreads.

console.log({...{one: 'hello'}, ...{two: 'world'}})
0 Likes

#3

Thanks @mkay581 for pointing out the sloppiness of my original post. I’ve updated the title and body to express what I mean more clearly. I’m afraid I didn’t look closely enough at the npm library.

JQuery’s extend function has a “deep” option which means that unlike object spreads, it doesn’t overwrite sub properties, but merges them. So for example:

console.log({...{one: {a: 'hello', b: 'goodbye'}}, ...{one: {b: 'world'}}})

evaluates to {one: {b: “world”}}, so the value of ‘a’ was lost. A deep merge would only replace b, leaving a alone.

This article explains what I meant (but was way too sloppy to convey properly).

The article references deepmerge which also has 3.5 million downloads weekly (weird coincidence).

0 Likes

#4

Well, deepmerge is totally different from merge, which you originally had in your post. Deep merges can still be easily done by using the reduce function recursively in combination with object spreads which are all natively available.

Regardless though, the popularity of deep merge is because it use to solve a huge problem back when it first was introduced and engineers have added it to their codebases back then which are included in the download count. So the amount of downloads of a package has doesn’t necessarily really mean that its that popular today or that its even necessary in more modern tech stacks.

I have my biases though because I think that deep merging is a cure for a symptom of a bigger fundamental problem. Implicitly manipulating deeply nested objects should be avoided (if possible) and I don’t think adding a way to do that easily should be added to the core browser api because it would be encouraging bad practice. But that’s just my humble opinion :slight_smile: Regardless though, the deep merge problem is not a hard one to make a function for and probably should be dealt with on a case-by-case basis.

In addition to the edits you made to your original post, you should also remove this sentence

It also solves problems with using Object.assign for DOM elements, where properties like dataset and style are read only.

Because that can also be solved pretty easily natively, unless I’m reading that incorrectly.

0 Likes

#5

This may or may not be helpful to you…

There are really a ton of discussions in TC39 on features already - have you looked through them? You might peruse https://github.com/tc39/proposal-javascript-standard-library/issues?utf8=✓&q=is%3Aissue+is%3Aopen+lodash+standard+library++ for a small view and follow some links to see if there are any that align with something that you’re looking for and would like to +1 or weigh in on, and also to get an idea of the queue of things that are already in process.

0 Likes

#6

Thanks, @mkay581 for your thoughtful response.

Yes, I guess I didn’t have my nomenclature quite right – I never really considered Object.assign and “…” to be doing a merge, due to the aggressive (but faster?) overwriting, but it does appear it is often called “merge”, so I will be sure to use “deep merge” in order to keep that clear in the future.

I see now that my use of the word “solves” also gives the wrong impression, like being able to set styles and datasets can’t be done without difficulty. But what I’m looking for here is nice syntactic sugar to easily set a bunch of properties of a DOM element, passing in one object with everything in one step. If you have an elegant way of doing this, without defining a function, feel free to provide your preferred syntax, and maybe that would render this proposal as not being useful.

I think that the fact that Object.assign doesn’t work (directly? please correct me if I’m wrong) when you try to set properties of an element, including read-only properties style and dataset objects, provides evidence that that deep merge is a fundamental primitive missing from the JavaScript language. Surely setting style and dataset properties, in addition to other properties, is a common problem, which we shouldn’t avoid? Maybe I’m misunderstanding your concerns. So one could write a function that makes exceptions for dataset and style, but what if the DOM elements get another read only property in the future? Wouldn’t the code break?

I agree, as I mentioned before, that deepmerge functions are quite small (I note that npm deepmerge and JQueries ‘extend’ might not yet support symbols, which is a must).

But many other JavaScript functions, including Object.assign are also small and easy to write. They’ve been added to the platform, I think, simply because they are used so often, that it’s one less piece of code every application has to send to the browser.

I agree that the npm download count doesn’t guarantee that it is actually used that much, but I’m not sure how else to tell how often this functionality is used.

I should note (just realized) that lodash also has a deep extend function.

0 Likes

#7

Just seeing your response now, @briankardell. Good, if this is being looked at already, I’m very glad, and this proposal can be ignored (or closed), thanks for the pointer.

0 Likes

#8

I saw a separate proposal to expose an API for the Structured Clone algorithm (i.e. used for postMessage and a few other places). I think that would cover deep cloning objects too.

0 Likes

#11

https://github.com/whatwg/html/issues/793 feels like the closest similar proposal.

0 Likes