在 TypeScript 中克隆物件
Shuvayan Ghosh Dastidar
2023年1月30日
-
TypeScript 中的
克隆
機制 -
在 TypeScript 中使用
Spread
運算子克隆物件 -
在 TypeScript 中使用
Object.assign()
方法克隆物件 -
TypeScript 中
巢狀
物件的深度複製 - TypeScript 中類的深拷貝
在實現某些服務時,克隆物件是一件很常見的事情。克隆
是指建立現有物件的副本,包括其欄位。
可能會使用物件克隆的一些用例是在函式中返回物件的副本。
在更改某些屬性後更改其某些屬性或在 React 的情況下使用 setState
。本文演示了 TypeScript 中不同型別的克隆機制以及如何實現它們。
TypeScript 中的克隆
機制
大致有兩種克隆機制——淺拷貝
和深拷貝
。顧名思義,淺拷貝複製物件內的屬性和引用巢狀屬性。
同時,在深拷貝的情況下,它的所有屬性都被複制,複製或克隆物件的任何變化都不會影響原始物件。下面的程式碼段將討論淺拷貝和深拷貝是如何工作的。
let a : number = 5;
let b = a;
b = 6;
//does not hold reference to previous original variable and thus is deep copied
console.log(b);
console.log(a);
type Person = {
name : string;
age : number;
}
var person : Person = {
name : 'Geralt',
age : 95
}
// shallow copy
var personCopy : Person = person;
personCopy.age = 90;
console.log(personCopy.age)
console.log(person.age)
輸出:
6
5
90
90
因此,隱式只為物件分配淺表副本,因為複製物件中的任何更改都會影響從中複製它的原始物件。
在 TypeScript 中使用 Spread
運算子克隆物件
spread
運算子是 JavaScript ES6 版本中可用功能的新增功能,可以有效地複製物件。考慮前面程式碼段中的示例。
type Person = {
name : string;
age : number;
}
var person : Person = {
name : 'Geralt',
age : 95
}
var personCopy : Person = { ...person};
personCopy.age = 90;
console.log(personCopy.age)
console.log(person.age)
輸出:
90
95
因此,spread
運算子可以製作物件的深層副本。但是,在巢狀
物件的情況下它會失敗。
在 TypeScript 中使用 Object.assign()
方法克隆物件
Object.assign()
的工作方式與擴充套件運算子的情況類似,可用於克隆簡單物件,但在巢狀物件的情況下會失敗。
var personCopy : Person = Object.assign({}, person);
TypeScript 中巢狀
物件的深度複製
必須遞迴複製每個元素以複製巢狀
物件。對於陣列,擴充套件運算子適用於原始資料型別。
但是,必須為物件陣列單獨複製每個元素。我們可以設計一個函式來實現這一點;
function deepCopy<T>(instance : T) : T {
if ( instance == null){
return instance;
}
// handle Dates
if (instance instanceof Date) {
return new Date(instance.getTime()) as any;
}
// handle Array types
if (instance instanceof Array){
var cloneArr = [] as any[];
(instance as any[]).forEach((value) => {cloneArr.push(value)});
// for nested objects
return cloneArr.map((value: any) => deepCopy<any>(value)) as any;
}
// handle objects
if (instance instanceof Object) {
var copyInstance = { ...(instance as { [key: string]: any }
) } as { [key: string]: any };
for (var attr in instance) {
if ( (instance as Object).hasOwnProperty(attr))
copyInstance[attr] = deepCopy<any>(instance[attr]);
}
return copyInstance as T;
}
// handling primitive data types
return instance;
}
type info = {
gender : 'male' | 'female';
}
type Person = {
name : string;
age : number;
info : info;
}
var person : Person = {
name : 'Geralt',
age : 95,
info : {
gender : "male"
}
}
var personCopy : Person = deepCopy<Person>(person);
console.log(personCopy);
personCopy.info.gender = "female";
console.log(person.info.gender);
console.log(personCopy,info.gender);
輸出:
male
female
因此,成功的深層複製是為巢狀
物件完成的。
TypeScript 中類的深拷貝
可以使用自定義函式複製類,並在該函式中建立一個新例項。這使作者可以完全控制複製功能。
class Witcher{
name : string;
age : number;
constructor() {
this.name = "Geralt"
this.age = 43;
}
greet(){
return "Hi I am witcher known as " + this.name
}
copy(){
var witcherIns = new Witcher();
witcherIns.name = this.name;
witcherIns.age = this.age;
return witcherIns;
}
}
var witcherObj = new Witcher();
var witcherObjCopy = witcherObj.copy();
console.log(witcherObjCopy);
console.log(witcherObjCopy.greet());
輸出:
Witcher: {
"name": "Geralt",
"age": 43
}
"Hi I am witcher known as Geralt"