js的浅拷贝和深拷贝

常常遇到数组或对象等引用类型做为函数的参数的状况,但又不想修改原来的数据,这时候就须要拷贝(基本类型的变量不须要考虑)。
拷贝分为浅拷贝深拷贝。浅拷贝是引用复制,深拷贝是彻底单纯拷贝数据的值。由于数组是最多见的引用类型,因此下面大部分拿数组举例。git

  • 浅拷贝

  • 简单把引用复制
var a = [1,2,3]
var b = a
console.log(b) //Array(3) [1, 2, 3]
b[1] = 0
console.log(b) //Array(3) [1, 0, 3]
console.log(a) //Array(3) [1, 0, 3]

能够看出,修改数组b的时候,数组a也被修改了。这显然不是想要的作法。es6

要想不改变原来的数组,就要用到如下的几种方法:github

var a = [1,2,3]
var b = a.concat() //或 var b = [].concat(a)
console.log(b) //Array(3) [1, 2, 3]
b[1] = 0
console.log(b) //Array(3) [1, 0, 3]
console.log(a) //Array(3) [1, 2, 3]
var a = [1,2,3,4,5]
var b = a.slice(0)
console.log(b) //Array(5) [1, 2, 3, 4, 5]
b[0] = 0
console.log(a) //Array(5) [1, 2, 3, 4, 5]
console.log(b) //Array(5) [0, 2, 3, 4, 5]

还能够部分拷贝json

var a = [1,2,3,4,5]
var b = a.slice(1, 3) //返回[1,3)下标区间的数
console.log(b) //Array(2) [2, 3]
//负数也能够
console.log(a.slice(-2)) //Array(2) [4, 5]

还有一种方法,跟循环的方法有点相似,就是es6的新特性,展开语法数组

var a = [1,2,3,4,5]
var b = [...a]
b[0] = 0
console.log(a) //Array(5) [1, 2, 3, 4, 5]

这个方法就是逐一枚举a中的值,放到空数组中函数

可是,以上这几种拷贝方法看似都不会改变原来数组,其实也仍是属于浅拷贝范畴。若是原数组里面还有引用类型数组,这些方法都会失效(好比二维数组)code

var a = [[1,2,3],[4,5,6]]
var b = a.slice(0)
b[0][4] = 0
console.log(a[0]) //[[1, 2, 0],[4,5,6]]

其余concat,[...]等方法也同样。
能够这么理解:原数组就像一个带锁的独一无二的箱子,里面有各类零食。简单的引用复制,其实就是配了一把钥匙,谁动过里面的东西,其余人都会受到影响。而上面这4种方法其实就是本身买一个不一样箱子,参照原来的箱子里面的零食,去某宝买同款。动本身箱子的东西,原来的箱子不受影响。可是若是原来的箱子里面还套了个独一无二带锁的箱子,某宝买不到同款,那没办法,里面的箱子只能仍是配把钥匙共用。因此,这4种方法只是简单绕过第一层箱子的引用复制对象


  • 深拷贝

目前比较好的方法就是json大法JSON.stringify(),要么就是本身写递归的深拷贝函数。
JSON.stringify()是将对象或数组序列化成字符串。而后再用JSON.parse()解析成值或对象。递归

var a = {aa:1,bb:[1,2],cc:[3,4]}
var b = JSON.parse(JSON.stringify(a))
console.log(b) //{aa:1,bb:[1,2],cc:[3,4]}
b.cc[0] = 0
console.log(a) //{aa:1,bb:[1,2],cc:[3,4]}
console.log(b) //{aa:1,bb:[1,2],cc:[0,4]}

附带深拷贝的自定义函数(源自大佬mqyqingfeng的github)ip

var deepCopy = function(obj) {
    if (typeof obj !== 'object') return;
    var newObj = obj instanceof Array ? [] : {};
    for (var key in obj) {
        if (obj.hasOwnProperty(key)) {
            newObj[key] = typeof obj[key] === 'object' ? deepCopy(obj[key]) : obj[key];
        }
    }
    return newObj;
}
相关文章
相关标签/搜索