TypeScript
TypeScript是一种由微软开发的自由和开源的编程语言。它是JavaScript的一个超集,而且本质上向这个语言添加了可选的静态类型和基于类的面向对象编程。
TypeScript扩展了JavaScript的语法,所以任何现有的JavaScript程序可以不加改变的在TypeScript下工作。TypeScript是为大型应用之开发而设计,而编译时它产生 JavaScript 以确保兼容性。
TypeScript 支持为已存在的 JavaScript 库添加类型信息的头文件,扩展了它对于流行的库如jQuery,MongoDB,Node.js和 D3.js 的好处。
TS中的浅拷贝与深拷贝
所谓深拷贝与浅拷贝,是围绕引用类型变量的拷贝进行的讨论
在TypeScript中,变量分为基本类型和引用类型两种。其本质区别是不可变性,基本类型是不可变的,而引用类型是可变的。
所谓基本类型的不可变性,我们可以举个例子
let a = 1;
let b = 1;
a++;
console.log("a的值是:"+a,"b的值是:"+b);
//打印结果如下:
/*
a的值是2,b的值是1
*/
声明一个变量a,并为其赋值1,这时内存中开辟出一片区域用来储存1。此时声明了一个变量b,也为b赋值1。当执行a++时,基本类型的不可变性就体现出来,a++的值应该为2,但是这个值并不会将原来储存1的那片内存覆盖掉,而是再开辟一片内存来存储2。所以对于这个1来讲,他是永远不可变的。
而对于引用变量则不同,因为其存储的是只想某个内存区域的地址,所以其修改时直接操作在内存上的,这就导致了深拷贝和浅拷贝问题的出现。
- 浅拷贝
let shallowA = {
x: 1,
y: -1
}
let shallowB = shallowA;
shallowA.x++;
console.log("shallowA.x==="+shallowA.x,"shallowB.x==="+shallowB.x,)
//打印结果如下:
shallowA.x === 2
shallowB.x === 2
这就是最简单的浅拷贝,其效果十分明显,对拷贝源的操作,会直接体现在拷贝目标上,因为这个赋值行为的本质是内存地址的赋值,所以他们指向了同一片内存区域。
浅拷贝十分容易,也十分常见,但却无法满足需求,假如我们需要获得与拷贝源完全相同,却又不会互相影响的对象,应该怎么办呢。
- Object.assign()
TypeScript为我们提供了一种十分好用的方法,Object.assign(target, ...source)方法assign方法接受多个参数,第一个参数target为拷贝目标,剩余参数...source是拷贝源。此方法可以将...source中的属性复制到target中,同名属性会进行覆盖,并且在复制过程中实现了'伪'深拷贝
let shallowA = {
a: 1,
b: 2,
c: {
d: 1,
}
}
let shallowB = {};
Object.assign(shallowB, shallowA);
shallowA.a++;
console.log("shallowA.a==="+shallowA.a,"shallowB.a==="+shallowB.a,);
//打印结果如下:
shallowA.a === 2
shallowB.a === 1
表面上看,好像已经实现了深拷贝的效果,对shallowA.a进行的操作并没有体现在shallowA.a中,但是呢,关键的时候来了,这也是我今天为什么要写这个博客的主要问题所在。
shallowA.c.d++;
console.log("shallowA.c.d==="+shallowA.c.d,"shallowB.c.d==="+shallowB.c.d);
//打印结果如下:
shallowA.c.d === 2
shallowB.c.d === 2
从上面的打印结果看出,Object.assign()的拷贝类型十分明显了,这是一种可以对非嵌套对象进行深拷贝的方法,如果对象中出现嵌套情况,那么其对被嵌套对象的行为就成了普通的浅拷贝.
在今天的开发中我也遇到了此问题。从后台返回的数据是一个数组A,数组A里面又包含了B对象,B对象中又包含数组C,数组C里面又含有对象D。
而我又将数组A拷贝三份。放进一个大数组,形如【A1,A2,A3】;其中A1,A2,A3,都是A数组拷贝过来。当我操作A1数组里面的A.B.C.D的时候,发现,A2,与A3的D对象也跟着改变。
那么,应该如何拷贝才能达到操作A1中的D对象,而A2与A3的D对象不变呢,也就是如何实现完完全全的深拷贝呢?
stringify()和parse()
JSON对象中包含两个方法, stringify()和parse(),前者可以将对象JSON化,而后者可以将JSON格式转换为对象.这是一种可以实现深拷贝的方法.但这种方法的缺陷是会破坏原型链,并且无法拷贝属性值为function的属性所以如果只是想单纯复制一个嵌套对象,可以使用此方法。
let shallowA = {
a: 1,
b: {
c: 1
}
}
let shallowB = JSON.parse(JSON.stringify(shallowA));
shallowA.b.c++;
console.log("shallowA.b.c==="+shallowA.b.c"shallowB.b.c==="+shallowB.b.c);
//打印结果如下:
shallowA.b.c===2;
shallowB.b.c===1;
由此可见,我们已经实现了对象的完全深拷贝。
我的问题也就迎刃而解;接下来,就可以开心的开发接下来的功能了。。。。不解决此问题真的木办法往下继续了。