JS 데이터_특성과 복사

oching·2022년 4월 27일
0

JavaScript

목록 보기
7/11

FASTCAMPUS ST-FE 3기
Part 4. JavaScript Level up - Ch 1. JS 데이터 06~09

01. 구조분해할당

배열이나 객체를 해제하고, 그 값을 다른 변수에 담을 수 있게 하는 표현식.
변수명으로 값을 불러올 수 있어
객체에서 user.name || 배열에서 array[0] 식으로
번거롭게 참조하지 않아도되어 편리하다.

객체에서

const user = {
  name : 'oching',
  age : 95,
  email : 'oching.choi@gmail.com'
}
const {name, age, email, address} = user

console.log(name);  //oching
console.log(age);  //95
console.log(email);  //oching.choi@gmail.com
console.log(address); //undefined

const {name, age, email, address} = user
변수선언을 한 뒤 원래 구조인 객체user와 연결. -> '구조분해할당해 변수로 사용하는군'
const {name:text, age, email, address} = user
만약 name이라는 변수명이 마음에 들지않는다면,,
name이라는 key값은 그대로 가져오되, name:바꾸고자하는변수명으로 변경해 사용가능하다.

배열에서

const fruits = ['apple', 'banana', 'cherry'];
const [a,b,c,d] = fruits;
console.log(a,b,c,d);

배열은 더 쉽다.
const [a,b,c,d] = fruits 원래 순서대로 똑같이 지정해주고
변수로 뽑아서 사용하면 끝!
근데 만약, 내가 'cherry'라는 값만 필요하다면?

const fruits = ['apple', 'banana', 'cherry'];
const [, ,b] = fruits;
console.log(b);  //cherry

[, ,b] 위치로 값을 인식하기 때문에 ,로 순서 맞추는 것 유의하자.


02. 전개 연산자

배열데이터 안의 인자들을 나열시켜준다.
arr[i]식으로 부르지않아도 기호...를 배열앞에 붙여주면
배열 속 값들을 불러 나열시켜준다.

const fruits = ['apple', 'banana', 'cherry']
console.log(fruits);
console.log(...fruits);
//console.log(apple', 'banana', 'cherry');

function toObject(a,b,c){
  return {
    a:a,
    b:b,
    c:c
  }
}
console.log(toObject(...fruits)

console.log(...fruits); 전개연산자로 불러오지않았다면,
console.log(toObject(fruits[0], fruits[1], fruits[2])
각 배열의 인덱스로 접근해 인수를 전달해줘야했을 것이다.

배열안의 인자 개수와 파라미터의 개수가 다를때에도 전개연산자로
나머지 인수들을 모두 받아올 수 있게 할 수 있다.

const fruits = ['apple', 'banana', 'cherry', 'orange'] //배열속인자의 개수가 더 많음
console.log(fruits);
console.log(...fruits);
//console.log(apple', 'banana', 'cherry');

function toObject(a,b,...c){  //파라미터로 전개연산자처리, 여분의 값 다 받아온다. 
  return {
    a:a,
    b:b,
    c:c
  }
}
console.log(toObject(...fruits)

furits 배열에 있는 인자는 총 4개인데 toObject가 받는 파라미터는 a,b,c 세개로 존재했다.
때문에 마지막 orange는 전달받지못하는 상황이 발생한다.
이때 전개연산자를 활용하면 ...c에 남는 인자 모두 다 받아올 수 있다.
이를 reset parameter라고도 부른다.

💡 참고) js에서는 속성과 값의 이름이 같을 때 하나로 축약가능하다.

function toObject(a,b,...c){ 
  return {
    a,
    b,
    c
  }
}

03. 데이터 불변성

원시데이터 string, number, boolean, undefined, null
참조형데이터 object, array, function

데이터간 비교시 일치, 불일치를 결정하는 기준은
어떠한 메모리 주소를 참조하는 지이다.
a === b의 결과가 true라면, a와b가 바라보고있는 메모리의 주소가 같다는 것을 의미한다.

원시데이터는값을 할당해줄 때 새로운 메모리 주소를 생성하는 것이 아닌,
메모리 주소로 옮겨주는 것을 의미한다.
즉, let d = 4일 때 d에게 새로운 메모리 주소를 생성시키는 것이 아니라,
4가 가지고있는 기존의 메모리 주소로 옮겨주는 것이다.
이를 두고 불변한다고 표현하는 것을 데이터 불변성이라고 한다.

하지만 참조형데이터는 다르다. 참조형데이터의 경우
새로운 값을 할당 할 때 마다 새로운 메모리 주소를 갖는다.
가변한다.

이 때 주의할 점은, 값을 할당시킨 경우 결국 메모리의 주소를 공유 시키는 것이기 때문에,
주소를 공유한 변수 간의 예기치 않은 동기화가 발생할 수 있어 조심해야한다.

let a = {k:1}
let b = {k:1}
console.log(a,b,a===b)   //{k:1}, {k:1}, false - 각각의 메모리주소를 갖기때문

a.k = 7;
b = a ;
console.log(a,b,a===b)   //{k:7}, {k:7}, true
a.k = 2;
console.log(a,b,a===b)   //{k:2}, {k:2}, true

b=a로서 b를 a가 가진 메모리 주소로 옮겨두었기때문에
이후 a.k의 값만 변경했다해도 같이 b.k 값 까지 변경된 것이다.


04. 얕은 복사와 깊은 복사

같은 메모리 주소를 공유하면 의도치 않은 값의 공유가 생길 수 있기에 복사해 새로운 객체를 만들면,
내용은 같지만 각자의 메모리 주소로 배정될 수 있지않을까?
때문에 사용되는 개념이 복사이다.
참조형 데이터들은 바로 대입연산자로 같은 메모리 주소를 공유시키지않고 복사해서 사용한다.

const user ={
  name:'oching',
  age : 95,
  emails: 'oching.choi@gmail.com'
}
const copyUser = user;  
console.log(copyUser === user);   //true

user.age = 22;
console.log('user', user);  //22
console.log('copyUer', copyUer);   //22

const copyUser = user;로 같은 메모리 주소로 할당 시키고 나니, user.age값만 변경시켜도 copy.user의 값까지 같이 공유되어 변경되었음을 알 수 있다.

얕은복사

1.Object.assing({}, user)

const user ={
  name:'oching',
  age : 95,
  emails: 'oching.choi@gmail.com'
}
const copyUser = Object.assing({}, user);   //false
console.log(copyUser === user);

user.age = 22;
console.log('user', user);  //22
console.log('copyUer', copyUer);  //95

const copyUser = Object.assing({}, user);로 복사해 새로운 객체를 만들고 나면,
복사해 생성된 객체는 다른 메모리 주소를 배정받기에
일치하지도 않고, 값의 동기화로 변경이 일어나지않는다.

2. 전개연산자(...)

const user ={
  name:'oching',
  age : 95,
  emails: 'oching.choi@gmail.com'
}
const copyUser = (...user);
console.log(copyUser === user);  //false

user.age = 22;
console.log('user', user);  //22
console.log('copyUer', copyUer);  //95

const copyUser = (...user)로 값을 나열해 하나의 객체를 새로 생성해주며 복제했기에 false 값과 값의 변경 동기화가 일어나지않는다.

그럼 현재 user와 copyUser 두 객체 안의 내용은 복사가 되었을까? user.emails만 이메일 주소를 push해주었을 때 값의 동기화가 일어나지않기에 copyUser에는 push해준 이메일 주소가 없다. 이를 얕은 복사라고 한다.

user.emails.push('oching.choi@gamil.com');
console.log(user.emails === copyUser.emails);  //false
console.log('user', user);   //이메일주소가 value로 추가됨
console.log('copyUser', copyUser);  //이메일주소 추가되지않았음. 

깊은복사

참조데이터형 안에 또 다른 참조 데이터가 있을 경우 안의 key ,value값도 복사해와야하기에 깊은 복사를 고려해야한다.

lodash MDN사용
https://lodash.com/docs/4.17.15#cloneDeep

var objects = [{ 'a': 1 }, { 'b': 2 }];
 
var deep = _.cloneDeep(objects);
console.log(deep[0] === objects[0]);
// => false

변수 deep에 clone을 하면서 안에 있는 key값과 그에 연결된 value 값 까지 꼼꼼히 복사해온 것을 알 수 있다.
값을 복사해왔지만 새로운 객체를 생성해온 것이므로 다른 메모리 값을 가지고, 때문에 일치를 확인하면 false로 확인된다.

profile
FE Studying

0개의 댓글

관련 채용 정보