资讯专栏INFORMATION COLUMN

JavaScript的深浅拷贝

zhjx922 / 2300人阅读

摘要:实际上,是禁止这样做的。传值和传址基本数据类型赋值基本数据类型的赋值是在内存中新开辟一段栈内存,然后再把再将值赋值到新的栈中。结果见输出,可以看出来,无论是修改赋值得到的对象和浅拷贝得到的都会改变原始数据。

存储问题:
深拷贝和浅拷贝的主要区别:在内存中的存储类型(堆和栈)不同
堆:动态分配的内存,大小不定也不会自动释放
栈:自动分配的内存,由系统自动释放
数据类型:

基本数据类型:
 javascript的基本数据类型5种:undefined null  number  string boolean
 

存储位置

栈。原因:数据大小确定,内存空间大小可以分配,是直接按值存放的。

值是否可变?

基本数据类型值不可变,javascript中的原始值(undefined、null、布尔值、数字和字符串)与对象(包括数组和函数)有着根本区别。原始值是不可更改的:任何方法都无法更改(或“突变”)一个原始值。对       数字和布尔值来说显然如此 —— 改变数字的值本身就说不通,而对字符串来说就不那么明显了,因为字符串看起来像由字符组成的数组,我们期望可以通过指定索引来假改字符串中的字符。实际上,javascript 是禁止这样做的。字符串中所有的方法看上去返回了一个修改后的字符串,实际上返回的是一个新的字符串值。

基本类型的比较

基本类型的比较是值的比较,只要两个变量的值相等就认为他们是相等的。
比较最好用 === ,因为 == 会进行类型转换,例如:var a = 1; var b= true;if(a==b) 则会返回true

引用数据类型(object):

存储位置

堆。变量实际上是存放在栈内存中的一个指针,这个指针指向堆内存中的地址,每个空间大小不一样,要根据情况进行特定的分配。

值是否可变?

引用类型值可变
var a = [1,2,3];
a[1] = 5;
console.log(a[1]); // 5

应用类型的比较

引用类型的比较是引用的比较
所以每次我们对 js 中的引用类型进行操作的时候,都是操作其对象的引用(保存在栈内存中的指针),所以比较两个引用类型,是看其的引用是否指向同一个对象。
var a = [1,2,3];
var b = [1,2,3];
console.log(a === b); // false
虽然变量 a 和变量 b 都是表示一个内容为 1,2,3 的数组,但是其在内存中的位置不一样,也就是说变量 a 和变量 b 指向的不是同一个对象,所以他们是不相等的。

传值和传址

基本数据类型赋值

    基本数据类型的赋值(=)是在内存中新开辟一段栈内存,然后再把再将值赋值到新的栈中。
    var a = 10;
    var b = a;
    a ++;
    console.log(a); // 11
    console.log(b); // 10

引用数据类型赋值

但是引用类型的赋值是传址。只是改变指针的指向,例如,也就是说引用类型的赋值是对象保存在栈中的地址的赋值,这样的话两个变量就指向同一个对象,因此两者之间操作互相有影响。
  var a = {};  // a保存了一个空对象的实例 
  var b = a; // a和b都指向了这个空对象 
  a.name = "jozo";
  console.log(a.name); // "jozo" 
  console.log(b.name); // "jozo" 
  b.age = 22; 
  console.log(b.age);  // 22 
  console.log(a.age);  // 22 
  console.log(a == b);// true

浅拷贝

那么赋值和浅拷贝有什么区别呢,我们看下面这个例子:

var obj1 = {
    "name" : "zhangsan",
    "age" :  "18",
    "language" : [1,[2,3],[4,5]],
};

var obj2 = obj1;


var obj3 = shallowCopy(obj1);
function shallowCopy(src) {
    var dst = {};
    for (var prop in src) {
        if (src.hasOwnProperty(prop)) {
            dst[prop] = src[prop];
        }
    }
    return dst;
}

obj2.name = "lisi";
obj3.age = "20";

obj2.language[1] = ["二","三"];
obj3.language[2] = ["四","五"];

console.log(obj1);  
//obj1 = {
//    "name" : "lisi",
//    "age" :  "18",
//    "language" : [1,["二","三"],["四","五"]],
//};

console.log(obj2);
//obj2 = {
//    "name" : "lisi",
//    "age" :  "18",
//    "language" : [1,["二","三"],["四","五"]],
//};

console.log(obj3);
//obj3 = {
//    "name" : "zhangsan",
//    "age" :  "20",
//    "language" : [1,["二","三"],["四","五"]],
//};

先定义个一个原始的对象 obj1,然后使用赋值得到第二个对象 obj2,然后通过浅拷贝,将 obj1 里面的属性都赋值到 obj3 中。也就是说:

obj1:原始数据

obj2:赋值操作得到

obj3:浅拷贝得到

然后我们改变 obj2 的 name 属性和 obj3 的 name 属性,可以看到,改变赋值得到的对象 obj2 同时也会改变原始值 obj1,而改变浅拷贝得到的的 obj3 则不会改变原始对象 obj1。这就可以说明赋值得到的对象 obj2 只是将指针改变,其引用的仍然是同一个对象,而浅拷贝得到的的 obj3 则是重新创建了新对象。
然而,我们接下来来看一下改变引用类型会是什么情况呢,我又改变了赋值得到的对象 obj2 和浅拷贝得到的 obj3 中的 language 属性的第二个值和第三个值(language 是一个数组,也就是引用类型)。结果见输出,可以看出来,无论是修改赋值得到的对象 obj2 和浅拷贝得到的 obj3 都会改变原始数据。
这是因为浅拷贝只复制一层对象的属性,并不包括对象里面的为引用类型的数据。所以就会出现改变浅拷贝得到的 obj3 中的引用类型时,会使原始数据得到改变。

深拷贝:将 B 对象拷贝到 A 对象中,包括 B 里面的子对象,

浅拷贝:将 B 对象拷贝到 A 对象中,但不包括 B 里面的子对象

深拷贝

深拷贝是对对象以及对象的所有子对象进行拷贝。

怎么进行深拷贝?
思路就是递归调用刚刚的浅拷贝,把所有属于对象的属性类型都遍历赋给另一个对象即可
zepto深拷贝的例子
还需要继续了解深拷贝的实现方案。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/107090.html

相关文章

  • Javascript对象深浅拷贝

    摘要:开门见山,有人叫对象的复制为深复制浅复制,也有人叫深拷贝浅拷贝。高级属性修改深拷贝满足对象的复制,浅拷贝影响原数组。关于对象的深浅拷贝,暂且探索到这里,后续有新发现再进行补充。 showImg(https://segmentfault.com/img/remote/1460000014305581); 开门见山,有人叫对象的复制为深复制浅复制,也有人叫深拷贝浅拷贝。其实都是copy。 ...

    qieangel2013 评论0 收藏0
  • JavaScript专题之深浅拷贝

    摘要:专题系列第六篇,讲解深浅拷贝的技巧和以及实现深浅拷贝的思路前言拷贝也是面试经典呐数组的浅拷贝如果是数组,我们可以利用数组的一些方法比如返回一个新数组的特性来实现拷贝。所以我们可以看出使用和是一种浅拷贝。 JavaScript 专题系列第六篇,讲解深浅拷贝的技巧和以及实现深浅拷贝的思路 前言 拷贝也是面试经典呐! 数组的浅拷贝 如果是数组,我们可以利用数组的一些方法比如:slice、co...

    RancherLabs 评论0 收藏0
  • JavaScript深浅拷贝

    摘要:什么是深浅概念深拷贝浅拷贝只针对像这样的对象,对于基本类型而言,可以理解为是没有深浅的区别的。和指向了同一块内存深拷贝重新开辟了一个空间,修改对象的属性,彼此不会影响。并不会更改使用递归适用于对象里面有对象 什么是深浅 概念 深拷贝、浅拷贝只针对像Object/Array这样的对象,对于基本类型而言,可以理解为是没有深浅的区别的。 浅拷贝复制的是引用,修改对象的属性,会彼此影响。 ju...

    zhunjiee 评论0 收藏0
  • javascript深浅拷贝

    摘要:为何写最近在研究深浅拷贝,找了很多资料,感觉不是很满意,所以自己就整理了一份。深拷贝如果给放到新的内存中,将的各个属性都复制到新内存里,就是深拷贝。安全的值是指能够呈现为有效格式的值。参考文档冴羽的专题之深浅拷贝深拷贝与浅拷贝的实现 为何写: 最近在研究深浅拷贝,找了很多资料,感觉不是很满意,所以自己就整理了一份。废话不多说,我们来一起复习一下吧,也希望留下您宝贵意见。 何为深浅拷贝?...

    LMou 评论0 收藏0
  • 深浅拷贝

    摘要:深复制实现代码如下第一种方法通过递归解析解决第二种方法通过解析解决作者六师兄链接原生深拷贝的实现处理未输入新对象的情况通过方法构造新的对象 深浅拷贝针对的是 对象类型,如果是字符串的数组用[...arr],还是不会影响 要区分针对数组的深浅拷贝(默认情况为里面没有对象的数组),与针对对象的深浅拷贝 JavaScript数组深拷贝和浅拷贝的两种方法 let a1 = [1, 2]; ...

    Karrdy 评论0 收藏0
  • 复习Javascript专题(四):js中深浅拷贝

    摘要:基本数据类型的复制很简单,就是赋值操作,所以深浅拷贝也是针对,这类引用类型数据。它会抛弃对象的。另外,查资料过程中还看到这么一个词结构化克隆算法还有这一篇资料也有参考,也写得比较详细了的深浅拷贝 基本数据类型的复制很简单,就是赋值操作,所以深浅拷贝也是针对Object,Array这类引用类型数据。 浅拷贝对于字符串来说,是值的复制,而对于对象来说则是对对象地址的复制;而深拷贝的话,它不...

    MobService 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<