This is the 11th day of my participation in the August Wenwen Challenge.More challenges in August

Basic types of

There are seven basic data types: Number, String, Boolean, Null, Undefined, Symbol (ES6), BigInt (ES10). Variables are stored on the stack according to their values. Assign values directly with =.

Reference types

There is one reference data type: Object. Variable memory addresses are stored on the stack, values are stored in the heap, and assignment of reference types is closely related to shallow and deep copies discussed below.

Shallow copy

First declare shallow copy ≠ assignment.

Assignment = assigns the memory address of the object. Two objects refer to the same storage space in the heap and affect each other.

let obj1 = {
  name: 'jin line'.list: ['JS'.'CSS'.'HTML']}let obj2 = obj1
obj2.name = 'seven gold'
obj2.list[0] = 'Java'
// {list: ['Java', 'CSS', 'HTML']}
// {list: ['Java', 'CSS', 'HTML']}
Copy the code

Shallow copy creates a new memory space in the heap. After the copy, the basic data types of objects do not affect each other, but the reference types still share the same storage space and affect each other.

function shallowClone (obj1) {
  let obj2 = {}
  for (let i in obj1) { 
    obj2[i] = obj1[i] 
  } 
  return obj2;
}
let obj1 = {
  name: 'jin line'.list: ['JS'.'CSS'.'HTML']}let obj2 = shallowClone(obj1)
obj2.name = 'seven gold'
obj2.list[0] = 'Java'
console.log(obj1, obj2)
// {list: ['Java', 'CSS', 'HTML']}
// {list: ['Java', 'CSS', 'HTML']}
Copy the code

Array

Collate array shallow copy related API.

Extended operator

let arr1 = [1[2].3]
let arr2 = [...arr1]
arr2[0] = 4
arr2[1].push(5)
console.log(arr1, arr2) / / [1, 2, 5), 3] [4, (2, 5), 3]
Copy the code

Array.prototype.slice

let arr1 = [1[2].3]
let arr2 = arr1.slice()
arr2[0] = 4
arr2[1].push(5)
console.log(arr1, arr2) / / [1, 2, 5), 3] [4, (2, 5), 3]
Copy the code

Array.prototype.concat

let arr1 = [1[2].3]
let arr2 = arr1.concat([])
arr2[0] = 4
arr2[1].push(5)
console.log(arr1, arr2) / / [1, 2, 5), 3] [4, (2, 5), 3]
Copy the code

Array.from

Creates a new shallow-copy array instance of a class array or iterable.

let arr1 = [1[2].3]
let arr2 = Array.from(arr1)
arr2[0] = 4
arr2[1].push(5)
console.log(arr1, arr2) / / [1, 2, 5), 3] [4, (2, 5), 3]
Copy the code

Array.prototype.map

let arr1 = [1[2].3]
let arr2 = arr1.map(item= > item)
arr2[0] = 4
arr2[1].push(5)
console.log(arr1, arr2) / / [1, 2, 5), 3] [4, (2, 5), 3]
Copy the code

Array.prototype.filter

let arr1 = [1[2].3]
let arr2 = arr1.filter(item= > item)
arr2[0] = 4
arr2[1].push(5)
console.log(arr1, arr2) / / [1, 2, 5), 3] [4, (2, 5), 3]
Copy the code

Array.prototype.reduce

Reduce here may be a little bit of a cheat 🤣, does not really reflect its value, can be regarded as providing a novel idea.

let arr = [1[2].3]
let arr2 = arr.reduce((arr1,item) = > {
  arr1.push(item)
  return arr1
}, [])
arr2[0] = 4
arr2[1].push(5)
console.log(arr, arr2) / / [1, 2, 5), 3] [4, (2, 5), 3]
Copy the code

Object

Collate the API related to object shallow copy.

Extended operator

let obj1 = {
  name: 'jin line'.list: ['JS'.'CSS'.'HTML']}letobj2 = {... obj1} obj2.name ='seven gold'
obj2.list[0] = 'Java'
console.log(obj1, obj2) 
// {list: ['Java', 'CSS', 'HTML']}
// {list: ['Java', 'CSS', 'HTML']}
Copy the code

Object.assign

let obj1 = {
  name: 'jin line'.list: ['JS'.'CSS'.'HTML']}let obj2 = Object.assign({}, obj1)
obj2.name = 'seven gold'
obj2.list[0] = 'Java'
console.log(obj1, obj2) 
// {list: ['Java', 'CSS', 'HTML']}
// {list: ['Java', 'CSS', 'HTML']}
Copy the code

Deep copy

Heap memory is recreated to hold new objects, the two objects do not affect each other.

Array

serialization

Json.stringify converts the array to a JSON string, and json.parse converts the string to a new array.

let arr1 = [1[2].3]
let arr2 = JSON.parse(JSON.stringify(arr1))
arr2[0] = 4
arr2[1].push(5)
console.log(arr1, arr2) / / [[2] 1, 3] [4, (2, 5), 3]
Copy the code

Object

serialization

Json.stringify converts the object to a JSON string, and json.parse converts the string to a new object, but this method has drawbacks.

let obj1 = {
  name: 'jin line'.list: ['JS'.'CSS'.'HTML']}let obj2 = JSON.parse(JSON.stringify(obj1))
obj2.name = 'seven gold'
obj2.list[0] = 'Java'
console.log(obj1, obj2)
// {list: ['JS', 'CSS', 'HTML']}
// {list: ['Java', 'CSS', 'HTML']}
Copy the code

There doesn’t seem to be any problems, and there’s no need to introduce the LoDash library. So, now add a method to the object to see ~

let obj1 = {
  name: 'jin line'.list: ['JS'.'CSS'.'HTML'].work: function() {}}let obj2 = JSON.parse(JSON.stringify(obj1))
console.log(obj1, obj2)
/ / {name: jin line, list: [' JS ', 'CSS', 'HTML'], the work: the function () {}}
// {list: ['JS', 'CSS', 'HTML']}
Copy the code

Method lost after json.stringify… There is always a solution to everything, but when it comes to the lodash library.

What I did was turn the Function into a string to make sure it wasn’t lost again, and finally use new Function() to turn the string into a Function.

let obj1 = {
  name: 'jin line'.list: ['JS'.'CSS'.'HTML'].work: function() {},}for(let i in obj1) {
  if(typeof obj1[i] === 'function') {
    obj1[i] = obj1[i].toString()
  }  
}
let obj2 = JSON.parse(JSON.stringify(obj1))
for(let i in obj2) {
  if(typeof obj2[i] === 'string' && obj2[i].indexOf('function') = = =0) {
    obj2[i] = new Function('return ' + obj2[i])
  }   
}
console.log(obj1, obj2)
/ / {name: jin line, list: [' JS ', 'CSS', 'HTML'], the work: the function () {}}
/ / {name: jin line, list: [' JS ', 'CSS', 'HTML'], the work: the function () {}}
Copy the code

Of course, this method is not perfect. If I do have a field of type string and the value is function, that would be a coincidence.

This phenomenon made me curious about json.stringify. What other types of data are lost? Enumerates the write attributes…

let obj1 = {
  name: 'jin line'.list: ['JS'.'CSS'.'HTML'].work: function() {},
  date: new Date(),
  reg: new RegExp(),
  symbol: Symbol(),
  number: NaN.address: Infinity.age: undefined
}
console.log(JSON.stringify(obj1))
 
/ / {
// "name":" name",
// "list":["JS","CSS","HTML"],
/ / "date" : "the 2021-08-28 T11: they. 545 z",
// "reg":{},
// "number":null,
// "address":null
/ /}
Copy the code

The discovery is really deep pit 🤦♀️

  1. The function,Symbol,undefinedThe loss of
  2. NaN,Infinitychangenullthe
  3. RegExpThe object variable{}
  4. DateObject to string

Continue to look for json.stringify trolled articles on the web and beware of the following

  1. Methods withtoJSON, returns the function directlyreturnvalue
let obj1 = {
  name: 'jin line'.toJSON: function() {
    return 'jin line'}}console.log(JSON.stringify(obj1)) / / jin
Copy the code
  1. Property references itself, and an error is reported
let obj1 = {
  name: 'jin line'.copy: obj1
}
console.log(JSON.stringify(obj1)) 
Copy the code

  1. Non-enumerable attributes exist and are also lost
let obj1 = {
  name:  'jin line'
}
Object.defineProperty(obj1, 'name', {
  enumerable: false
})
console.log(JSON.stringify(obj1)) / / {}
Copy the code

Some of these cases can also be converted to string first, and then back to the original attribute type, which is a kind of idea, but in the case of the value of the object is known, otherwise it is better to use the mature cloneDeep in LoDash.

Deep copy is so complicated that you can study the source code of cloneDeep in Lodash after preparation. Try writing it by hand and make a draft first. If you feel helpful, welcome to like + follow + collect 🧡, exchange learning