面试官:(...)扩展运算符是深拷贝吗?

大家好,我是勇宝,一名正在学习前端的打工仔,欢迎大家关注我,一起探讨更多前端小知识。今天我们来好好唠一唠深浅拷贝

一、情景再现

金三银四,最近找工作的小伙伴是扑面而来,这其中少不了我的好朋友张某某同学,我们'相依为命',我经常开导他,这不最近的一次面试中他就遇到这样一个考题:

面试官:(...)是深拷贝吗?

二、JavaScript数据类型

在聊深浅拷贝之前,我们先来说一说JS中的数据类型:

我们都知道JavaScript中有两种数据类型(基本类型引用类型),那么我就先考考大家:数据类型都有什么?

  • 基本数据类型 :String(字符串)、Number(数值)、Boolean(布尔值)、Null、Undefined、Symbol;
    • 基本数据类型是直接存储在栈中。
  • 引用数据类型 :Array、Object;
    • 引用类型存储的是该对象在栈中的引用,真正的数据是存储在内存(堆)中的。

举例一

js 复制代码
let name = 'iyongbao';
let name2 = name;

name2 = 'zhangsan';

console.log(name); // iyongbao
console.log(name2); // zhangsan

举例二

js 复制代码
let obj = { name: 'iyongbao' };
let obj2 = obj;

obj2.name = 'zhangsan';

console.log(obj); // {name: "zhangsan"}
console.log(obj2); // {name: "zhangsan"}

上线的案例都是'拷贝',从中我们可以看到,引用类型的赋值会影响到原数据,这其实就是浅拷贝

二、探究深浅拷贝

对于深浅拷贝,勇宝给出自己的理解:

浅拷贝:对于浅拷贝也就是基本数据类型,拷贝后的值无论怎么变化都不会影响到原数据;而对于引用类型来说,有的人认为浅拷贝是会拷贝对象的第一层值,也就是说对象通过浅拷贝当我们修改新复制对象的一层属性时,原数据不会发生改变。

深拷贝:无限层级拷贝。在深拷贝中,修改基本数据类型和引用数据类型都不会影响原有的数据类型。

js 复制代码
// 浅拷贝
let obj = { a: 1, b: { c: 2 } };

let obj2 = { ...obj };

obj2.a = 3;
obj2.b.c = 4;

console.log(obj); // {a:1, b: { c: 4 }}
console.log(obj2); // {a: 3, b: { c: 4 }}

结论 :通过上边的案例,我们可以看出...(拓展运算符)是一个浅拷贝

js 复制代码
// 深拷贝
let obj = { a: 1, b: { c: 2 } };

let obj2 = JSON.parse(JSON.stringify(obj));

obj2.a = 3;
obj2.b.c = 4;

console.log(obj); // {a:1, b: { c: 2 }}
console.log(obj2); // {a: 3, b: { c: 4 }}

关于JSON.stringify大家可以看一看我的另一篇文章:你不知道的JSON.stringify神操

三、浅拷贝方法

3.1 直接赋值

js 复制代码
let obj = {
    name: 'iyongbao',
    age: 26
}

let obj2 = obj;
obj2.name = "zhangsan";

console.log(obj); // {name: "zhangsan", age: 26}
console.log(obj2); // {name: "zhangsan", age: 26}

3.2 Object.assign

js 复制代码
let obj = {
    name: 'iyongbao',
    score: {
        vue: 98
    }
}

let obj2 = Object.assign({}, obj);

obj2.name = "zhangsan";
obj2.score.vue = 60;

console.log(obj); // {name: "iyongbao", score: { vue: 60 }}
console.log(obj2); // {name: "zhangsan", score: { vue: 60 }}

注意 :使用Object.assign第一层是深拷贝。

3.3 扩展运算符

js 复制代码
let obj = {
    name: 'iyongbao',
    score: {
        vue: 98
    }
}

let obj2 = { ...obj };

obj2.name = "zhangsan";
obj2.score.vue = 60;

console.log(obj); // {name: "iyongbao", score: { vue: 60 }}
console.log(obj2); // {name: "zhangsan", score: { vue: 60 }}

注意扩展运算符Object.assign的效果一样。

3.4 slice和concat

slice是截取数组,concat是拼接数组。

js 复制代码
let obj = ['iyongbao', score: { vue: 98 }]

let obj2 = obj.slice();
let obj3 = obj.concat();

obj[0] = "zhangsan";
obj[1].vue = 60;

console.log(obj); // {name: "zhangsan", score: { vue: 60 }}
console.log(obj2); // {name: "iyongbao", score: { vue: 60 }}
console.log(obj3); // {name: "iyongbao", score: { vue: 60 }}

四、深拷贝方法

4.1 JSON.parse(JSON.stringify(待拷贝对象))

这里使用的还挺多的。

js 复制代码
let obj = {
    name: 'iyongbao',
    age: 26
}

let obj2 = JSON.parse(JSON.stringify(obj));
obj2.name = "zhangsan";

console.log(obj); // {name: "iyongbao", age: 26}
console.log(obj2); // {name: "zhangsan", age: 26}

4.2 使用第三方库 Lodash

js 复制代码
const _ = require('lodash');

let obj = {
    name: 'iyongbao',
    age: 26
}

let obj2 = _.cloneDeep(obj);
obj2.name = "zhangsan";

console.log(obj); // {name: "iyongbao", age: 26}
console.log(obj2); // {name: "zhangsan", age: 26}

4.3、手写一个深拷贝

JSON.stringify还是存在一些不足的,比如对`(函数、undefined、正则、Symbol)不友好,下面我们就自己来动手写一个简单的深拷贝方法。

js 复制代码
function deepClone (obj) {
    if (typeof obj !== 'object' || obj == null) {
        return obj;
    }
    
    let deepCloneObj = Array.isArray(obj) ? [] : {}
    
    for (let key in obj) {
        if (obj.hasOwnProperty(key)) {
            deepCloneObj[key] = deepClone(obj[key]);
        }
    }
}

五、总结

深浅拷贝JavaScript开发中有着不同的应用场景和实现方式。了解它们的区别对于正确处理对象和数组的赋值是至关重要的。希望通过今天的分享,能够帮助小伙伴们更好的去加深与理解。

相关推荐
LuckyLay1 小时前
React百日学习计划——Deepseek版
前端·学习·react.js
gxn_mmf1 小时前
典籍知识问答重新生成和消息修改Bug修改
前端·bug
hj10431 小时前
【fastadmin开发实战】在前端页面中使用bootstraptable以及表格中实现文件上传
前端
乌夷1 小时前
axios结合AbortController取消文件上传
开发语言·前端·javascript
晓晓莺歌2 小时前
图片的require问题
前端
码农黛兮_462 小时前
CSS3 基础知识、原理及与CSS的区别
前端·css·css3
水银嘻嘻2 小时前
web 自动化之 Unittest 四大组件
运维·前端·自动化
(((φ(◎ロ◎;)φ)))牵丝戏安2 小时前
根据输入的数据渲染柱形图
前端·css·css3·js
wuyijysx3 小时前
JavaScript grammar
前端·javascript
溪饱鱼3 小时前
第6章: SEO与交互指标
服务器·前端·microsoft