• JavaScript 深浅拷贝


    JavaScript有五种基本数据类型(Undefined, null, Boolean, String, Number),还有一种复杂的数据类型,就是对象。

    Undefined 其实是已声明但没有赋值的变量的输出结果,null其实就是一个不存在的对象的结果

    • 对于简单的数据类型
      它们值在占据了内存中固定大小的空间,并被保存在栈内存中。 当一个变量向另一个变量复制基本类型的值时,会创建这个值的副本,还有就是不能给基本类型的值添加属性。

      1
      2
      3
      4
      var a = 1;
      var b = a;
      a.attr = 'long';
      console.log(a.attr) //undefined

      上边代码中a就是简单数据类型(number),b就是a的副本,它们两者都占有不同位置,但相等的内存空间。

    • 对于复杂的数据类型
      复杂的数据类型即引用类型,它的值是对象,保存在堆内存中,包含引用类型值的变量实际上包含的并不是对象本身,而是一个指向该对象的指针。从一个变量向另一个变量复制引用类型的值,复制的其实是指针,因此两个变量最终都指向同一个对象。

      1
      2
      3
      4
      5
      6
      7
      8
      var obj = {
      name: 'long',
      age: 0
      };
      var obj2 = obj;
      obj2.c = 5;
      console.log(obj); //Oject {name: 'long', age: 0, c: 5}
      console.log(obj2); //Oject {name: 'long', age: 0, c: 5}

    我们可以看到obj赋值给obj2后,当我们更改其中一个对象的属性值,两个对象都发生了改变,究其原因是因为obj和obj2这两个变量都指向同一个指针,赋值是复制了指针,所以当我们改变其中一个值,就会影响另一个变量的值。

    浅拷贝

    其实上边的代码就是浅拷贝,有时候我们只是想备份数组,但是只是简单让它赋给一个变量,改变其中一个,另外一个就紧跟着改变,但很多时候这不是我们想要的。

    1
    2
    3
    4
    5
    6
    7
    8
    var obj = {
    name:'wsscat',
    age:0
    }
    var obj2 = obj;
    obj2['c'] = 5;
    console.log(obj);//Object {name: "wsscat", age: 0, c: 5}
    console.log(obj2);////Object {name: "wsscat", age: 0, c: 5}

    深拷贝

    数组

    对于数组我们可以使用slice()和concat()方法来解决上面的问题。

    • slice

      1
      2
      3
      4
      5
      var arr = ['ge', 'yu', 'long'];
      var arrCopy = arr.slice(0);
      arrCopy[0] = 'gai';
      console.log(arr) // ['ge', 'yu', 'long']
      console.log(arrCopy) // ['gai', 'yu', 'long']
    • concat

      1
      2
      3
      4
      var arr = ['ge', 'yu', 'long'];
      var arrCopy = arr.concat();
      arrCopy[0] = 'gai';
      //console跟上边一样

    对象

    对象我们可以定义一个新的对象并遍历新的属性去实现深拷贝
    原始方法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    var obj = {
    name: 'geyulong',
    age: 0
    };
    var obj2 = new Object();
    obj2.name = obj.name;
    obj2.age = obj.age;
    obj.name = "gaiyulong";
    console.log(obj); // Object {name: 'geyulong', age: 0}
    console.log(obj2); // Object {name: 'gaiyulong', age: 0}

    当然我们是要封装一个方法来实现深拷贝。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    var deepCopy = function(source) {
    var result = {};
    for(var key in source) {
    if(typeof source[key] === 'object') {
    result[key] = deepCopy(source[key])
    } else {
    result[key] = source[key]
    }
    }
    return result;
    }
    var obj2 = deepCopy(obj);

    ShareComments

  • 相关阅读:
    iOS开发--关闭ARC
    iOS开发--libxml/HTMLparser.h file not found 解决方法 (libxml.dylib错误处理)
    leetcode -- Dungeon Game
    网络编程之协程——gevent模块
    网络编程之协程——greenlet模块
    网络编程之协程
    网络编程之进程池与线程池
    网络编程之多线程——线程queue
    网络编程之多线程——信号量,Event,定时器
    网络编程之多线程——死锁现象与递归锁
  • 原文地址:https://www.cnblogs.com/libin-1/p/6412091.html
Copyright © 2020-2023  润新知