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

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

一、情景再现

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

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

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

相关推荐
梦曦i2 小时前
@meng-xi/create-uni-app vs unibest:轻量脚手架与重型框架的定位之争
前端·uni-app
平头哥技术团队2 小时前
Day 10 | 工欲善其事:VS Code 配置与项目归档
android·开发语言·前端·javascript·html·交互
乌恩大侠2 小时前
GH200 新增 NVMe SSD 分区、格式化与挂载完整流程
运维·服务器·前端
yume_sibai2 小时前
Element Plus 数据展示组件完全指南(15个核心组件)
前端·javascript·vue.js
qiuhaipeng13 小时前
Claude code 升级后上下文长度变短问题
java·前端·数据库
zzz_23683 小时前
个人 AI 记忆如何跨工具复用:用 Markdown、索引和 Skill 搭一个可治理的记忆库
前端·人工智能·react.js·前端框架·agent·agent测评
剑之所向5 小时前
.NET 官方`System.Threading.Channels`
前端·javascript·数据库
计算机魔术师5 小时前
GPT-6 Astra幻觉砍到2%,却被一种老招数轻松绕过
前端
cjy0001116 小时前
2026AI 产品如何从一次性 Demo 变成可重复使用的业务工具?
前端·人工智能·fde
IT_陈寒6 小时前
React的状态更新坑得我差点加班到天亮
前端·人工智能·后端