JavaScript专题之深浅拷贝

简介: JavaScript 专题系列第六篇,讲解深浅拷贝的技巧和以及实现深浅拷贝的思路

1.png

JavaScript 专题系列第六篇,讲解深浅拷贝的技巧和以及实现深浅拷贝的思路


前言


拷贝也是面试经典呐!


数组的浅拷贝


如果是数组,我们可以利用数组的一些方法比如:slice、concat 返回一个新数组的特性来实现拷贝。


比如:


var arr = ['old', 1, true, null, undefined];
var new_arr = arr.concat();
new_arr[0] = 'new';
console.log(arr) // ["old", 1, true, null, undefined]
console.log(new_arr) // ["new", 1, true, null, undefined]复制代码


用 slice 可以这样做:


var new_arr = arr.slice();复制代码


但是如果数组嵌套了对象或者数组的话,比如:


var arr = [{old: 'old'}, ['old']];
var new_arr = arr.concat();
arr[0].old = 'new';
arr[1][0] = 'new';
console.log(arr) // [{old: 'new'}, ['new']]
console.log(new_arr) // [{old: 'new'}, ['new']]复制代码


我们会发现,无论是新数组还是旧数组都发生了变化,也就是说使用 concat 方法,克隆的并不彻底。


如果数组元素是基本类型,就会拷贝一份,互不影响,而如果是对象或者数组,就会只拷贝对象和数组的引用,这样我们无论在新旧数组进行了修改,两者都会发生变化。


我们把这种复制引用的拷贝方法称之为浅拷贝,与之对应的就是深拷贝,深拷贝就是指完全的拷贝一个对象,即使嵌套了对象,两者也相互分离,修改一个对象的属性,也不会影响另一个。


所以我们可以看出使用 concat 和 slice 是一种浅拷贝。


数组的深拷贝


那如何深拷贝一个数组呢?这里介绍一个技巧,不仅适用于数组还适用于对象!那就是:


var arr = ['old', 1, true, ['old1', 'old2'], {old: 1}]
var new_arr = JSON.parse( JSON.stringify(arr) );
console.log(new_arr);复制代码


是一个简单粗暴的好方法,就是有一个问题,不能拷贝函数,我们做个试验:


var arr = [function(){
    console.log(a)
}, {
    b: function(){
        console.log(b)
    }
}]
var new_arr = JSON.parse(JSON.stringify(arr));
console.log(new_arr);复制代码


我们会发现 new_arr 变成了:


不能拷贝函数


浅拷贝的实现


以上三个方法 concat、slice、JSON.stringify 都算是技巧类,可以根据实际项目情况选择使用,接下来我们思考下如何实现一个对象或者数组的浅拷贝。


想一想,好像很简单,遍历对象,然后把属性和属性值都放在一个新的对象不就好了~


嗯,就是这么简单,注意几个小点就可以了:


var shallowCopy = function(obj) {
    // 只拷贝对象
    if (typeof obj !== 'object') return;
    // 根据obj的类型判断是新建一个数组还是对象
    var newObj = obj instanceof Array ? [] : {};
    // 遍历obj,并且判断是obj的属性才拷贝
    for (var key in obj) {
        if (obj.hasOwnProperty(key)) {
            newObj[key] = obj[key];
        }
    }
    return newObj;
}复制代码


深拷贝的实现


那如何实现一个深拷贝呢?说起来也好简单,我们在拷贝的时候判断一下属性值的类型,如果是对象,我们递归调用深拷贝函数不就好了~


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;
}复制代码


性能问题


尽管使用深拷贝会完全的克隆一个新对象,不会产生副作用,但是深拷贝因为使用递归,性能会不如浅拷贝,在开发中,还是要根据实际情况进行选择。


下期预告


难道到这里就结束了?是的。然而本篇实际上是一个铺垫,我们真正要看的是 jquery 的 extend 函数的实现,下一篇,我们会讲一讲如何从零实现一个 jquery 的 extend 函数。


专题系列


JavaScript专题系列目录地址:github.com/mqyqingfeng…


JavaScript专题系列预计写二十篇左右,主要研究日常开发中一些功能点的实现,比如防抖、节流、去重、类型判断、拷贝、最值、扁平、柯里、递归、乱序、排序等,特点是研(chao)究(xi) underscore 和 jQuery 的实现方式。


如果有错误或者不严谨的地方,请务必给予指正,十分感谢。如果喜欢或者有所启发,欢迎 star,对作者也是一种鼓励。


目录
相关文章
|
2月前
|
JSON 前端开发 JavaScript
JavaScript拷贝大作战:浅拷贝vs深拷贝
JavaScript拷贝大作战:浅拷贝vs深拷贝
50 0
|
3月前
|
JSON 缓存 JavaScript
拷贝对象,拷贝快乐:揭开JavaScript中拷贝的神奇面纱
拷贝对象,拷贝快乐:揭开JavaScript中拷贝的神奇面纱
|
8月前
|
JavaScript
理解JS的深浅拷贝以及深度拷贝解决双向绑定的问题
理解JS的深浅拷贝以及深度拷贝解决双向绑定的问题
54 0
|
11月前
|
存储 JSON JavaScript
Javascript中的对象拷贝(对象复制/克隆)
本文介绍 Javascript中的对象拷贝(对象复制/克隆)的实现方式
209 0
Javascript中的对象拷贝(对象复制/克隆)
|
12月前
|
存储 JSON JavaScript
都2022年了你不会还没搞懂JS赋值拷贝、浅拷贝、深拷贝吧
面试中能把JS赋值拷贝、浅拷贝、深拷贝问题说明白的寥寥无几。今天笔者再来温习一遍,希望能对你有所帮助
116 0
|
JavaScript
js如何拷贝元数据后,更改数据不对元数据有影响
js如何拷贝元数据后,更改数据不对元数据有影响
|
JavaScript
js 通过lodash拷贝对象
js 通过lodash拷贝对象
84 0
|
存储 前端开发 JavaScript
深入理解JavaScript-拷贝的秘密
深入理解JavaScript-拷贝的秘密
70 0
JavaScript-手写优秀的拷贝
面试中,大家经常会遇到,面试官让你讲述什么是深拷贝,什么是浅拷贝,如何实现深拷贝,如何实现浅拷贝。这都是一下面试中经常遇到的问题。我们如果不经能说出,还能写出,那你就很叼了。
87 0
|
JavaScript 前端开发
JS的数组和对象深层拷贝(二十一)
JS的数组和对象深层拷贝(二十一)