js的赋值,浅拷贝,深拷贝。

82 阅读3分钟

赋值,浅拷贝,深拷贝。在我们日常开发中可谓是无处不在,今天简单总结一下。

1.赋值。

在js的基本数据类型中(string, number, boolean, null, undefined, symbol),赋值就是将一个变量的值复制一份在给另一个变量,其中一个只改变,并不影响另一个值。如

   let a='123';
   let b=a;
   b='456'
   console.log('a:',a,'b:',b)//a:'123',b:'456'

但是如果是引用类型(对象,数组等)直接写等号赋值是将地址赋值到另一个变量, 其中一个改变,会影响到另一个变量,如

   let a=[1,2,3]
   let b=a
   b[0]=4
   console.log(a);//[4,2,3]
   

如果我们不想原变量受到影响,这个时候我们就会用到深浅拷贝。

2.浅拷贝

那么什么是浅拷贝呢?当我们想要拷贝的数组或对象的内部的值是基本类型时,如[1,2,3]或{name:tom,age:12}。浅拷贝可以拷贝它的值,而且改变拷贝的值,是不会影响原来的值的。如

 let a=[1,2,3];
 let b=[...a];//用es6的...号可以很容易的实现浅拷贝
 b[0]=9;
 console.log(a)//1,2,3
 console.log(b)//9,2,3

但是如果数组或对象内部还有数组或对象会怎么样了?看下面

let a=[1,2,[1,2,3,6]]
let b=[...a]
b[0]=9;
b[2][1]=8;
console.log(a);//1,2,[1,8,3,6]
console.log(b);//9,2,[1,8,3,6]

一目了然,对内部的基本类型数据更改不会影响原来的值,但是引用类型会影响。这个时候我们会用到深拷贝。

3.深拷贝

无论它的对象或数组嵌套了多少层如 [1,2,[2,1,[1,2]]]类似的,深拷贝都能实现对值的拷贝。改变拷贝值不会影响原来的值。 首先我们先说一下最简单的方法

let obj={
  name:'tom'
}
let obj2=JSON.parse(JSON.stringfy(obj))//先把原对象转化为字符串,再转化为对象,这时的对象已经是新的了

但是这样会有局限性,如果对象里面有函数或者promise等复杂的对象,就不行了。

这时我们要手动写,或者引用相关的库( lodash的deepClone方法)(Lodash 简介 | Lodash 中文文档 | Lodash 中文网 (lodashjs.com))。

手动实现如下

//定义检测数据类型的功能函数
    function checkedType(target) {
      return Object.prototype.toString.call(target).slice(8, -1)
    }
    //实现深度克隆---对象/数组
    function clone(target) {
      //判断拷贝的数据类型
      //初始化变量result 成为最终克隆的数据
      let result, targetType = checkedType(target)
      if (targetType === 'Object') {
        result = {}
      } else if (targetType === 'Array') {
        result = []
      } else {
        return target
      }
      //遍历目标数据
      for (let i in target) {
        //获取遍历数据结构的每一项值。
        let value = target[i]
        //判断目标结构里的每一值是否存在对象/数组
        if (checkedType(value) === 'Object' ||
          checkedType(value) === 'Array') { //对象/数组里嵌套了对象/数组
          //继续遍历获取到value值
          result[i] = clone(value)
        } else { //获取到value值是基本的数据类型或者是函数。
          result[i] = value;
        }
      }
      return result
    }

以上就是全部了,大家看的同时,可以在浏览器里面试一下。