일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- nodejs파일업로드
- css기초
- 아이디 중복체크기능
- express session
- javascript기초
- JWT 만들어보기
- 라우터와 미들웨어
- OAuth 카카오
- 라우트 매개변수
- express router
- ws 라이브러리
- JWT 하드코딩
- 시퀄라이즈 기본설정
- express.static
- cookie-parser 만들어보기
- 라우터 분리
- 비동기파일업로드
- 블록 만들기
- Uncaught Error: could not find react-redux context value; please ensure the component is wrapped in a <Provider>
- 라우터미들웨어 분리
- next 매개변수
- FormData()
- 세션으로 로그인 구현
- buffer.from
- JWT 로그인 기능 구현
- mysql wsl
- express실행
- node.js path
- useEffect clean up
- useContext
- Today
- Total
즐코
깊은 복사 vs 얕은 복사 / spread (...) ! 본문
1. 깊은 복사 vs. 얕은 복사
2. 얕은 복사 연습해보기
다시 떠올려보는 비교연산자
https://yjleekr.tistory.com/17
console.log({ } === { })
false가 출력된다. 왜냐하면 저번에 공부했던 object equality 에서 객체안에 같은 key:value값이 있어도
서로 다른 reference로 컴퓨터가 받아들이기 때문에 엄연히 따지면, 다른 아이들이다.
컴퓨터는 이 객체를 만들때마다 새로운 값으로 인식 및 저장한다.
하지만 그 객체 안의 값이 같다면, 그 속성값들 자체는 같은 데이터로 인식 및 저장한다.
1. 깊은 복사 vs 얕은 복사
깊은 복사 deep copy | 얕은 복사 shallow copy |
깊은 복사가 되는 데이터 원시 타입 (primitive type) 데이터 = number, string, boolean 등 |
얇은 복사가 되는 데이터 객체, 참조타입 (원시 타입 제외한) 데이터 = array, object, function 등 |
값 자체를 가져온다! 데이터 복사 시 새로운 메모리 공간을 생성하여 메모리에 독립적인 값을 저장 |
값을 가리키는 포인터 (주소이자 링크이자 뿌리?)를 가져온다 데이터 복사 시 데이터에 대한 주소, 뿌리의 값으로 저장되기 때문에 복사 시 값 자체가 아니라, 값을 가리키는 레퍼런스, 참조 주소가 복사된다. |
깊은 복사 (for primitive datatype)
let a = 1; let b = a; console.log(a); // 1 console.log(b); // 1 a = 3; console.log(a) // 3 console.log(b) // 1
변수 a 에 1을 할당하고 / 변수 b 에 a를 할당해준다. => 즉, a == b 같아지게됨
이 때, 변수 a 에 3을 다시 할당해버리면, a는 3으로 바뀌고, b는 그대로 1이다.
이는 a,b는 독립적인 공간을 차지하고 저장되기 때문이다.
즉, 얇은 복사처럼 공간의 주소값, 참조값을 가져오는 게 아니라 독립적인 공간을 가지고 있으니까
a가 바껴도 b는 바뀌지 않는다.
얕은 복사 (shallow copy)
let obj1 = {name:'lee'} let obj2 = obj1 console.log(obj1) // {name : 'lee'} console.log(obj2) // {name : 'lee'} obj1.name = "kim" console.log(obj1) // {name : 'kim'} console.log(obj2) // {name : 'kim'} console.log(obj1 === obj2) // true let obj3 = {name:"kim"} console.log(obj3) // {name: 'kim'} console.log(obj3 === obj1) // false console.log(obj3.name === obj1.name) // true
위에서 한 깊은 복사와 다르다.
#1 - obj2에 obj1을 대입해준 경우,
콘솔처리해보면 복사가 되는 건 똑같다.
이 때 obj2는 obj1 값을 실물 그대로 가져온 게 아니라, obj1을 가리키는 주소값, 링크를 가져온거다.
(like POINTER)
따라서, obj1 과 obj2를 비교해보면 주소값이 같기 때문에 true 가 나온다.
#2 - obj3을 obj1과 동일한 key,속성값을 가진 객체로 만든 경우 (대입X)
내부 데이터는 같을지언정, 컴퓨터는 둘을 다른 데이터 주소값으로 저장해주기 때문에
obj3과 obj1을 비교해보면 주소값이 다르기 때문에 false가 나온다.
#3. - 마지막으로 obj3, obj1 의 객체 속성값을 비교해보면?!
obj1.name 과 obj3.name 서로 다른 객체 안에 있지만,
어쨌든 객체 내부의 원시값 자체는 깊은 복사가 되기 때문에,
둘을 비교하면 name : "kim" 은 같은 string값이므로 true가 출력된다.
Object.assign(A , B)
단어 뜻 그대로 객체를 할당해주는 역할 / 객체 내부의 데이터값들을 바꿔준다!
사용법 / Object.assign(A , B)
첫번째에 들어가는 매개변수 A : 속성을 바꿔줄 객체 (바꿔줘!)
두번째에 들어가는 매개변수 B : A에 넣고 싶은 속성을 가지고 있는 객체 (어 바꿔줄게!)
연습삼아 두 가지 경우를 해보았고 결론부터 말하자면 아래와 같다.
1- 이미 속성값들을 가진 객체를 바꿔주면서 새로운 변수에 담아준 경우 - > 깊은 복사가 됐다
2- 바꿔줄 객체를 빈 객체로 설정해 그 빈 객체에 복사를 한 경우 -> 얕은 복사가 됐다
#1. 깊은 복사가 된 경우
let yj = { name : 'A', age : 29, footsize : 230 } let wantChange = { name : 'A', age : 20, height : 170, } let changedYj = Object.assign(yj,wantChange) console.log(changedYj) console.log(yj) console.log(yj===changedYj) // true
이미 속성이 있는 yj에 다른 객체 wantChange를 복사해준다.
<출력>
name : 'A' 같으니까 그대로 있고
age :29-> 20 으로 바뀌고
footsize : 230 은 다른 객체인 wantChange에 없는 속성이므로 그대로 가져간다.
height: 170 은 그대로 복사 되어 추가된다.
바뀐 yj 객체를 변수 changedYj에 담아주고
yj 와 changedYj를 콘솔 찍어보니 같은 객체가 나온다.
둘을 비교해보면?
changedYj는 yj를 기반한 객체이므로 둘을 비교해보면 같은 참조값을 가진 객체이기때문에 true가 나온다.
#2. 얕은 복사가 된 경우
let lee = { name : 'leeyj', age : 30 } let Newlee = Object.assign({},lee) console.log(lee) console.log(Newlee) console.log(Newlee===lee) // false
lee라는 객체를 복사해서 담아줄 Newlee라는 변수를 선언해준다.
그리고 여기에 Object.assign({ },lee)를 담아줬다.
즉, 빈 객체 { } 에 lee를 담아줬고, 콘솔을 찍어보면, lee 객체나 Newlee 객체나 같은 객체로 출력된다.
근데? 둘을 비교해보면?
false가 나온다.
왜냐면, Newlee는 lee의 속성만을 복사해온거지, lee 객체 자체를 가져온 게 아니다.
새로운 빈 객체 { } 안에 lee 속성을 넣은 거니까 얕은 복사가 된거다.
그래서 결과물은 lee와 Newlee가 같지만 엄연히 따지면 다른 참조값을 가진 객체이므로 false이다!
... spread 문 ?
사용법 :
속성을 복사해서 넣어줄 객체 = { 속성1, 속성2, ... 속성을 복사해오고싶은 객체명}
변경할 객체 안에 복사해올 객체명을 넣고 그 바로 앞에 ... 붙이면 끝!!
Object.assign()과 비슷한데, Object.assign은 옛날구문이고 이 spread 문법?이 ES6 의 최신 문법이라고 한다.
내가 봐도 이 dotdotdot 이 더 간결한 것 같다.
얕은 복사
let cat = {name : 'hoochu'} let cat2 = { age : 2, ...cat } console.log(cat2) /* {age : 2, name : 'hoochu'} */
cat2에 다른 속성값이 있어도, 그 맨 뒤에 ...cat 만 넣으면
cat의 속성값이 복사되어 온다.
객체 안에 객체를 복사해서 넣을수도 있다!
blockchain의 그 block이 객체이다.
const blockHeader = { hash:000000000000000000000, // 이블럭의 이름 (16진수로 들어감) timestamp:1641519318, //timestamp = 1970-01-01을 기준으로 날짜를 계산하자 height:717521, // block의 속성값들은 아무거나 Difficulty:4, //mining 시 난이도조절 Nonce:4006, } const blockBody = [ { fee:'0.000000000 BTC', Hash:89232461321215545465465212 }, { fee:'0.000000000 BTC', Hash:89232461321215545465465212 } ] const block = { blockHeader : {...blockHeader}, // 객체의 속성값으로 객체가 들어감 blockBody : [...blockBody] // 객체의 속성값으로 객체가 들어감 } console.log(block)
객체 내부의 속성값으로 객체가 넣어졌다!
new Set (객체명)
객체안의 중복되는 속성값들을 제거해준다.
const dupArr = [1,2,3,1,2] const set = new Set (dupArr) console.log(set)
결과물 = 중복된 1, 2는 제거 되고 (3) [1, 2, 3] 만 남는다.
tip!
이전에 배울 때 const 는 상수, 즉 바뀌지 않는 고정값의 변수를 선언 할 때 쓴다고 했었다.
https://yjleekr.tistory.com/16
primitive data type들은 const로 변수를 선언해버리면 바뀌지 않는데 비해
객체는 const로 선언했어도 객체 그 자체를 바꾸진 못해도 내부의 내용을 변경하거나 추가하는 건 할 수 있다..
뭔가 모순이 생겨버리는데,, 적절히 알아서 잘 쓸것,,
'JavaScript' 카테고리의 다른 글
DOM ?! / class 와 object (1) | 2022.01.11 |
---|---|
배열 - array method에 대하여 (API) - 1 (0) | 2022.01.11 |
배열 array와 객체 object / property와 method (0) | 2022.01.06 |
Function 함수/ return vs. console.log (0) | 2022.01.06 |
Operators (연산자)에 대해서 - 2 (if, for, while구문) (0) | 2022.01.04 |