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

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

一、情景再现

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

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

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

相关推荐
霸王蟹4 分钟前
带你手写React中的useReducer函数。(底层实现)
前端·javascript·笔记·学习·react.js·typescript·前端框架
托尼沙滩裤9 分钟前
【Vue3】实现屏幕共享惊艳亮相
前端·javascript·vue.js
啃火龙果的兔子14 分钟前
前端八股文-vue篇
前端·javascript·vue.js
孜然卷k20 分钟前
前端处理后端对象类型时间格式通用方法封装,前端JS处理JSON 序列化后的格式 java.time 包中的日期时间类
前端·json
幼儿园技术家24 分钟前
微信小程序实现用户进行推客的注册绑定
前端
gwcgwcjava27 分钟前
[技术积累]成熟的前端和后端开发框架
前端
bbsh209929 分钟前
SiteAzure:SetCookie 未设置Secure
前端·网络·安全·siteazure
Mintopia1 小时前
计算机图形学环境贴图(Environment Mapping)教学指南
前端·javascript·计算机图形学
码农之王1 小时前
(二)TypeScript前置编译配置
前端·后端·typescript
spmcor1 小时前
css 之 Flexbox 的一生
前端·css