iis服务器助手广告广告
返回顶部
首页 > 资讯 > 前端开发 > JavaScript >JavaScript 赋值,浅复制和深复制的区别
  • 367
分享到

JavaScript 赋值,浅复制和深复制的区别

2024-04-02 19:04:59 367人浏览 薄情痞子
摘要

目录一、变量赋值1.1 原始值和引用值1.2 赋值二、浅复制(Shallow Copy)2.1 原生 javascript 中的浅复制Object.assign()2.2 浅复制的手

前言:

浅复制和深复制可以说是面试中很常见的一道题了,本文就来聊一聊JavaScript中的浅复制和深复制。

一、变量赋值

不知道会不会有人会和我一样,会觉得浅复制就是通过=操作符将一个变量赋值给另外一个变量。但实际上,浅复制和变量赋值之间是存在区别的。所以,我们先来了解一下变量赋值。

1.1 原始值和引用值

原始值(primitive value):最简单的数据,即:Undefined、Null、Boolean、Number、String、BigInt、Symbol这其中类型的值。保存原始值的变量是按值访问的,我们操作的就是存储在变量中的实际值。

引用值(reference value):有多个值构成的对象,即 Object 类型。引用值是保存在内存中的对象,但是 JavaScript 不允许直接访问内存位置,所以不能直接操作对象所在的内存空间。在操作对象时,实际操作的是该对象的引用(reference) 而非实际的对象本身。保存引用值得变量实际上存储得是对象得引用,是按引用访问得。

1.2 赋值

首先说明这里说的赋值,不是直接把引用值(例如:{})或者原始值(例如:false、1、"str"等)直接赋值给一个变量。而是通过变量把一个值赋值给另一个变量。

原始值赋值:保存原始值的变量是按值访问的,所以通过变量把一个原始值赋值给另一个变量时,原始值会被复制到新变量的位置。

let num1 = 5;
let num2 = num1;
console.log(num1, num2);  // 5 5
num2 = 4;
console.log(num1, num2);  // 5 4

可以看出 num2 通过 num1 被赋值为5,保存的是同一个原始值。而且两个变量相互独立,互不干扰。

具体赋值过程如下:

引用值赋值:保存引用值的变量是按引用访问的,通过变量把一个引用赋值给另一个变量时,存储在变量中的值也会被复制到新变量的位置。但是,这里复制的实际上是一个指向存储在堆内存中对象的指针。赋值后,两个变量实际上指向同一个对象。所以两个变量通过引用对对象的操作会互相影响。

let obj1 = {};
let obj2 = obj1;
console.log(obj1);  // {}
console.log(obj2);  // {}
obj1.name = 'haha';
console.log(obj1);  // { name: 'haha' }
console.log(obj2);  // { name: 'haha' }
obj1.age = 24;
console.log(obj1);  // { name: 'haha', age: 24 }
console.log(obj2);  // { name: 'haha', age: 24 }

如上代码,通过 obj1 将指向对象的引用赋值给 obj2后, obj1 和 obj2 保存了指向同一对象的引用,所以操作的是同一对象。

具体可见下图:

注:如上两图来自《JavaScript 高级程序设计(第四版)》

接下来要说的浅复制和深复制就是针对引用值而言的。

二、浅复制(Shallow Copy)

我们先来看一篇博客中对于浅复制的定义:

An object is said to be shallow copied when the source top-level properties are copied without any reference and there exist a source property whose value is an object and is copied as a reference. If the source value is a reference to an object, it only copies that reference value to the target object.

对此,个人的理解浅复制就是复制该对象的的每个属性,如果该属性值是原始值,则复制该原始值,如果属性值是一个对象,那么就复制该对象的引用。

即:浅复制将复制顶层属性,但嵌套对象在原始(源)和拷贝(目标)之间共享

2.1 原生 JavaScript 中的浅复制

Object.assign()

Object.assign()方法将所有可枚举(Object.propertyIsEnumerable()返回 true)和自有(Object.hasOwnProperty()返回 true)属性从一个或多个源对象复制(浅复制) 到目标对象,返回修改后的对象。

如下代码可以看出,浅复制和变量赋值不同,修改对象的属性值互不影响。

const source = { a: 1, b: 2 };
const objCopied = Object.assign({}, source);

console.log(objCopied); // { a: 1, b: 2 }

source.a = 3;
console.log(source);  // { a: 3, b: 2 }
console.log(objCopied);  // { a: 1, b: 2 }

objCopied.a = 4;
console.log(source);  // { a: 3, b: 2 }
console.log(objCopied);  // { a: 4, b: 2 }

对象内的嵌套对象在源对象和拷贝对象之间还是共享的,如上代码,修改对象内对象的属性时会相互影响。

const source = { a : {b : 1} };
const objCopied = Object.assign({}, source);

console.log(objCopied); // { a: { b: 1 } }

source.a.b = 3;
console.log(source);  // { a: { b: 3 } }
console.log(objCopied);  // { a: { b: 3 } }

但是注意如下代码中,source.a = {};修改的是源对象中属性的值,这个并不共享。

const source = { a : {b : 1} };
const objCopied = Object.assign({}, source);

console.log(objCopied); // { a: { b: 1 } }

source.a = {};
console.log(source);  // { a: {} }
console.log(objCopied);  // { a: { b: 1 } }

展开运算符(...):展开语法(Spread syntax), 可以在函数调用/数组构造时, 将数组表达式或者string在语法层面展开;还可以在构造字面量对象时, 将对象表达式按key-value的方式展开。

const source = { a : {b : 1}, c: 2 };
const objCopied = {...source}

console.log(objCopied); // { a: { b: 1 }, c: 2 }

source.c = 3;
console.log(source);  // { a: { b: 1 }, c: 3 }
console.log(objCopied);  // { a: { b: 1 }, c: 2 }

source.a.b = 3;
console.log(source);  // { a: { b: 3 }, c: 3 }
console.log(objCopied);  // { a: { b: 3 }, c: 2 }

2.2 浅复制的手动实现

function shallowClone(source) {
    // 如果是原始值,直接返回
    if (typeof source !== 'object') {
        return source;
    }

    // 拷贝后的对象
    const copied = Array.isArray(source) ? [] : {};
    // 遍历对象的key
    for(let key in source) {
        // 如果key是对象的自有属性
        if(source.hasOwnProperty(key)) {
            // 复制属性
            copied[key] = source[key]
        }
    }

    // 返回拷贝后的对象
    return copied;
}

三、深复制(Deep Copy)

首先来看深复制的定义:

A deep copy will duplicate every object it encounters. The copy and the original object will not share anything, so it will be a copy of the original.

与浅复制不同时,当源对象属性的值为对象时,赋值的是该对象,而不是对象的引用。所以深复制中,源对象和拷贝对象之间不存在任何共享的内容。

2.1 原生 JavaScript 中的深复制

JSON.parse(JSON.stringify(object))

JavaScript 中最常见的深复制的方法就是JSON.parse(JSON.stringify(object))

如下代码所示,深复制中源对象和拷贝对象不共享任何内容,即使是嵌套对象。

let obj = {
    a: 1,
    b: {
        c: 2,
    },
}
let newObj = JSON.parse(JSON.stringify(obj));
obj.b.c = 20;
console.log(obj); // { a: 1, b: { c: 20 } }
console.log(newObj); // { a: 1, b: { c: 2 } }

2.2 深复制的手动实现

function deepClone(source) {
    // 如果是原始值,直接返回
    if (typeof source !== 'object') {
        return source;
    }
    // 拷贝后的对象
    const copied = Array.isArray(source) ? [] : {};
    // 遍历对象的key
    for(let key in source) {
        // 如果key是对象的自有属性
        if(source.hasOwnProperty(key)) {
            // 深复制
            copied[key] = deepClone(source[key]);
        }
    }
    return copied;
}

有关浅复制和深复制的手动实现,这里只是简单实现了一下。其中还有很多细节未实现,具体的实现大家可以参见 lodash 中的实现。

小结

  • 赋值操作符是把一个对象的引用赋值给一个变量,所以变量中存储的是对象的引用
  • 浅复制是复制源对象的每个属性,但如果属性值是对象,那么复制的是这个对象的引用。所以源对象和拷贝对象之间共享嵌套对象。
  • 深复制与浅复制不同的地方在于,如果属性值为对象,那么会复制该对象。源对象和拷贝对象之间不存在共享的内容。

到此这篇关于JavaScript 赋值,浅复制和深复制的区别的文章就介绍到这了,更多相关JS 赋值内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: JavaScript 赋值,浅复制和深复制的区别

本文链接: https://www.lsjlt.com/news/149721.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • JavaScript 赋值,浅复制和深复制的区别
    目录一、变量赋值1.1 原始值和引用值1.2 赋值二、浅复制(Shallow Copy)2.1 原生 JavaScript 中的浅复制Object.assign()2.2 浅复制的手...
    99+
    2024-04-02
  • JavaScript赋值,浅复制和深复制的区别是什么
    本篇内容介绍了“JavaScript赋值,浅复制和深复制的区别是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1、变量赋值不知道会不会有...
    99+
    2023-06-30
  • Python中的赋值与浅复制与深复制之间
    #赋值与浅复制一层列表 """a = [1, 2]    b = a   #赋值c = a.copy() #浅复制a.append(3)     print(b)  #父对象改变print(c)  #父对象不变'''[1, 2, 3][1...
    99+
    2023-01-30
    赋值 Python
  • C++深复制和浅复制讲解
    目录前言:1、什么是浅复制2、如何实现深复制前言: 深复制和浅复制在python中同样存在,但是由于python中没有指针这个概念,所以当时学python时理解这个问题非常困难。实际...
    99+
    2024-04-02
  • Java 浅复制和深复制的实例详解
    Java 浅复制和深复制的实例详解1 浅复制和深复制区别浅复制:浅复制只是复制本对象的原始数据类型,如int、float、String,对于数组和对象引用等是不会复制的。因此浅复制是有风险的。深复制:不但对原始数据类型进行复制,对于对象中的...
    99+
    2023-05-31
    java 浅复制 深复制
  • Java对象复制(直接赋值,浅拷贝,深拷贝)
    目录 Java对象复制1,直接赋值2,浅拷贝3,深拷贝4,序列化拷贝 Java对象复制 将一个对象的引用复制给另一个对象,一共有三种方式。第一种是直接赋值,第二种方式是浅拷贝,第三种是...
    99+
    2023-08-31
    java
  • C++中深复制和浅复制是什么
    这篇文章主要为大家展示了“C++中深复制和浅复制是什么”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“C++中深复制和浅复制是什么”这篇文章吧。1、什么是浅复制在C++中深复制和浅复制最大的区别在...
    99+
    2023-06-29
  • JavaScript数组中的深复制与浅复制是什么
    本篇内容介绍了“JavaScript数组中的深复制与浅复制是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所...
    99+
    2024-04-02
  • 深入浅析Java中对象的深复制与浅复制
    本篇文章为大家展示了深入浅析Java中对象的深复制与浅复制,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。 Java对象深复制与浅复制实例详解我们在遇到一些业务场景的时候经常需要对对象进行复...
    99+
    2023-05-31
    java 对象 中对
  • python中的深复制和浅复制是什么意思
    本篇内容介绍了“python中的深复制和浅复制是什么意思”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!0、定义:    ...
    99+
    2023-06-04
  • python变量及浅复制与深复制
    一、变量及定义:     变量定义:一段存放在内存特定区域的空间,在python中变量名没有类型,引用的对象有类型之分;     命名规则:字母或下划线开头,不能以数字开头。     特殊变量:以单下划线(_)开头的变量 不能被 from ...
    99+
    2023-01-31
    变量 python
  • js中如何复制一个数组(浅复制、深复制)
    目录下面介绍数组的浅复制方法一:concat()方法二:slice()方法三:扩展运算符方法四: Object.assign()下面是深复制方法一:JSON.parse(J...
    99+
    2023-05-15
    js复制数组 js浅复制 js深复制
  • Java中对象的深复制和浅复制的详细介绍
    这篇文章主要介绍“Java中对象的深复制和浅复制的详细介绍”,在日常操作中,相信很多人在Java中对象的深复制和浅复制的详细介绍问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java中对象的深复制和浅复制的详...
    99+
    2023-06-17
  • python 中赋值,深拷贝,浅拷贝的区别
    目录一、赋值实例二、浅拷贝实例三、深拷贝实例赋值:其实就是对象的引用(相当于取别名)。浅拷贝(copy):拷贝父对象,不会拷贝对象内部的子对象,会引用子对象。深拷贝(deepcopy...
    99+
    2024-04-02
  • python3-列表的深浅复制
    # Auther: Aaron Fannames = ["aaron", "alex", "james", "meihengfan"]#复制一份列表#浅复制 (注意,这只是一个浅复制,只能复制第一层列表里面的东西,如果列表里面还有一层列表,...
    99+
    2023-01-31
    深浅 列表
  • JS的深浅复制详细
    目录1、浅复制的意思2、深复制的意思3、使用深复制的原由4、可实现深复制的几种方法实现方式一:JSON的序列化与反序列化实现方式二:Object.assign()实现方式三:扩展运算...
    99+
    2024-04-02
  • Python中赋值、浅拷贝、深拷贝三者的区别
    本篇文章为大家展示了Python中赋值、浅拷贝、深拷贝三者的区别,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。python有哪些常用库python常用的库:1.requesuts;2.scrapy;...
    99+
    2023-06-14
  • mysql同步复制和异步复制有什么区别
    这篇文章主要介绍mysql同步复制和异步复制有什么区别,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!区别:异步复制是Master将事件写入binlog,提交事务,自身并不知道slav...
    99+
    2024-04-02
  • Python基础之赋值,浅拷贝,深拷贝的区别
    目录一、赋值二、浅拷贝三、深拷贝四、例子一、赋值 不会开辟新的内存空间,只是复制了新对象的引用。所以当一个数据发生变化时,另外一个数据也会随之改变。 二、浅拷贝 创建新对象,其内容是...
    99+
    2024-04-02
  • Mysql异步复制、同步复制、半同步复制的区别
    这篇文章主要介绍“Mysql异步复制、同步复制、半同步复制的区别”,在日常操作中,相信很多人在Mysql异步复制、同步复制、半同步复制的区别问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作