Immutable.fromJS() 不深
Immutable.fromJS() is not deep
Immutable.fromJS
的描述是:
Deeply converts plain JS objects and arrays to Immutable Maps and Lists.
但这是错误的。我有一个具有以下结构的对象。大写的项目是 ES6 类.
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
Immutable.fromJS(foo)
的结果是一个地图。数组 bars
和 bazes
是 List
。但是,这些列表中的每个元素仍然是普通 (ES6) 对象。每个Baz的bars
属性是数组,不是列表
是我做错了什么,还是文档不正确?
也许 ES6 对象不支持深度特征?如果是这样,我怎样才能使我的对象深度不可变?
更新:
这有效但感觉有点恶心:Immutable.fromJS(JSON.parse(JSON.stringify(foo)))
docs for fromJS
中的第一句话是:
Deeply converts plain JS objects and arrays to Immutable Maps and Lists.
如果 Foo、Bar 和 Baz 是 ES6 classes 那么它们既不是普通的 JS 对象也不是数组——它们是 class 的实例。所以,不,文档没有错。
顺便说一句,如果 Immutable.fromJS
自动将它遇到的任何对象转换为普通 JS 对象,正如您似乎所期望的那样,这对大多数用户来说将是非常令人惊讶的行为,而且根本不会可取。
但由于这是您想要的行为,您会很高兴知道 Immutable wiki 有 a section on this exact topic,我将在此处复制以供后代使用:
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();
}
这很简单。而且,事实上,它完全按照承诺工作,正如您在 运行 下面的代码片段中看到的那样。
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>
此外,我必须检查 Date
类型,因为此函数将我的日期转换为非日期对象。这个函数使用了 typescript 和 lodash,但我相信你可以相应地改变它
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();
}
Immutable.fromJS
的描述是:
Deeply converts plain JS objects and arrays to Immutable Maps and Lists.
但这是错误的。我有一个具有以下结构的对象。大写的项目是 ES6 类.
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
Immutable.fromJS(foo)
的结果是一个地图。数组 bars
和 bazes
是 List
。但是,这些列表中的每个元素仍然是普通 (ES6) 对象。每个Baz的bars
属性是数组,不是列表
是我做错了什么,还是文档不正确?
也许 ES6 对象不支持深度特征?如果是这样,我怎样才能使我的对象深度不可变?
更新:
这有效但感觉有点恶心:Immutable.fromJS(JSON.parse(JSON.stringify(foo)))
docs for fromJS
中的第一句话是:
Deeply converts plain JS objects and arrays to Immutable Maps and Lists.
如果 Foo、Bar 和 Baz 是 ES6 classes 那么它们既不是普通的 JS 对象也不是数组——它们是 class 的实例。所以,不,文档没有错。
顺便说一句,如果 Immutable.fromJS
自动将它遇到的任何对象转换为普通 JS 对象,正如您似乎所期望的那样,这对大多数用户来说将是非常令人惊讶的行为,而且根本不会可取。
但由于这是您想要的行为,您会很高兴知道 Immutable wiki 有 a section on this exact topic,我将在此处复制以供后代使用:
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(); }
这很简单。而且,事实上,它完全按照承诺工作,正如您在 运行 下面的代码片段中看到的那样。
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>
此外,我必须检查 Date
类型,因为此函数将我的日期转换为非日期对象。这个函数使用了 typescript 和 lodash,但我相信你可以相应地改变它
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();
}