我爱编程RNAngular2+ 学习

【ionic开发】TypeScript的深拷贝与浅拷贝

2017-11-15  本文已影响5237人  全栈攻城狮DWQ
duwenquan-方形LOGO.png

引述

    首先,对自己的读者说声抱歉。由于自己换了公司,公司研发总监在技术选型方面采用ionic开发。ionic是一个用来开发混合手机应用的,开源的,免费的代码库。可以优化html、css和js的性能,构建高效的应用程序,而且还可以用于构建Sass和AngularJS的优化。我要从一个iOS开发者转为ionic开发,还是在项目周期特别紧张的情况,导致我最近三个月一直是在边学习边做项目的状态中,也没时间写博客和回答各位读者的问题。三个月过去了,如今也转正了,也可以熟练的使用ionic开发项目了,现在也终于有点时间可以和各位读者交流了,不过有点蛋疼的是我用ionic开发的是PC端的项目。😭😭😭😭😭😭。下面,晒一下我的转正OA【这三个月太难了,从0到到现在真的是压力太大了】。


转正考核表.png

TypeScript

    TypeScript是一种由微软开发的自由和开源的编程语言。它是JavaScript的一个超集,而且本质上向这个语言添加了可选的静态类型和基于类的面向对象编程
    TypeScript扩展了JavaScript的语法,所以任何现有的JavaScript程序可以不加改变的在TypeScript下工作。TypeScript是为大型应用之开发而设计,而编译时它产生 JavaScript 以确保兼容性。
    TypeScript 支持为已存在的 JavaScript 库添加类型信息的头文件,扩展了它对于流行的库如jQueryMongoDBNode.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 

    这就是最简单的浅拷贝,其效果十分明显,对拷贝源的操作,会直接体现在拷贝目标上,因为这个赋值行为的本质是内存地址的赋值,所以他们指向了同一片内存区域。

    浅拷贝十分容易,也十分常见,但却无法满足需求,假如我们需要获得与拷贝源完全相同,却又不会互相影响的对象,应该怎么办呢。

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;

由此可见,我们已经实现了对象的完全深拷贝。

我的问题也就迎刃而解;接下来,就可以开心的开发接下来的功能了。。。。不解决此问题真的木办法往下继续了。


image.png

越努力越幸运,愿你我一起共同努力。

上一篇下一篇

猜你喜欢

热点阅读