JS 변수 저장 깊이 복사 와 얕 은 복사

변수 형식 과 저장 공간
창고 메모리 와 더미 메모리

기본 데이터 형식
string,number,null,undefined,boolean,symbol(ES6 추가)변수 값 을 스 택 메모리 에 저장 하고 변수의 값 에 직접 접근 하고 수정 할 수 있 습 니 다.
기본 데이터 형식 에는 복사 가 존재 하지 않 습 니 다.예 를 들 어 수치 1 의 값 을 수정 할 수 없습니다.
참조 형식
Object Function RegExp Math Date 값 을 대상 으로 메모리 에 저장
스 택 메모리 에 변 수 를 저장 하 는 것 은 포인터 로 메모리 에 대응 하 는 주 소 를 가리 키 는 것 입 니 다.
인용 형식 에 접근 할 때 스 택 에서 대상 의 주소 포인 터 를 꺼 낸 다음 메모리 에서 필요 한 데 이 터 를 가 져 와 야 합 니 다.
그래 픽 저장 공간

let a1 = 0; //    
let a2 = "this is string" //    
let a3 = null; //    
let b = { x: 10 }; //   b     ,{ x: 10 }         
let c = [1, 2, 3]; //   c     ,[1, 2, 3]         

인용 형식의 할당

let a = { x: 10, y: 20 }
let b = a;
b.x = 5;
console.log(a.x); // 5

딥 카피 와 얕 은 카피
딥 카피
대상 을 메모리 에서 완전 하 게 복사 하고 메모리 에서 새로운 영역 을 열 어 새 대상 을 저장 하 며 새 대상 을 수정 하면 원래 대상 에 영향 을 주지 않 습 니 다.
얕 은 복사
얕 은 복사 본 은 위치 에 따라 복사 대상 으로 새로운 대상 을 만 들 것 입 니 다.이 대상 은 원시 대상 속성 값 의 정확 한 복사 본 을 가지 고 있 습 니 다.속성 이 기본 유형 이 라면 기본 유형의 값 을 복사 합 니 다.속성 이 메모리 주소(참조 형식)라면 복사 한 것 은 메모리 주소 입 니 다.
대상 의 할당
우리 가 하나의 대상 을 새로운 변수 에 할당 할 때,부 여 된 것 은 사실 이 대상 의 창고 에 있 는 주소 이지,쌓 여 있 는 데이터 가 아니다.즉,두 대상 이 같은 저장 공간 을 가리 키 는데 어느 대상 이 바 뀌 든 사실은 변 경 된 저장 공간의 내용 이기 때문에 두 대상 은 연동 된다.
삼자 대비

얕 은 복사 에 자주 사용 되 는 다섯 가지 방법
Object.assign()
Object.assign()방법 은 여러 개의 소스 대상 자체 의 매 거 진 속성 을 대상 에 게 복사 한 다음 대상 으로 돌아 갈 수 있 습 니 다.하지만 Object.assign()은 얕 은 복사 가 진행 되 고 있 습 니 다.
Object.assign 은 원본 대상(sources)의 모든 속성 을 왼쪽 에서 오른쪽으로 옮 겨 다 니 며 대상(target)에=할당 합 니 다.

var obj = { a: {a: "kobe", b: 39},b:1 };
        var initalObj = Object.assign({}, obj);
        initalObj.a.a = "wade";
        initalObj.b = 2;
        console.log(obj.a.a); //wade
        console.log(obj.b); //1
확장 연산 자

let obj = {a:1,b:{c:1}}
let obj2 = {...obj};
obj.a=2;
console.log(obj); //{a:2,b:{c:1}}
console.log(obj2); //{a:1,b:{c:1}}

obj.b.c = 2;
console.log(obj); //{a:2,b:{c:2}}
console.log(obj2); //{a:1,b:{c:2}}
Array.prototype.slice
slice()방법 은 새로운 배열 대상 을 되 돌려 줍 니 다.이 대상 은 begin 과 end(end 포함 하지 않 음)가 결정 하 는 원래 배열 의 얕 은 복사 입 니 다.원본 배열 의 기본 형식 은 변 하지 않 고 인용 형식 은 변 합 니 다.

let arr = [1, 3, {
    username: ' kobe'
    }];
let arr3 = arr.slice();
arr3[0]=0;
arr3[2].username = 'wade'
console.log(arr);
Array.prototype.concat()

let arr = [1, 3, {
    username: 'kobe'
    }];
let arr2=arr.concat();   
arr3[0]=0;
arr2[2].username = 'wade';
console.log(arr);
핸드 카피

function shallowCopy(src) {
    var dst = {};
    for (var prop in src) {
        if (src.hasOwnProperty(prop)) {
            dst[prop] = src[prop];
        }
    }
    return dst;
}
딥 카피
jsON.parse(jsON.stringify())
JSON.stringify 를 통 해 딥 카 피 를 실현 하려 면 몇 가지 주의해 야 할 점 이 있 습 니 다.
복사 한 대상 의 값 에 함수 가 있 으 면 undefined,symbol 은 JSON.stringify()를 거 쳐 직렬 화 된 JSON 문자열 에서 이 키 쌍 이 사라 집 니 다.
셀 수 없 는 속성 을 복사 할 수 없습니다.대상 의 원형 체인 을 복사 할 수 없습니다.
Date 참조 형식 을 복사 하면 문자열 이 됩 니 다.
RegExp 참조 형식 을 복사 하면 빈 대상 이 됩 니 다.
대상 에 NaN,Infinity,-infinity 가 포함 되 어 있 으 면 직렬 화 된 결 과 는 null 이 됩 니 다.
대상 의 순환 응용 프로그램 을 복사 할 수 없습니다(즉,obj[key]=obj)

let arr = [1, 3, {
    username: ' kobe'
}];
let arr4 = JSON.parse(JSON.stringify(arr));
arr4[2].username = 'duncan'; 
console.log(arr, arr4)
손 으로 쓴 거지 판 딥 카피
우선 이 deepClone 함 수 는 셀 수 없 는 속성 과 Symbol 형식 을 복사 할 수 없습니다.
Object 참조 형식의 값 에 대한 순환 교체 일 뿐,Array,Date,RegExp,Error,Function 참조 형식 은 올 바 르 게 복사 할 수 없습니다.
대상 이 링 이 되 는 것,즉 순환 참조(예:obj 1.a=obj)

function clone(target) {
    if (typeof target === 'object') {
        let cloneTarget = Array.isArray(target) ? [] : {};
        for (const key in target) {
            cloneTarget[key] = clone(target[key]);
        }
        return cloneTarget;
    } else {
        return target;
    }
};
황제 판 딥 카피
이 인 스 턴 스 는 ConardLi 사내 의 github 에서 왔 습 니 다.원본 주소:https://github.com/ConardLi/

const mapTag = "[object Map]";
    const setTag = "[object Set]";
    const arrayTag = "[object Array]";
    const objectTag = "[object Object]";
    const argsTag = "[object Arguments]";

    const boolTag = "[object Boolean]";
    const dateTag = "[object Date]";
    const numberTag = "[object Number]";
    const stringTag = "[object String]";
    const symbolTag = "[object Symbol]";
    const errorTag = "[object Error]";
    const regexpTag = "[object RegExp]";
    const funcTag = "[object Function]";

    const deepTag = [mapTag, setTag, arrayTag, objectTag, argsTag];

    function forEach(array, iteratee) {
      let index = -1;
      const length = array.length;
      while (++index < length) {
        iteratee(array[index], index);
      }
      return array;
    }

    function isObject(target) {
      const type = typeof target;
      return target !== null && (type === "object" || type === "function");
    }

    function getType(target) {
      return Object.prototype.toString.call(target);
    }

    function getInit(target) {
      const Ctor = target.constructor;
      return new Ctor();
    }

    function cloneSymbol(targe) {
      return Object(Symbol.prototype.valueOf.call(targe));
    }

    function cloneReg(targe) {
      const reFlags = /\w*$/;
      const result = new targe.constructor(targe.source, reFlags.exec(targe));
      result.lastIndex = targe.lastIndex;
      return result;
    }

    function cloneFunction(func) {
      const bodyReg = /(?<={)(.|
)+(?=})/m; const paramReg = /(?<=\().+(?=\)\s+{)/; const funcString = func.toString(); if (func.prototype) { const param = paramReg.exec(funcString); const body = bodyReg.exec(funcString); if (body) { if (param) { const paramArr = param[0].split(","); return new Function(...paramArr, body[0]); } else { return new Function(body[0]); } } else { return null; } } else { return eval(funcString); } } function cloneOtherType(targe, type) { const Ctor = targe.constructor; switch (type) { case boolTag: case numberTag: case stringTag: case errorTag: case dateTag: return new Ctor(targe); case regexpTag: return cloneReg(targe); case symbolTag: return cloneSymbol(targe); case funcTag: return cloneFunction(targe); default: return null; } } function clone(target, map = new WeakMap()) { // if (!isObject(target)) { return target; } // const type = getType(target); let cloneTarget; if (deepTag.includes(type)) { cloneTarget = getInit(target, type); } else { return cloneOtherType(target, type); } // if (map.get(target)) { return map.get(target); } map.set(target, cloneTarget); // set if (type === setTag) { target.forEach(value => { cloneTarget.add(clone(value, map)); }); return cloneTarget; } // map if (type === mapTag) { target.forEach((value, key) => { cloneTarget.set(key, clone(value, map)); }); return cloneTarget; } // const keys = type === arrayTag ? undefined : Object.keys(target); forEach(keys || target, (value, key) => { if (keys) { key = value; } cloneTarget[key] = clone(target[key], map); }); return cloneTarget; } const map = new Map(); map.set("key", "value"); map.set("ConardLi", "code "); const set = new Set(); set.add("ConardLi"); set.add("code "); const target = { field1: 1, field2: undefined, field3: { child: "child" }, field4: [2, 4, 8], empty: null, map, set, bool: new Boolean(true), num: new Number(2), str: new String(2), symbol: Object(Symbol(1)), date: new Date(), reg: /\d+/, error: new Error(), func1: () => { console.log("code "); }, func2: function(a, b) { return a + b; } }; const result = clone(target); console.log(target); console.log(result);
이상 은 JS 변수 저장 깊이 복사 와 얕 은 복사 에 대한 상세 한 내용 입 니 다.JS 변수 저장 깊이 복사 와 얕 은 복사 에 관 한 자 료 는 다른 관련 글 을 주목 하 십시오!

좋은 웹페이지 즐겨찾기