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.sliceslice()방법 은 새로운 배열 대상 을 되 돌려 줍 니 다.이 대상 은 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 변수 저장 깊이 복사 와 얕 은 복사 에 관 한 자 료 는 다른 관련 글 을 주목 하 십시오!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
JS 판단 수조 네 가지 실현 방법 상세그러면 본고는 주로 몇 가지 판단 방식과 방식 판단의 원리를 바탕으로 문제가 있는지 토론하고자 한다. 예를 들어 html에 여러 개의 iframe 대상이 있으면 instanceof의 검증 결과가 기대에 부합되지 않을...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.