강의 | Chap 18 JS 데이터

#7. 전개 연산자(Spread)

이렇게 생겼다. ...
아래와 같이 전체 또는 일부의 내용을 ...로 치환하여 축약할 수 있다.

1) 전체 치환

const fruits = ['Apple', 'Banana', 'Cherry']
console.log(...fruits) // = console.log('Apple', 'Banana', 'Cherry')

2) 일부 치환(rest parameter)
아래 보기.


toObject 함수는 아래와 같이 축약할 수 있다.
1) 축약 전

function toObject (a, b, ...c) { // 일반함수 toObject를 화살표 함수로 바꾸고 앞에 const 붙이기.
	return{ // return {}는 생략 가능.
      a: a, // JS에서 `a: a`는 `a`로 축약 가능하다. (속성:변수 이름이 동일하면 가능)
      b: b, // 위와 같음.
      c: c // 위와 같음.
    }
}

2) 축약 후

const toObject = (a, b, ...c) => ({a, b, c}) 
// object은 ()로 감싸서 객체 데이터로 정의해야지만 인식된다. 
// ()를 빠트려서 중괄호(블럭 표시)로 해석되지 않게 유의하자.

#8. 불변성(Immutability)

원시 데이터의 경우

원시 데이터는 값의 모양이 똑같이 생겼으면 같은 값이다.

1) 3열에서 일치연산자로 a와 b가 일치하는지 확인했을 때 false가 뜨는 이유는 뭘까?
두 데이터가 다른 이유는 단지 값이 달라서가 아니라,
'a(칸1)라는 변수와 b(칸2)라는 변수가 서로 바라보고(참고하고) 있는 메모리 칸이 다르기 때문에'이다.

2) b=a 하고 나서 a === b가 되는 이유는 (현재 a=b=1이다)
값이 현재 1이라 a가 바라보고 있는 칸1을 b 또한 바라보게 되었기 때문이다.

3) 이후 a=7로 바꾸면 b도 7이 될까?
아니다. 아직 a만 칸3을 보고 있고, b는 위에서 언급한 칸1을 보고 있다.

4) 새로운 변수 c에 값 1을 넣으면 어떻게 될까?
칸1에 들어간 숫자 1의 값을 가지게 되며
(칸4에 1이 들어가지 않는다! = 한 번 만들어진 원시 데이터는 다시 새롭게 만들어지지 않는다. = 불변한다.)
마찬가지로 칸1을 보는 b와 같은 값으로 간주된다.

참조형 데이터의 경우

참조형 데이터는 값의 모양이 똑같이 생겼어도 다른 값일 수 있다.

1) 변수 a와 b는 보기엔 같아도 막상 동등 연산자를 사용하면 false가 뜬다. 왤까?
참조형 데이터는 새로운 값이 들어오면 새로운 메모리 주소에 할당된다. (원래 있던 같은 값의 메모리 주소를 중복 사용하지 않는다)
변수 a와 b가 바라보는 메모리 칸이 다르기에 둘은 다른 값이다.


2) a와 b가 같은 경우이다. a에 주어진 k의 값을 7로 바꾸면 k:7이란 데이터는 어디에 할당될까?
원래 a가 쓰고 있던 칸1을 쓴다. 즉 k:1의 1이 7로 바뀐다! (원시 데이터와 다르다. 가변성!)
이후 b = a를 선언하면 b는 a와 같은 칸, 즉 칸1을 보게된다.
이 때 두 값은 같은 값으로, a === b이다.

3) a의 k값을 2로 바꾸면 a와 b는 어떻게 될까.
칸1의 값이 k:2로 바뀌면서, a도 b도 같은 칸을 참조하고 있었기 때문에(이 부분도 원시 데이터와 다르다)
둘 다 k:2로 바뀌며, a === b 이다.

참조형 데이터의 경우 : 같은 메모리를 바라보고 있는 변수가 여러 개일 때,
한 쪽의 변수에 있는 값을 바꾸면 나머지 변수들의 값도 일괄! 바뀌는 점을 주의.

4) 변수 c가 변수 b와 같다고 표현하면,
a, b, c 모두가 메모리 칸 1을 참조하고 있기 때문에 a === b === c가 되며 {k: 2} 값을 갖는다.

5) 여기서 a내 k 값을 9로 바꾸면?
마찬가지다. 모두 칸1을 보고 있기 때문에 역시 a === b === c가 되며 {k: 9} 값을 갖는다.

#9. 얕은 복사와 깊은 복사

아래의 경우 user나 copyUser - 어느 한 쪽의 값을 변경하면
같은 칸(const copyUser = user라고 했기 때문에)을 보고 있는 둘 다 변경된다.
한 쪽만 변경하려면 대책이 필요하다. 그게 바로 얕은 복사와 깊은 복사.

1. 얕은 복사Shallow Copy :

  • 객체/배열 복사할 때 내부에 또 다른 참조 데이터가 없을 경우 사용.
  • Object.assign 또는 전개 연산자를 이용.

방법 1. Object.assign

대상 객체 {} 에 출처 객체 user를 담아서 Object.assign으로 copyUser에게 반환한다.
이때 빈 객체{}에 새로 담긴 내용은 메모리 칸1이 아닌 칸2를 차지하게 되고, 하여 다르게 인식된다.

방법 2. 전개 연산자

const copyUser = userconst copyUser = {...user} 로 표현하여 복사할 수 있다.

2. 깊은 복사Deep Copy:

  • 참조형 데이터(객체/배열/함수) 복사할 때 내부에 또 다른 참조 데이터가 있을 경우 사용.
  • lodash 패키지를 이용한다.

깊은 복사는 그럼 언제 쓸까. 위에서도 말했지만 참조형 데이터 안에 참조형 데이터가 또 있을 경우 쓴다.
가령 위에서는 user 객체 데이터만 복사했지,
그 안의 emails라는 배열 데이터는 복사한 적 없음. (...???)
user나 copyUser나... 그 안의 emails 배열 데이터 내의 정보를 건드리면 또 두 쪽 모두에 영향이 간다.

아래의 fruits를 fruits1로 얕은 복사해봤자,
fruits1에 있는 apple에 Japan을 push해서 추가하면 그 부분에 있어 fruits도 바뀐다는 것.

const fruits = {
  apple: Korea,
  banana: U.S.A.,
  coconut: Thailand,
  durian: Australia
}

방법:

  • 터미널에서 npm i lodash 치고 (-D는 쓰지 않음), 개발 서버 열리면 터미널 닫기.
  • JS 파일 위에 import _ from 'lodash' 쓰기.
  • const copyUser = userconst copyUser = _.cloneDeep(user) 로 고쳐쓰기.
profile
프론트엔드 개발 입문자입니다. 오타, 틀린 내용 피드백 환영합니다.

0개의 댓글