Comments (7)
There's currently logic to do this in some situations: merge
determines whether changes were made and then returns the unmodified original object if not.
The question here is how far it ought to go in deciding whether any changes were made. It currently considers the example you gave a change because it does referential equality checking to determine that. If instead it did deep (value-based) equality checking, it would realize that this was not actually a change and you'd get the result you were hoping for. 😃
This isn't yet possible because the deepEquals branch hasn't landed, but assuming it had, there's still a tradeoff to consider. Doing this check on every merge can get expensive, especially when merging large data structures. It would probably still unlock a considerable performance boost in the case of shouldComponentUpdate
, but could be a substantial performance hit in other use cases.
My general feeling is that once deepEquals
is in (which has been on the backburner for me, but which mainly just needs tests at this point), merge
should use it by default for this purpose, but should accept an optional alternative "change-detector" function so you can save yourself from a huge performance hit on large data structures.
from seamless-immutable.
@rtfeldman cases like this could be handled by a custom merger if we add the following to addToResult
in the merge
function:
Right now it looks like:
var mergerResult = merger && merger(currentObj[key], immutableValue, config);
If we extend that to:
var mergerResult = merger && merger(currentObj[key], immutableValue, config);
if (mergerResult && mergerResult === currentObj[key]) return;
Then if a merger returns something and it is the same thing as the property in the currentObj
we could abort addToResult
.
Combining that with a custom merger that returns the array from the currentObj
if they contain the same items:
function equalityArrayMerger(current, other) {
if (!(current instanceof Array) || !(other instanceof Array)) return;
if (current.length !== other.length) return;
for (var i = 0; i < current.length; i++) {
if (current[i] !== other[i]) return;
}
return current;
}
would give the desired results.
But not sure if it is worth adding if there is another long term goal with deepEquals
? It's a minor change but it will add another check in the addToResult
function. And this was only a quick test, I haven't checked how/if it affects other things.
from seamless-immutable.
Yeah, that seems like a good implementation. I'd change the second line to this, though:
if (merger && mergerResult === currentObj[key]) return;
That way the conditional can still pass if the value happens to be falsy in both places.
As far as merge
goals, the goals with deepEquals
would be (1) to change the default implementation to use deepEquals
for change detection over ===
, and (2) to allow users to specify a custom function to do this if necessary.
from seamless-immutable.
@cr0cK: now that PR #41 has been merged you should be able, after the next release, to pass in the following or similar to the merge to get your example to work:
function equalityArrayMerger(current, other) {
if (!(current instanceof Array) || !(other instanceof Array)) return;
if (current.length !== other.length) return;
for (var i = 0; i < current.length; i++) {
if (current[i] !== other[i]) return;
}
return current;
}
...
> i2 = i.merge(o2, {merger: equalityArrayMerger})
{ a: [ 1, 2 ] }
> i === i2
true
It will override the merge for array properties and return the same reference if they contain the same list of values in both objects.
Note that it will not work with current master until a grunt build
has been run.
from seamless-immutable.
Thank you @crudh, It looks nice :)
What do you think about to make this behavior as the default one?
from seamless-immutable.
@cr0cK: it's released now. And if you use Node/Browserify I have added the equalityArrayMerger
in this project if you prefer that instead of copying the function above.
As for the default behaviour I agree with what @rtfeldman said above, as long as it is easy to get back to the current behaviour when a deep check isn't needed or is too expensive.
from seamless-immutable.
Why do some kind of deepEquals
test when you could just use recursive merging to determine if anything has changed? Here's a rough 17-line deep merge implementation (not thoroughly tested, and one would want to make it customizable):
function mergeDeep(a, b) {
if (a instanceof Object || a instanceof Array) {
if (!b) return a;
var remade;
for (var key in b) {
if (b.hasOwnProperty(key)) {
var merged = mergeDeep(a[key], b[key]);
if (merged !== a[key]) {
if (!remade) remade = a.asMutable();
remade[key] = merged;
}
}
}
return remade ? Immutable(remade) : a;
}
return b;
}
Here was my testcase that works with this mergeDeep
but not merge(..., {deep: true})
:
var a = Immutable({
plots: [
{
traces: [
{channel: 'a'},
{channel: 'b'}
]
}
]
});
var b = mergeDeep(a, {
plots: [
{
traces: [
{channel: 'a'},
{channel: 'b', min: 0, max: 100}
]
}
]
});
console.log(a.plots[0].traces[0] === b.plots[0].traces[0]); // should be true
console.log(a.plots[0].traces[1] === b.plots[0].traces[1]); // should be false
Note that since this function treats arrays like number-keyed maps, mergeDeep(Immutable([1,2,,,5]), [,3,4])
would produce [1,3,4,,5]
with this implementation, which is exactly analogous to map merging (and I believe the way Immutable.js mergeDeep works). Another common merge type would be for the output to be deep equal to b, but with all original values from a that were equal:
function updateDeep(a, b) {
if (a instanceof Object || a instanceof Array) {
if (!b) return a;
var remade;
for (var key in b) {
if (b.hasOwnProperty(key)) {
var updated = updateDeep(a[key], b[key]);
if (updated !== a[key]) {
if (!remade) remade = a.asMutable();
remade[key] = updated;
}
}
}
for (var key in a) {
if (!b.hasOwnProperty(key)) {
if (!remade) remade = a.asMutable();
delete remade[key];
}
}
return remade ? Immutable(remade) : a;
}
return b;
}
from seamless-immutable.
Related Issues (20)
- Make `without` support removing item from an array HOT 4
- how to use splice like array HOT 1
- Internet Explorer tests are failing HOT 4
- Issue regarding null values HOT 5
- Why are IE tests failing? HOT 3
- How to apply splice with seamless-immutable? HOT 1
- Merge does not work with class instances
- __immutable_invariants_hold is enumerable on Edge HOT 1
- Garbage collector features? HOT 1
- Performance characteristics
- Any difference with deepCopy? HOT 1
- [types] Mixin not applied to nested objects HOT 1
- flatMap not working HOT 2
- Add documentation for merge mode
- Files not being replaced on a deep merge
- Fails on IE 11 HOT 1
- TypeError: Object(...) is not a function HOT 1
- Lodash Vulnerability Problem
- Is the project still maintained? HOT 2
- immutable object causes rapid memory growth HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from seamless-immutable.