7 ms·
Show HN: An isomorphic, configurable JavaScript utility for object deep cloning
- smohare 8y agoMy background is in pure mathematics, where an isomorphism is a structure preserving map between two objects. The description “an isomorphic...JavaScript function” does not make grammatical sense to me, unless the implication is that this function is isomorphic to some standard clone/copy method somehow, or that it is an automorphism on some set of JavaScript objects. Is the word being used in some other sense?
- spion 8y agoYes, in the silly sense that the code can run in both nodejs and a browser. The unfortunate article that coined it: https://blog.nodejitsu.com/scaling-isomorphic-javascript-code/ https://blog.nodejitsu.com/scaling-isomorphic-javascript-cod...
- throwawaymath 8y agoI'm not generally a fan of litigating language choices since, well, all words are made up after all. It's easy to be accused of pedantry if you're going to complain about someone misusing mathematical terminology in an orthogonal context (see what I did there?). It's hard to build a compelling soapbox on, "Well actually, that terminology isn't correct..." That being said, I'm a little baffled after reading that article. I suppose the thinking was that the client and server are isomorphic to each other if they're running the same code. As someone who also has a mathematical background I don't think it's very elegant...but it's obviously caught on and it's creative, so I can dig it.
- jacobolus 8y ago“isomorph” is just Greek for “same form”. I don’t think mathematics should get a monopoly on this one. Though it can probably keep “isomorphism” to itself, since “morphism” is as far as I know a made up math term.
- deleted 8y ago[deleted]
- jfet97 8y agoYes, an isomorphic js program is a program that can run both in browsers and nodejs. I know that is not mathematically correct, but lot of devs use this word and understand its meaning.
- ricardobeat 8y agoThat's a misuse of the term though. Calling these 'universal' javascript would be more correct, and it doesn't even have to be mentioned since it's been standard for a while that any library not dealing with browser APIs can run in node. The term 'isomorphic' refers to the output, as in being able to render the same UI / application on the server and on the client.
- erikpukinskis 8y agoIn JavaScript we've dealt with a lot of APIs that are different on the client and server. If you want to make an HTTP request from Node or the browser it's a totally different API. So in this case isomorphic means the API has the "same shape" on the client and the server, even though the implementation might be different.
- ricardobeat 8y agoI still think it is misused, was also my first time seeing it used this way (I’ve been working with node since the start in 2009).
- erikpukinskis 8y agoYou probably just missed it/ignored it. It’s a very common usage, going back to the era when a Meteor starter. Meteor being noteworthy because everything on their platform is isomorphic. It’d be easy to be active and not come across it though. Most of the JavaScript world maintains a clear client/server separation. In my experience most production apps can’t share code between client and server. It’s either written and packaged for one or the other.
- jph 8y agoGreat tool, thank you for building it and sharing it. I especially like your configurability among what to clone or not, and your good handling of so many edge cases. IMHO the concept of "deep clone" is a design pattern and a potential language improvement idea. An example is "How does this deep clone handle external items, or transient items, or circular items?" Your project shows (correctly IMHO) that there many be many choices, and also reasonable defaults.
- ThePhysicist 8y agoI found that often when you want clean deep cloning of objects (e.g. for state data) and when you’re in control of creating the objects it’s better to build them out of Map and Array instances instead of the builtin object type. We use this extensively for config structures and state data, and it makes cloning or merging objects much easier (as you only need to differentiate between a map, array and everything else). This assumes that you will not clone any of the “object” types in your data structure though, so you might want to store immutable data types on there only (which often is possible and advisable for config and state data though). The downside is that the syntax for creating and working with maps is quite ugly (IMHO), I hope they will improve this in a future version of JS.
- jfet97 8y agohoping that my funtion can help you :)
- yogthos 8y agoMeanwhile, using persistent data structures instead of objects avoids the problem space entirely.
- supermatt 8y agowhat are those data structures you use instead of objects?
- yogthos 8y agoPersistent data structures work the same way version control works on files. When you make a change, you're not copying the entire data structure over. Instead, you track deltas in changes between the original data and new data. From user perspective, you're effectively making a copy each time you make a change, but you're not paying the price of a full copy. Instead, the cost of updates tends to be o( log n) vs o(1), which turns out to be fast enough for vast majority of cases. You can read about this in more detail here: https://en.wikipedia.org/wiki/Persistent_data_structure https://en.wikipedia.org/wiki/Persistent_data_structure JavaScript has a number of libraries that implement these data structures, underscore.js and immutable.js are examples. However, these libraries still require a lot of programmer discipline to use. For example, nothing stops you from putting a mutable object into an immutable data structure. At that point all bets are off. There are also languages that are built around the idea of immutability. For example, I work with ClojureScript, and all data there is immutable by default. Data structure syntax in ClojureScript is actually quite similar to JSON, and it makes it easy to move between the two.
- supermatt 8y agothis article is specifically about deep cloning an object. i’m not quite sure how immutability fits in here and how it overcomes the need to create a clone of an object with no references to the original values. i’m not saying you are wrong about immutability overall, i just don’t understand how you perform this specific operation given your explanation
- 8y ago
- fiallega 8y agoI am sure before you started this project you looked at other existing libraries. How is this solution compared with the lodash _.cloneDeep https://lodash.com/docs/4.17.11#cloneDeep https://lodash.com/docs/4.17.11#cloneDeep. Thanks
- jfet97 8y agoNo I've built it on my own. I only know that popular libraries as lodash don't call constructors, so I think there is no way to mantain a proper [[Prototype]] nor the constructor props. IDK how other libraries do to handle circ references nor if them allow to copy non-enums props and getters&setters.
- porphyrogene 8y agoYou don’t need to use the constructor syntax to have an object inherit prototypes from another.
- erikpukinskis 8y agoHow do you do it without a constructor? Iterate over the properties on the prototype?
- porphyrogene 8y agoThe global Object’s assign method is the “old” way to inherit prototypes. ES6 syntax did not add new language features; they were there all along.
- fiallega 8y agoThanks a lot for all clarifications.
- porphyrogene 8y agoNo problem. A good exercise I used to do was writing inheritence patterns first with pre-ES6 syntax, then constructors, then classes. They are, of course, interchangeable but it’s not wise to rehearse an anti-pattern. EDIT: I said assign method earlier, I meant create. The assign method is the pre-ES6 way of creating object instances. Object.create() is used to inherit prototypes. That’s such a common mix-up that I’m embarrassed I didn’t catch it.
- gitgud 8y agoThis doesn't seem to copy methods on an object. Why is this better than using JSON.stringify(OBJ) and JSON.parse(OBJ) to deep clone?
- jfet97 8y agoLot of stuff, as you can see in the docs. JSON.parse/stringify does not call the constructors for example