We know that js has several basic data types and other complex data types including (objects, arrays, functions). The assignment of basic data types is actually a copy of the value. We call it value transfer, and the variable after assignment There is no other relationship with the original variable except that the value is equal.
let x = 666 let y = x let m = 'abc' let n = m y = 888 n = 'def' console.log(x, y)//666,888 console.log(m, n)//'abc','def'
The transfer of complex data types is not like this, because when a variable is bound to a complex data type, what is recorded is not the value of the complex data, but an address where the data is stored. Information, when assigning this variable to another variable, only the address is passed. These two variables actually point to a data information. When any variable is changed, the other variables will be affected. This kind of transfer The method is called pass by reference
let obj1 = { a : '1', b : 2 } let obj2 = obj1 obj2.b = 3 console.log(obj1,obj2)//{a: "1", b: 3},{a: "1", b: 3}
We know that the assignment of complex data types is pass by reference. The variables before and after the assignment will affect each other. In actual projects, we often do not want this to happen. , for example:
We use data (an Array) in two places in a view. One is that a list only needs to display the data in order, and the other is that a chart needs to display the data in reverse order. When doing data processing, we will have a problem at this time. If the first list after data.reverse() is also in reverse order, this is not what we want. We need a method to only copy the values of the array, and this new array The data address of the original array is different. This copy method is called a copy of the array.
let obj1 = {a:1, b:{c:2}} let shallowCopy = (src)=> { let dst = {} for (let prop in src) { if (src.hasOwnProperty(prop)) { dst[prop] = src[prop] } } return dst } let obj2 = shallowCopy(obj1) console.log(obj1,obj2) //@1 obj1.a = 6 console.log(obj2.a) //@2 obj2.b.c = 666 console.log(obj1.b.c) //@3 obj2.b = { c: 888 } console.log(obj1.b.c) //@4
It can be seen from the above example that the first layer attribute of obj1 is a copy of the attribute value, and there is no copy of the inherited address, but the second layer is that the b attribute does share a memory address. This is a shallow copy, but At @4, obj1 has not been affected by obj2 because attribute b is an object. This kind of reassignment by reference transfer will cause the computer to reallocate a new memory to store data and record address information, so at this time obj1. b.c and obj2.b.c are no longer an attribute value of the record
It can also be understood as: copying is for transfer. Direct assignment of complex data types is transfer by reference and cannot be called copying. Copying is For a simple data backup of the original data, the memory address information of the data is not exactly the same. This is because the copy is also divided into shallow copy and deep copy.
The non-nested copy of complex data types means that only the first layer of data information is copied, which is a shallow copy. If the first layer of data has complex data types, the reference passing method is still used. , what is copied is still the address information, and the multi-layer nested copy of array objects etc. implemented through other methods is a deep copy.
Let’s take a look at how arrays and objects implement deep and shallow copies:
slice method
let arr1 = [1,2,[3,4]] let arr2 = arr1.slice(0) arr2[2].push(5) arr2.push(6) console.log(arr1,arr2)
concat method
let arr1 = [1,2,[3,4]] let arr2 = arr1.concat() arr2[2].push(5) arr2.push(6) console.log(arr1,arr2)
for loop
let arr1 = [1,2,[3,4]] let arr2 = [] for(let i = 0; i<arr1.length; i++){ arr2.push(arr1[i]) } arr2[2].push(5) arr2.push(6) console.log(arr1,arr2)
…Operator
let arr1 = [1,2,[3,4]] let [...arr2] = arr1 arr2[2].push(5) arr2.push(6) console.log(arr1,arr2)
The copies of the above four types of arrays are all shallow copies. To realize the deep copy of the array, it must be implemented recursively
let deepClone = (src)=> { let result (src instanceof Array) ? (result = []) :(result = {}) for (let key in src) { result[key] = (typeof src[key] === 'object') ? deepClone(src[key]) : src[key]//数组和对象的type都是object } return result } let arr1 = [1,2,[3,4]] let arr2 = deepClone(arr1) arr2[2].push(5) arr2.push(6) console.log(arr1,arr2)
It can be found that the methods arr1[2] and arr2[2] are different, the same as above The deep copy method is also applicable to the copy of the object
Universal for loop
let obj1 = {a:1,b:{c:2}} let obj2 = {} for(let key in obj1){ obj2[key] = obj1[key] } obj1.b.c = 6 console.log(obj1,obj2)
...operator
let obj1 = {a:1,b:{c:2}} let {...obj2} = obj1 obj1.b.c = 6 console.log(obj1,obj2)
Object.assign()
let obj1 = {a:1,b:{c:2}} let obj2 = Object.assign({},obj1) obj1.b.c = 6 console.log(obj1,obj2)
The above three methods are shallow copies of objects, and we will introduce two types of deep copies of objects. Method:
Convert to string and then back to object
let obj1 = {a:1,b:{c:2}} let obj2 = JSON.parse(JSON.stringify(obj1)) obj1.b.c = 6 console.log(obj1,obj2)
deepClone method is the deepClone method of the above array
Pure function
Given an input to a function, it returns a unique output and does not have any impact on the external environment. We call it a pure function. The variables defined within it will be recycled by the garbage collection mechanism after the function returns.
But if the parameter of the function is an array, object or function, a reference is passed in, and the operation will affect the original data. The function written in this way will have incidental effects, making it readable Sexuality becomes low.
The way to reduce the impact is to make a deep copy of the incoming parameters and assign them to a new variable, so that the original parameters are tampered with.
Let’s look at an example of a pure function:
let pureFunc = (animal)=> { let newAnimal = JSON.parse(JSON.stringify(animal)) newAnimal.type = 'cat' newAnimal.name = 'Miao' return newAnimal } let wang = { type: 'dog', name: 'Wang' } let miao = pureFunc(wang) console.log(wang,miao)
Through the above example, we can see that the value of wang has not been changed by the pure function.
Let’s think about the following example again. If you answer it correctly, it means you have a deep understanding of what this article talks about (remind everyone—>Reassignment of references)
let afterChange = (obj)=>{ obj.a = 6 obj = { a: 8, b: 9 } return obj } let objIns = { a: 1, b: 2 } let objIns2 = afterChange(objIns) console.log(objIns, objIns2)
The above is my understanding of the reference and transmission of js. Please forgive me if there is any inappropriateness. Thanks!
You can also read some other articles to deepen your understanding. I recommend this Explaining Value vs. Reference in Javascript.
Related recommendations:
Passing parameters by value for js functions
JavaScript parameter passing illustration tutorial
A brief analysis of json transmission in php and js
The above is the detailed content of Detailed explanation of js transfer and copy. For more information, please follow other related articles on the PHP Chinese website!