我有一个类的实例,比如说
class MyObject{
id: number = 0;
data: string = "";
constructor(){
}
toString(){
return `${this.id}: ${this.data}`;
}
}
const myObj = new MyObject()
myObj.data = "hello"
如何将其转换为普通的 JS 对象:
const output = {id: 10, data: "hello"}
我知道这行得通,但必须有一种方法可以不序列化整个对象:
const output = JSON.parse(JSON.stringify(myObj))
最好的方法是什么?
请注意,我正在寻找一个通用的解决方案,而不是像这样:
toObject() {
return {
id: this.id,
data: this.data,
};
}
Object.assign()
将对象的所有可枚举 own 属性复制到另一个对象,该对象可以指定为新的普通对象。
class MyObject{
id = 0;
data = "";
constructor(){
}
toString(){
return `${this.id}: ${this.data}`;
}
}
const instance = new MyObject();
const properties = Object.assign({}, instance);
console.log(properties);
对于简单的情况,您可以使用object literal spread syntax:
class MyObject{
constructor(){
this.id = 0;
this.data = "";
}
toString(){
return `${this.id}: ${this.data}`;
}
}
const myObj = new MyObject();
console.log(myObj.constructor.name); // MyObject
myObj.data = "hello";
const result = {...myObj};
console.log(result.constructor.name); // Object
如果您的原始对象具有嵌套的自定义对象——也需要转换为普通对象或数组——那么要么创建一个递归函数,要么使用
structuredClone
函数(添加于 ECMAScript 2023,Node 17) .这是一个更真实的链表实现示例:
class Node {
constructor(value, next) {
this.value = value;
this.next = next;
}
*[Symbol.iterator]() {
yield this.value;
if (this.next) yield* this.next;
}
}
class LinkedList {
constructor(...values) {
this.head = null;
for (const value of values.toReversed()) {
this.head = new Node(value, this.head);
}
}
*[Symbol.iterator]() {
if (this.head) yield* this.head
}
toString() {
return [...this].join("→");
}
}
const myObj = new LinkedList(1, 2, 3);
console.log("list: ", myObj.constructor.name, myObj.toString());
const result = structuredClone(myObj);
console.log("list2: ", result.constructor.name, myObj);
但是请注意,这确实在幕后对整个对象进行序列化/反序列化,并且在涉及本地类的地方,它们也在目标对象中维护(如
Set
,Map
,Date
,RegExp
,Number
,...)。这可能是也可能不是你想要的,但要意识到 JSON.stringify
在这种情况下也有 particular 结果:对于 Set
、Map
或 RegExp
你得到一个空对象,对于 Date
你得到一个字符串,...等,所以这可能需要特别注意——取决于期望。