[英]Deep clone in TypeScript (preserving types)
我需要在TypeScript中深度克隆一个对象。 这应该不是问题,因为像Lodash这样的库提供了适当的功能。 但是,这些似乎丢弃了类型信息。
> var a = new SomeClass();
> a instanceof SomeClass;
< true
> var b = _.cloneDeep(a);
> b instanceof SomeClass;
< false
有没有办法在保留此类型信息的同时克隆TypeScript中的对象?
打字稿不会丢弃类型信息。 在DefinitelyTyped lodash.d.ts文件中,您可以看到cloneDeep
被定义为
cloneDeep<T>(
val: T,
customizer?: (value: any) => any,
thisArg?: any
) : T
忽略我们不关心的参数,它需要一个T
作为输入,并吐出一个T
作为输出。 因此,Typescript不会丢失任何类型的信息; 它认为cloneDeep
的输出与输入的类型相同。
您应该能够通过编辑器验证这一点:假设您有一些编辑器可以让您检查变量的类型或自动填充方法(如果您不这样做,我强烈建议您这样做)。
为什么typeof
不能像你期望的那样工作? 这是因为Typescript类型信息不会延续到运行时。 instanceof
是一个本机JS运算符,其中的Typescript不会改变其行为,您可以通过运行此代码段来查看:
"use strict"; class A {} let a = new A(); let b = _.cloneDeep(a); if (b instanceof A) { alert("b is an instance of A"); } else { alert("b is not an instance of A"); }
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.js"></script>
b instanceof A
为false的原因是instanceof
正在检查构造函数:如果函数A
是x的原型链中的某个构造函数A
则x instanceof A
返回true(请参阅instanceof上的MDN文档)。 但是,Lodash在克隆对象时不使用构造函数。 它不能。 (它如何知道要传递的参数?)它创建了一个普通的JS对象,它具有克隆对象的所有方法,但不会重现它的原型链。
在处理原始JS对象时,最好使用Lodash的clone
(以及大多数lodash的方法)。 如果你将它与构造函数和instanceof
一起使用,那么事情会变得有些模糊。
这里的一个解决方案是避免检查instanceof
,并做类似鸭子打字的事情; 不要检查对象的构造函数是否是特定函数,但检查该对象是否具有您期望的属性。
另一种解决方案是,如评论中所建议的,在您的类本身上实现克隆方法,该方法不会使用lodash。
class A() {
clone() {
var cloned = new A(); //pass appropriate constructor args
//make other necessary changes to make the state match
return cloned;
}
}
有一篇关于深度克隆的有趣博客文章http://blog.soulserv.net/understanding-object-cloning-in-javascript-part-ii/ 。 您可以使用作者的深度克隆clone()
函数的实现:
class SomeClass {
constructor(public test) {
}
}
let c = new SomeClass("Hey!");
c.test = "Hey!";
console.log(c instanceof SomeClass); // returns true
let cloneC = clone(c, /* resolve circular references */ true);
console.log(cloneC instanceof SomeClass); // returns true
[ clone()源代码 ] [ 完整源代码 ]
您可以使用Lodash#cloneDeep实用程序。 使用示例:
import * as _ from "lodash";
...
{
this.cloned = _.cloneDeep(data);
}
您可以使用JSON stringify和parse方法创建自己的深度克隆:
export function deepClone<T>(obj: T): T {
return JSON.parse(JSON.stringify(obj)) as T;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.