This article describes the copy and usage of JavaScript objects. Share it for your reference, as follows:
Deep and shallow copy
In JavaScript, for basic data types (undefined, null, boolean, number, string), the value of the variable itself is stored in the variable, and copying is the rightCopy of values, there is no theory of depth. However, among the common characteristics of C languages, the reference type (object) is stored, and in fact, its address is stored in the variable. Therefore, for complex data types (objects) in JavaScript, there will also be concepts of shallow copy and deep copy:A shallow copy refers to the address of two different variables that hold the same object, that is, two variables point to the same memory area; a deep copy refers to the real memory area to store the copied object, and the two variables store the real two variables that do not affect each other.
Some data believeShallow copy is to reallocate memory and copy each attribute in the original object in sequence without recursively copying the property value is an object, that is, only the outermost layer of the object is copied.. This article attributes this situation to the "intermediate situation between deep copy and shallow copy". In the article, it divides deep and shallow copy with "whether new memory is divided" as the boundary. This division method is consistent with C-based languages such as C/C++, C#, and Java.
Implementation of shallow copy in JavaScript
A shallow copy is simple in js, for example:
let objA = { name: 'Object A', content: 'I am A' }; let copyA = objA; (); // ==> "Object A"(); // ==> "Object A"
In this way, a shallow copyA of objA is obtained. Since it points to the same object, it also modifies objA and vice versa.
()
(target, …sources) The description of this method on MDN isCopy all enumerable attribute values from one or more source objects to the target object, String type and Symbol type attributes are copied, andThis method ignores source objects with values of or undefined. For example:
var o1 = { a: 1 }; var o2 = { [Symbol('foo')]: 2 }; var obj = ({}, o1, o2); (obj); // { a : 1, [Symbol("foo")]: 2 } (cf. bug 1207182 on Firefox) (obj); // [Symbol(foo)]
Deep and shallow copies of
Note that the enumerable attributes mentioned earlier are an enumerable attributes, which is a method between a complete deep copy and a complete shallow copy: if we set its first parameter target to an empty object {}, while ensuring that the attribute types in the remaining source object sources do not contain reference types, the return value of the method is another object that is the same as the source object but not in the same memory space, that is, a deep copy of the source object is obtained. However, if the property of the source object contains an object, that is, the value of this property points to an object, like this:
var obj = { name: 'obj name', content: { a: 1, b: 2 } };
Use({}, obj)
When the content property in the returned target object is the same memory area pointed to by the content property in the source object obj, that is, the content property under obj is performedLight copy. Therefore, for deep copy, you need to use other methods, such as implementing a deep copy yourself, or using((obj))
, because()
The copy is the attribute value.
Properties override
If the attributes in the target object have the same key, the attributes will be overwritten by the attributes in the source. The properties of later sources will similarly override the previous properties, so they can be used to merge objects (a common scenario is to use reducers to update the state of the React application).
var o1 = { a: 1, b: 1, c: 1 }; var o2 = { b: 2, c: 2 }; var o3 = { c: 3 }; var obj = ({}, o1, o2, o3); (obj); // { a: 1, b: 2, c: 3 }
About inherited and non-enumerable properties of objects
As mentioned earlier,The copy is the enumerable attribute of the object, which uses the source object's
[[Get]]
and the target object[[Set]]
, so it will call relatedgetter
andsetter
. So it's better to say that it's allocating attributes, not just copying or defining new attributes. If the merge source contains getters, this may make it unsuitable to merge new properties into the prototype, copying the property definition (including its enumeration) to the prototype should use()
and()
,thereforeThe inherited properties of an object cannot be copied, for example:
var obj = ({foo: 1}, { // foo is an inheritance attribute. bar: { value: 2 // bar is an unenumerable property. }, baz: { value: 3, enumerable: true // baz is an enumerable attribute. } }); var copy = ({}, obj); (copy); // { baz: 3 }
When the source object is the original data type
ECMAScript has 5 primitive types:Undefined
、Null
、Boolean
、Number
andString
. whenWhen the source object is a primitive type, the source object will be wrapped into an "object", and the corresponding key is its index value in the source object:
var v1 = "abc"; var v2 = true; var v3 = 10; var v4 = Symbol("foo") var obj = ({}, v1, null, v2, undefined, v3, v4); // The original type will be wrapped, null and undefined will be ignored.// Note that only the wrapper object of the string may have its own enumerable attributes.(obj); // { "0": "a", "1": "b", "2": "c" }
When an exception occurs during copying
In case of an error, for example, if the property is not writable, a TypeError will be raised and the exception will interrupt subsequent copy tasks. If any attributes are added before the error is thrown, you can change the target object.
var target = ({}, "foo", { value: 1, writable: false }); // The foo attribute of target is a read-only attribute.(target, {bar: 2}, {foo2: 3, foo: 3, foo3: 3}, {baz: 4}); // TypeError: "foo" is read-only // Note that this exception occurs when copying the second property of the second source object.(); // 2, indicating that the first source object has been copied successfully.(target.foo2); // 3, indicating that the first attribute of the second source object has also been copied successfully.(); // 1. The read-only attribute cannot be overwritten, so the second attribute copy of the second source object failed.(target.foo3); // undefined, after the exception, the assign method exits, and the third attribute will not be copied.(); // undefined, the third source object will not be copied.
For more information about JavaScript, readers who are interested in reading this site's special topic:JavaScript object-oriented tutorial》、《Summary of JavaScript Errors and Debugging Skills》、《Summary of JavaScript data structure and algorithm techniques》、《JavaScript traversal algorithm and skills summary"and"Summary of JavaScript mathematical operations usage》
I hope this article will be helpful to everyone's JavaScript programming.