JavaScript Topic 5: Deep and Shallow Copy
Understand the process behind copying and avoid unnecessary mistakes. Let’s work together on the deep and shallow copying of Js special series~
Contents
- 1. Copy example
- 2. Shallow copy
- 3. How to deep copy?
4. Implement deep and shallow copy by yourself
Free learning recommendation: javascript video tutorial
1. Copy example
When we operate the data, we may encounter the following situation:
- A set of data will be changed frequently, but the original data may be used
- I need two sets of the same data, but I don’t want to change one and the other will change
- I It is necessary to compare the data before and after the operation
- …
When we encounter similar need scenarios, the first thing that comes to mind is to copy it, but we don’t know that copying also has a lot of knowledge~
Does the following simple example sound familiar to you?
1.1 Basic type copy example
var str = 'How are you';var newStr = str;newStr = 10console.log(str); // How are youconsole.log(newStr); // 10
As everyone can imagine, string is a basic type, and its value is stored in the stack. When copying it, it is actually opening up new variables. new space. str
and newStr
are like two identical rooms, with the same layout but no connection.
1.2 Reference type copy example
var data = [1, 2, 3, 4, 5];var newData = data;newData[0] = 100;console.log(data[0]); // 100console.log(newData[0]); // 100
Similar code segment, but this time we use the reference type of array as an example. You will find that after modifying the assigned data, the original data has also changed. This obviously doesn't meet our needs. This article will talk about the knowledge of quoting data copy.
If you have questions about the data types of Js, you might as well take a look at "Basic Data Types in JavaScript"
2. Shallow copy
The division of copies is discussed based on reference types. Shallow copy - as the name suggests, shallow copy is a "shallow copy". In fact, it only does superficial work:
var arr = [1, 2, 3, 4];var newArr = arr;console.log(arr, newArr); // [1,2,3,4] [1,2,3,4]newArr[0] = 100;console.log(arr, newArr) // [100,2,3,4] [100,2,3,4]
Fortunately, nothing happens (operation). Once the new array is operated on, the data stored in both variables will change.
The reason why this kind of situation occurs is also because of the basic characteristics of reference type
:
- The value stored in the variable is a pointer (point), pointing to the storage The memory address of the object. Assigning a value to a new variable is equivalent to assigning a new key, and the room has not been changed.
Both slice and concat in the array will return a new array. Let’s try it together:
var arr = [1,2,3,4];var res = arr.slice();// 或者res = arr.concat()res[0] = 100;console.log(arr); // [1,2,3,4]
Is this problem solved so quickly? Although this layer of data is processed in this way, the problem is indeed solved, but!
var arr = [ { age: 23 }, [1,2,3,4] ];var newArr = arr.concat();arr[0].age = 18;arr[1][0] = 100;console.log(arr) // [ {age: 18}, [100,2,3,4] ]console.log(newArr) // [ {age: 18}, [100,2,3,4] ]
Sure enough, things are not that simple, this is also because of the different data types.
S We are not allowed to directly operate the address in the memory, which means that we cannot operate the memory space of the object. Therefore, our operations on the object are only operating on its reference.
Since shallow copy
cannot meet our requirements, based on the principle of efficiency, we are looking to see if there is anyone who can help us achieve deep copy
Methods.
#3. How to deep copy?
The data method failed, is there any other way? We need to achieve a true copy of independent data.
3.1 JSON
Here we use two methods of JSON, JSON.stringify()
, JSON.parse()
to achieve the most concise Deep copy
var arr = ['str', 1, true, [1, 2], {age: 23}]var newArr = JSON.parse( JSON.stringify(arr) );newArr[3][0] = 100;console.log(arr); // ['str', 1, true, [1, 2], {age: 23}]console.log(newArr); // ['str', 1, true, [100, 2], {age: 23}]
This method should be the simplest way to implement deep copy, but it still has problems, let’s take a look at what we just did:
- Define an array containing all types
arr
- JSON.stringify(arr), convert a JavaScript object or value into a
JSON string
- JSON.parse(xxx), method is used to parse JSON strings and construct
values or objects described by strings
Understand :
We can understand that the original data is converted into new string
, and then restored to a new object# through
new string ##, the method of changing the data type indirectly bypasses the process of copying the object reference, and does not affect the original data.
Restrictions:
The fundamental purpose of this method is to ensure the integrity of the data during "transfer", andJSON.stringify() There are also flaws in converting values to the corresponding
JSON format:
- undefined、任意的函数以及 symbol 值,在序列化过程中会被忽略(出现在非数组对象的属性值中时)或者被转换成 null(出现在数组中时)。
- 函数、undefined 被单独转换时,会返回 undefined,
- 如JSON.stringify(function(){})
- JSON.stringify(undefined)
- 对包含循环引用的对象(对象之间相互引用,形成无限循环)执行此方法,会抛出错误。
- NaN 和 Infinity 格式的数值及 null 都会被当做 null。
- 其他类型的对象,包括 Map/Set/WeakMap/WeakSet,仅会序列化可枚举的属性。
所以当我们拷贝函数、undefined等stringify
转换有问题的数据时,就会出错,我们在实际开发中也要结合实际情况使用。
举一反三:
既然是通过改变数据类型来绕过拷贝引用这一过程,那么单纯的数组深拷贝是不是可以通过现有的几个API来实现呢?
var arr = [1,2,3];var newArr = arr.toString().split(',').map(item => Number(item))newArr[0] = 100;console.log(arr); // [1,2,3]console.log(newArr); // [100,2,3]
注意,此时仅能对包含纯数字的数组进行深拷贝,因为:
- toString无法正确的处理对象和函数
- Number无法处理 false、undefined等数据类型
但我愿称它为纯数字数组深拷贝!
3.2 Object.assign()
有的人会认为Object.assign()
,可以做到深拷贝,我们来看一下
var obj = {a: 1, b: { c: 2 } }var newObj = Object.assign({}, obj)newObj.a = 100;newObj.b.c = 200;console.log(obj); // {a: 1, b: { c: 200 } }console.log(newObj) // {a: 100, b: { c: 200 } }
神奇,第一层属性没有改变,但第二层却同步改变了,这是为什么呢?
因为 Object.assign()拷贝的是(可枚举)属性值。
假如源值是一个对象的引用,它仅仅会复制其引用值。MDN传送门
四、自己实现深浅拷贝
既然现有的方法无法实现深拷贝,不妨我们自己来实现一个吧~
4.1 浅拷贝
我们只需要将所有属性即其嵌套属性原封不动的复制给新变量一份即可,抛开现有的方法,我们应该怎么做呢?
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;}
我们只需要将所有属性的引用拷贝一份即可~
4.2 深拷贝
相信大家在实现深拷贝的时候都会想到递归,同样是判断属性值,但如果当前类型为object
则证明需要继续递归,直到最后
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;}
我们用白话来解释一下deepCopy
都做了什么
const obj = [1, { a: 1, b: { name: '余光'} } ];const resObj = deepCopy(obj);
- 读取
obj
,创建 第一个newObj- 判断类型为
[]
- key为
0
(for in
以任意顺序遍历,我们假定按正常循序遍历) - 判断不是引用类型,直接复制
- key为
1
- 判断是引用类型
- 进入递归,重新走了一遍刚才的流程,只不过读取的是
obj[1]
- 判断类型为
另外请注意递归的方式虽然可以深拷贝,但是在性能上肯定不如浅拷贝,大家还是需要结合实际情况来选择。
写在最后
前端专项进阶系列的第五篇文章
,希望它能对大家有所帮助,如果大家有什么建议,可以在评论区留言,能帮到自己和大家就是我最大的动力!
相关免费学习推荐:javascript(视频)
The above is the detailed content of JavaScript Topic 5: Deep and Shallow Copy. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics



How to use WebSocket and JavaScript to implement an online speech recognition system Introduction: With the continuous development of technology, speech recognition technology has become an important part of the field of artificial intelligence. The online speech recognition system based on WebSocket and JavaScript has the characteristics of low latency, real-time and cross-platform, and has become a widely used solution. This article will introduce how to use WebSocket and JavaScript to implement an online speech recognition system.

WebSocket and JavaScript: Key technologies for realizing real-time monitoring systems Introduction: With the rapid development of Internet technology, real-time monitoring systems have been widely used in various fields. One of the key technologies to achieve real-time monitoring is the combination of WebSocket and JavaScript. This article will introduce the application of WebSocket and JavaScript in real-time monitoring systems, give code examples, and explain their implementation principles in detail. 1. WebSocket technology

Introduction to how to use JavaScript and WebSocket to implement a real-time online ordering system: With the popularity of the Internet and the advancement of technology, more and more restaurants have begun to provide online ordering services. In order to implement a real-time online ordering system, we can use JavaScript and WebSocket technology. WebSocket is a full-duplex communication protocol based on the TCP protocol, which can realize real-time two-way communication between the client and the server. In the real-time online ordering system, when the user selects dishes and places an order

How to use WebSocket and JavaScript to implement an online reservation system. In today's digital era, more and more businesses and services need to provide online reservation functions. It is crucial to implement an efficient and real-time online reservation system. This article will introduce how to use WebSocket and JavaScript to implement an online reservation system, and provide specific code examples. 1. What is WebSocket? WebSocket is a full-duplex method on a single TCP connection.

JavaScript and WebSocket: Building an efficient real-time weather forecast system Introduction: Today, the accuracy of weather forecasts is of great significance to daily life and decision-making. As technology develops, we can provide more accurate and reliable weather forecasts by obtaining weather data in real time. In this article, we will learn how to use JavaScript and WebSocket technology to build an efficient real-time weather forecast system. This article will demonstrate the implementation process through specific code examples. We

JavaScript tutorial: How to get HTTP status code, specific code examples are required. Preface: In web development, data interaction with the server is often involved. When communicating with the server, we often need to obtain the returned HTTP status code to determine whether the operation is successful, and perform corresponding processing based on different status codes. This article will teach you how to use JavaScript to obtain HTTP status codes and provide some practical code examples. Using XMLHttpRequest

Usage: In JavaScript, the insertBefore() method is used to insert a new node in the DOM tree. This method requires two parameters: the new node to be inserted and the reference node (that is, the node where the new node will be inserted).

JavaScript is a programming language widely used in web development, while WebSocket is a network protocol used for real-time communication. Combining the powerful functions of the two, we can create an efficient real-time image processing system. This article will introduce how to implement this system using JavaScript and WebSocket, and provide specific code examples. First, we need to clarify the requirements and goals of the real-time image processing system. Suppose we have a camera device that can collect real-time image data
