JavaScript의 심층 복제본 상세 분석

JS의 깊이 복사를 말하기 전에 우리는 JS의 데이터 유형에 대해 알아야 한다. 기본 데이터 유형과 인용 데이터 유형으로 나뉘는데 기본 데이터 유형에 대해 깊이 복사가 없다는 말은 주로 인용 데이터 유형을 대상으로 한다.
1. 얕은 복사
얕은 복사본은 인용만 복사하고 복사 값은 없습니다.JS에서 가장 간단한 간단한 간단한 복사본은 "="부호 조작부호를 이용하여 실현하는 것이다.

var obj1 = {
  a:1,
  b:[2,3,4],
  c:{name:'tanj'},
  fun:function(){
    console.log('fun')
  }
}
var obj2 = obj1
obj2.a = 666 /*  obj2 ,obj1  */
console.log(obj1) /* {a: 666, b: Array(3), c: {…}, fun: ƒ} */
상기 코드에서 우리는obj2의 값을 수정했고obj1의 값도 이에 따라 바뀌었다. 사용 = "얕은 복사만 실현했다."
2. 딥 카피
딥 복제본은 대상에 대한 완전 복제본으로 딥 복제본이 실행된 후의 두 값은 서로 영향을 주지 않는다.
1. JSON을 이용한다.stringify와 JSON.parse 방법
JSON.stringify는 JavaScript 값을 JSON 문자열로 변환합니다.
JSON.parse는 JSON 문자열을 JavaScript 값으로 변환합니다.

var obj1 = {
  a:1,
  b:[2,3,4],
  c:{name:'tanj'},
}			
var obj2 = JSON.parse(JSON.stringify(obj1))
obj2.a = 12
console.log(obj1) /* {a: 1, b: Array(3), c: {…}} */
obj2의 값을 수정하는 것은 obj1의 속성 값에 영향을 주지 않습니다. 분명히 우리는 JSON을 이용합니다.parse와 JSON.stringify는 깊은 복사를 실현했다.
하지만 정말 이렇게 간단하게 실현할 수 있을까?우리 아래의 예를 봅시다!

var obj1 = {
  a:1,
  b:[2,3,4],
  c:{name:'tanj'},
  fun:function(){
    console.log('fun')
  }
}			
var obj2 = JSON.parse(JSON.stringify(obj1))
obj2.a = 12
console.log(obj1) /* {a: 1, b: Array(3), c: {…}, fun: ƒ} */
console.log(obj2) /* {a: 12, b: Array(3), c: {…}} */
변환된 obj2에 fun이라는 속성이 없습니다. 이것은 JSON을 이용하기 때문입니다.stringify 변환 과정에서 undefined,function,symbol을 무시했습니다.분명히 우리의 대상에 이러한 유형의 속성이 나타날 때 이 방법을 이용하여 깊은 복사를 할 수 없다.
2. 귀속

function deepClone(source){
  if(!isObject(source)) return source
  var newObj = source instanceof Array? []:{}
  for(let key in source){
	if(source.hasOwnProperty(key)){
	  newObj[key] = isObject(source[key])?deepClone(source[key]):source[key]
    }
  }
  return newObj
}
function isObject(x) {
  return typeof x === 'object' && x != null
}
위의 방법을 테스트해 보십시오.

var obj1 = {
  a:1,
  b:[2,3,4],
  c:{name:'tanj'},
  fun:function(){
	console.log('fun')
  }
}			
var obj2 = deepClone(obj1)
obj2.a = 12
console.log(obj1) /* {a: 1, b: Array(3), c: {…}, fun: ƒ} */
예를 통해 알 수 있듯이 우리는obj2의 a 속성 값을 수정했지만 obj1의 a 속성 값에 영향을 주지 않았다.귀속을 통해 우리는 깊은 복사를 실현할 수 있다!
주의: 상술한 방법은 순환 인용 문제를 해결하지 못했다.

var obj1 = {}
obj1.a = obj1
var obj2 = deepClone(obj1) /*  ,  */
console.log(obj2)
순환 인용 문제를 해결하고 Symbol 형식의 복사를 실현하는 방법에 관해서는 잠시 후에 보완하겠습니다.
3. 기타 복제 방법
1. 그룹의 concat () 및 slice () 방법
우리는 그룹 중 두 가지 방법인concat과slice가 복제 그룹을 완성하고 새 그룹으로 되돌아갈 수 있다는 것을 알고 있다.concat을 예로 들다.

var arr = [1,2,3]
var arr2 = arr.concat()
arr2[2]=4
console.log(arr) /* [1, 2, 3] */
console.log(arr2) /* [1, 2, 4] */
arr2의 값을 바꾸면 arr의 값에 영향을 주지 않는다. 이것은 수조의 깊은 복사를 실현한 것인가. 먼저 결론을 서둘러 내리지 않고 아래의 예를 보고 분석한다.

var arr = [1,2,3,[4,5,6],{a:7}]
var arr2 = arr.concat()
arr2[3] = 444
arr2[4].a=8
console.log(arr) /* [1,2,3,[4,5,6],{a:8}] */
console.log(arr2) /* [1,2,3,444,{a:8}] */
우리는 arr2[3]를 직접 수정했지만 arr의 변화를 일으키지는 않았지만, 우리는 arr2[4]를 수정했다.a시,arr의 상응하는 원소가 함께 바뀌었다.사실 우리는arr2수조의 원소를 직접 변화(예를 들어arr2[0]=***,arr2[1]=***,arr2[3]=***)할 때 원수조arr에 영향을 주지 않지만 우리가 수조의 [3,4,5] 또는 {a:7}를 수정할 때 원수조arr의 변화를 초래할 수 있다.
결론:concat () 방법은 수조 1층을 깊이 복사했다.
수조의 슬라이스 () 방법을 다시 시도해 볼 수 있으며, 수조의 1층만 깊이 복사했다.
2. Object.assign () 및...확장 연산자

var obj1 = {
  a:1,
  b:[2,3,4],
  c:{name:'tanj'}
}
var obj2 = {...obj1}
obj2.a = 666
obj2.c.name = 'xinxin'
console.log(obj1) /* {a:1,b:[2,3,4],c:{name:'xinxin'}} */
보시면 이용...전개 연산자는 대상의 첫 번째 층의 깊은 복사를 실현한다.뒤에 있는 것은 복사된 인용 값일 뿐이다.
Object를 사용해 보세요.assign () 메서드:

var obj1 = {
  a:1,
  b:[2,3,4],
  c:{name:'tanj'}
}
var obj2 = {}
Object.assign(obj2,obj1)
obj2.a = 666
obj2.b[0] = 0
console.log(obj1) /* {a:1,b:[0,3,4],c:{name:'tanj'} */
마찬가지로 대상의 첫 번째 층만 깊이 복사했다. 만약에 원본 대상의 속성 값(예를 들어obj1)이 대상을 가리키는 인용이라면obj2도 그 인용 값만 복사한다.그래서obj2에서 b가 가리키는 그 그룹을 바꾸면obj1의 값도 바뀐다.
계층 1에 대해서만 심층 복제할 수 있습니다.

function shallowClone(source) {
  const newObj = source.constructor === Array ? [] : {}
  for (let keys in source) {
    if (source.hasOwnProperty(keys)) {
	  newObj[keys] = source[keys]
	}
  }
  return newObj
}
다음은 JavaScript의 얕은 복사본에 대한 상세한 내용을 분석하고 JavaScript의 얕은 복사본에 대한 더 많은 자료를 보시기 바랍니다.

좋은 웹페이지 즐겨찾기