问题
The description of Immutable.fromJS
is:
Deeply converts plain JS objects and arrays to Immutable Maps and Lists.
But that's wrong. I have an object with the following structure. The capitalized items are ES6 classes.
Foo
prop1
prop2
bars
Bar
prop1
prop2
Bar
prop1
prop2
bazes
Baz
prop1
prop2
bars
Bar
prop1
prop2
Bar
prop1
prop2
Baz
prop1
prop2
bars
Bar
prop1
prop2
Bar
prop1
prop2
The result of Immutable.fromJS(foo)
is a Map. The arrays bars
and bazes
are List
s. However, each element of these lists is still a plain (ES6) object. The bars
property of each Baz is an array, not a list.
Am I doing something wrong, or is the documentation incorrect?
Maybe the deep feature is not supported for ES6 objects? If that's the case, how can I make my object deeply immutable?
UPDATE:
This works but feels kinda gross: Immutable.fromJS(JSON.parse(JSON.stringify(foo)))
回答1:
The very first sentence in the docs for fromJS is:
Deeply converts plain JS objects and arrays to Immutable Maps and Lists.
If Foo, Bar, and Baz are ES6 classes then they are neither plain JS objects nor arrays—they're instances of a class. So, no, the docs are not incorrect.
As an aside, if Immutable.fromJS
automatically converted any object it encountered into a plain JS object, as you seem to have expected it to, that would be very surprising behavior to most users, and not at all desirable.
But since that's the behavior you want, you'll be happy to know that the Immutable wiki has a section on this exact topic, which I'll duplicate here for posterity:
Here is an example which will convert any Object, including exotic Objects, to
Immutable.Map
:function fromJSGreedy(js) { return typeof js !== 'object' || js === null ? js : Array.isArray(js) ? Immutable.Seq(js).map(fromJSGreedy).toList() : Immutable.Seq(js).map(fromJSGreedy).toMap(); }
That's pretty simple. And, indeed, it works exactly as promised, as you can see by running the below snippet.
class Foo {
constructor(name, ...children) {
this.name = name;
this.children = children;
}
}
class Bar extends Foo {}
class Baz extends Foo {}
const myBar = new Bar("myBar", new Baz("myBaz1"), new Baz("myBaz2"));
const myFoo = new Foo("myFoo", myBar);
function fromJSGreedy(js) {
return typeof js !== 'object' || js === null ? js :
Array.isArray(js) ?
Immutable.Seq(js).map(fromJSGreedy).toList() :
Immutable.Seq(js).map(fromJSGreedy).toMap();
}
console.log(fromJSGreedy(myFoo).toString());
<script src="https://cdnjs.cloudflare.com/ajax/libs/immutable/3.8.1/immutable.js"></script>
回答2:
Additionally, I had to check for Date
types because this function was converting my dates into non-date objects. This function uses typescript and lodash, but I'm sure you can alter it accordingly
export function myFromJS(js: any): any {
return typeof js !== 'object' || js === null || (_.isDate(js)) ? js :
Array.isArray(js) ?
Immutable.Seq(js).map(myFromJS).toList() :
Immutable.Seq(js).map(myFromJS).toMap();
}
来源:https://stackoverflow.com/questions/40661729/immutable-fromjs-is-not-deep