In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-24 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >
Share
Shulou(Shulou.com)06/02 Report--
This article mainly introduces how to achieve deep copy, the article is very detailed, has a certain reference value, interested friends must read it!
There are three ways to implement deep copy: 1, to copy all hierarchical attributes recursively, 2, to use parse and stringify of JSON object, and 3, to borrow the extend method of JQ.
The three ways to implement deep copy are:
1. Copy all hierarchical attributes recursively
Function deepClone (obj) {let objClone = Array.isArray (obj)? []: {} If (obj & & typeof obj=== "object") {for (key in obj) {if (obj.hasOwnProperty (key)) {/ / determine whether the ojb child element is an object, and if so, recursively copy if (objkey] & & typeof obj [key] = "object") {objClone [key] = deepClone (objkey) } else {/ / if not, simply copy objClone [key] = obj [key];}} return objClone;} let a = [1, 2, 2, 3, 4], b=deepClone (a); a [0] = 2, console.log (a)
As previously thought, b is now out of the control of an and is no longer affected by a.
Here again, deep copy is to copy the attributes at all levels of the object, you can look at an example. There is an extend method in JQ that can also copy objects. Let's take a look.
Let a = [1, 2, 2, 3, 4], b=a.slice (); a [0] = 2, console.log (a, b)
Does that mean that the slice method is also deeply copied? after all, b is not affected by a. As mentioned above, deep copy copies attributes at all levels, or in this example, we change a.
Let a = [0JEI 1, [2jue 3], 4], b=a.slice (); a [0] = 1bot a [2] [0] = 1bot console.log (aPerm b)
The copy is not complete, the first-level attribute of the b object is indeed not affected, but the second-level attribute still failed to copy successfully, still can not be separated from the control of a, indicating that slice is not a real deep copy at all.
Here is a picture in Zhihu's question and answer.
It is true that the properties of the first layer are copied deeply and have independent memory, but the deeper attributes still share the address, which is why the above problem is caused.
Similarly, the same is true of the concat method and slice, which are not really deep copies, which need to be noted here.
two。 In addition to recursion, we can also borrow parse and stringify of the JSON object
Function deepClone (obj) {let _ obj = JSON.stringify (obj), objClone = JSON.parse (_ obj); return objClone} let a = [0L1, [2je 3], 4], b=deepClone (a); a [0] = 1th a [2] [0] = 1th console.log (ajol b)
As you can see, b is not affected by an at all.
Incidentally, JSON.stringify and JSON.parse, in addition to deep copy, can also be combined with localStorage to implement object array storage. If you are interested, you can read this article by the blogger.
LocalStorage storage array, object, localStorage,sessionStorage storage array object
3. In addition to the above two methods, we can also borrow JQ's extend method.
Extend ([deep], target, object1 [, objectN])
Deep indicates whether it is a deep copy. If it is true, it is a deep copy. If it is false, it is a shallow copy.
The target Object type target object to which the member properties of other objects are attached.
Object1 objectN is optional. The first and nth merged object of type Object.
Let a = [0jue 1, [2jue 3], 4], b=$.extend (true, [], a); a [0] = 1 a [2] [0] = 1 position console.log (afield b)
As you can see, the effect is the same as the above method, except that you rely on the JQ library.
Having said so much, understanding deep copy is not only to cope with the interview questions, but also very useful in actual development. For example, when a pile of data is returned from the backend, you need to manipulate this pile of data, but in the case of multi-person development, you cannot know whether other functions of this pile of data also need to be used. Direct modification may cause hidden problems. Deep copy can help you operate the data more safely and safely. This is probably what it means to use deep copy according to the actual situation.
4.lodash 's _ .cloneDeep ()
The following is a problem solving about deep copy that I see.
JSON.parse
First convert an object to a json object. Then parse the json object.
Let obj = {a: {bvl 22}}; let copy = JSON.parse (JSON.stringify (obj))
The advantage of this approach is that the code is relatively simple to write. But the shortcomings are also obvious. You first create a temporary, possibly large, string just to put it back into the parser. Another disadvantage is that this method cannot handle circular objects.
For example, the following loop object throws an exception when using this method
Let a = {}; let b = {a}; a.b = Bittlet copy = JSON.parse (JSON.stringify (a))
Built-in types such as Map, Set, RegExp, Date, ArrayBuffer, and other built-in types are lost during serialization.
Let a = {}; let b = new Set (); b.add (11); a.test = bterlet copy = JSON.parse (JSON.stringify (a))
The value of an is printed as follows
The value of copy is printed as follows
By comparison, it is found that Set has been lost.
Structured Clone structured cloning algorithm
MessageChannel
Establish two sides, one side sends the message, the other side receives the message.
Function structuralClone (obj) {return new Promise (resolve = > {const {port1, port2} = new MessageChannel (); port2.onmessage = ev = > resolve (ev.data); port1.postMessage (obj);})} const obj = / *... * /; structuralClone (obj) .then (res= > {console.log (res);})
The advantage of this approach is that it solves the problem of circular references and supports a large number of built-in data types. The disadvantage is that this method is asynchronous.
History API
Take advantage of history.replaceState. This api can change url without refresh when doing routing for single-page applications. This object uses structured cloning and is synchronized. But we need to be careful not to mess up the original routing logic on a single page. So when we clone an object, we need to restore the original state of the route.
Function structuralClone (obj) {const oldState = history.state; history.replaceState (obj, document.title); const copy = history.state; history.replaceState (oldState, document.title); return copy;} var obj = {}; var b = {obj}; obj.b = bvar copy = structuralClone (obj); console.log (copy)
The advantage of this method is. Can solve the problem of circular objects, but also support many built-in types of cloning. And it's synchronized. But the disadvantage is that some browsers have a limit on the frequency of calls. For example, Safari only allows 100 calls in 30 seconds.
Notification API
This api is mainly used for desktop notifications. If you use Facebook, you will find that there is always a pop-up window in the lower right corner of the browser, right this guy. We can also use this api to make a deep copy of the js object.
Function structuralClone (obj) {return new Notification (', {data: obj, silent: true}). Data;} var obj = {}; var b = {obj}; obj.b = bvar copy = structuralClone (obj); console.log (copy)
It also has both advantages and disadvantages, the advantage is that it can solve the problem of circular objects, but also supports many built-in types of clones, and is synchronous. The disadvantage is that the use of api requires permission from the user, but it can be used without user authorization when it is used here to clone data. In the case of the http protocol, you will be prompted to use it in the https scenario.
Lodash's _ .cloneDeep ()
Support for circular objects, and a large number of built-in types, handle a lot of details quite well. Recommended.
There are many types that are supported
Let's take a look again at how lodash solves the problem of circular application.
From the relevant code. We can find out. Lodash is recorded with a stack. All referenced values that are copied. If you encounter the same reference value again, you will not copy it again. Instead, it takes advantage of values that have been copied before.
Achieve a deep copy of a simple point, with the goal of solving the problem of circular references
We just make a deep copy that is a little easier. Can handle circular references gracefully. Before implementing a deep copy, let's review the methods of traversing the properties of objects in js and the pros and cons of various methods.
The method of traversing the properties of an object in js
Object.keys () only returns its own enumerable properties, excluding inherited, let alone Symbol properties
Object.getOwnPropertyNames () returns its own enumerable and non-enumerable properties. But does not include the Symbol attribute
Object.getOwnPropertySymbols () returns its own Symol property
For...in can traverse the object's own and inherited enumerable properties, without the Symbol property
Reflect.ownkeys () returns all the properties of the object itself, whether enumerable or Symbol or not. Note that inherited attributes are not included
Implement deep copy to solve the problem of circular reference
/ * determine whether it is a basic data type * @ param value * / function isPrimitive (value) {return (typeof value = 'string' | | typeof value =' number' | | typeof value = = 'symbol' | | typeof value =' boolean')} / * * determine whether it is a js object * @ param value * / function isObject (value) {return Object.prototype.toString.call (value) = = "[object Object]"} / * * * Deep copy a value * @ param value * / function cloneDeep (value) {/ / record the copied value Avoid circular references let memo = {} Function baseClone (value) {let res; / / if it is a basic data type, return if (isPrimitive (value)) {return value; / / if it is a reference data type, we copy a new value to replace the original value} else if (Array.isArray (value)) {res = [... value];} else if (isObject (value)) {res = {... value} } / / check whether the property value of the object we copied is a reference data type. If so, recursively copy Reflect.ownKeys (res) .forEach (key= > {if (typeof res [key] = "object" & & res [key]! = = null) {/ / here we use memo to record the reference addresses that have been copied. In order to solve the problem of circular reference, if (memo [key]) {res [key] = res [key];} else {memo [key] = res [key]; res [key] = baseClone (value)}) return res;} return baseClone (value)}
Verify whether the cloneDeep we wrote can solve the problem of circular application.
Var obj = {}; var b = {obj}; obj.b = bvar copy = cloneDeep (obj); console.log (copy); above is all the content of this article, thank you for reading! Hope to share the content to help you, more related knowledge, welcome to follow the industry information channel!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.