개발 공부/JavaScript

JavaScript 이론 정리 #4 [구조 분해 할당, 나머지 매개 변수, 전개구문]

YJzero 2022. 8. 27. 18:28

코딩앙마님의 강의를 보고 정리한 글입니다.

https://www.youtube.com/watch?v=4_WLS9Lj6n4&list=PLu8qrPjYh1hcuFnkwiaEDb578Jklc1EWh&index=1&t=3774s 


 

구조 분해 할당(Destructuring assignment)

:배열이나 객체의 속성을 분해해서 그 값을 변수에 담을 수 있게 하는 표현식

 

 

배열 구조 분해
let [x, y] = [1, 2];

console.log(x); //1
console.log(y); //2
let users = ["Mike", "Tom", "Jane"];

let [user1, user2, user3] = users;
// let user1 = users[0];
// let user2 = users[1];
// let user3 = users[2];

console.log(user1); //'Mike'
console.log(user2); //'Tom'
console.log(user3); //'Jane'

이렇게 구조 분해 할당을 하면 아래 주석과 동일한 작동을 한다.

 

 

let str = "Mike-Tom-Jane";

let[user1, user2, user3] = str.split('-');

console.log(user1);//'Mike'
console.log(user2);//'Tom'
console.log(user3);//'Jane'

split를 이용해서 문자열을 배열로 쪼개서 구조 분해 할당을 하는 것도 가능하다!

 

 

만약 구조 분해 할당을 했는데 해당하는 값이 없다면 어떻게 될까?

let [a, b, c] = [1, 2];

console.log(c); //undefined

값이 없다면 undefined가 들어가게 된다.

 

그래서 기본값을 설정해두면 이러한 오류를 막을 수 있다.

let [a=3, b=4, c=5] = [1, 2];

console.log(a); //1
console.log(b); //2
console.log(c); //5

만약 c처럼 할당된 값이 없다면 설정되어 있는 기본 값 5가 출력된다.

 

 

구조 분해 할당을 하되 필요 없는 값은 무시하고 싶다면? 공백을 이용하면 된다.

let [user1, ,user2] = ['Mike', 'Tom', 'Jane', 'Tony'];

console.log(user1); //'Mike'
console.log(user2); //'Jane'

이렇게 쉼표와 공백을 사용하면 Mike는 user1에 할당, Tom은 공백에 할당, Jane은 user2에 할당 Tony는 할당 값없음. 이렇게 되어 최종적으로 Mike와 Jane만 할당 값을 갖게 된다.

 

 

할당된 값 바꾸기

구조분해 할당 없이 이미 할당된 변수를 바꾸려면 의미 없는 변수 하나를 더 만들어서 바꿀 수 있다.

이미 값이 할당된 변수 a와 b의 값을 바꾸고 싶다면 a=b 이렇게 하면 안 된다. 왜냐하면 a의 값이 사라지기 때문이다. 따라서 의미 없는 변수 c를 만들어서 a의 값을 c에 저장한 후 a=b, b=c 이렇게 값을 변경해주면 된다.

let a = 1;
let b = 2;

let c = a;
a=b;
b=c;
a b c
2 1 1

 

이럴 때 구조 분해 할당을 이용해면 간단하다.

let a=1;
let b=2;

[a, b] = [b, a];

임시 변수를 사용하지 않고 쉽게 값을 바꿀 수 있다.

 

 

 

객체 구조 분해
let user = {name: 'Mike', age: 30};

let {name, age} = user;
//let name = user.name;
//let age = user.age;

console.log(name); //'Mike'
console.log(age); //30

이렇게 구조 분해 할당한 것과 그 아래의 주석은 동일하게 작동한다.

배열 구조 분해와 거의 똑같지만 차이점은 순서를 신경쓰지 않아도 된다는 것이다. name 과 age의 순서가 바뀌어도 똑같이 작동된다.

 

 

새로운 변수 이름 할당

꼭 객체의 키 값으로 해야 하는 것은 아니다. 새로운 변수 이름으로 할당할 수 있다.

let user = {name: 'Mike', age: 30};

let {name: userName, age:userAge} = user;

console.log(userName); //'Mike'
console.log(userAge); //30

 

 

기본값

배열과 마찬가지로 기본값을 설정할 수 있다.

let user = {name: 'Mike', age: 30};

let {name, age, gender = 'male'} = user;

gender에 할당된 값이 없어서 기본값이 없으면 undeifned가 뜨지만 기본 값을 설정해두면 할당된 값이 없어도 undeifned가 아닌 기본값이 출력된다.

 

기본값은 undeifned 일 때만 사용된다! 만약 할당된 값이 있다면 그 값이 출력된다.

 

 

나머지 매개변수

 

인수전달

function showName (name){
	console.log(name);
}

showName('Mike'); //'Mike'
showName('Mike', 'Tom'); //?

 

이렇게 한 개를 매개 변수로 받는 함수에서 두 개의 인수를 전달했을 때 오류는 나지 않는다. 자바스크립트에서는 인수의 개수에 제한이 없기 때문에.

하지만 Mike가 출력되고 Tom 은 출력되지 않는다.

 

함수의 인수를 얻는 방법은 첫 번째 arguments를 사용하는 방법, 두 번째 나머지 매개 변수를 사용하는 방법이 있다.

 

arguments

:함수로 넘어온 모든 인수에 접근

:함수 내에서 이용 가능한 지역 변수

: legnth / idnex 

: Array 형태의 객체

: 배열의 내장 메서드 없음

 

function showName(name) {
	console.log(arguments.length);
    console.log(arguments[0]);
    console.log(arguments[1]);
}

showName('Mike', 'tom');

//2
//'Mike'
//'Tom'

이렇게 arguments로 접근이 가능하고 length(받은 인수의 개수)와 index 사용이 가능하다.

 

하지만 es6를 사용할 수 있는 환경이라면 나머지 매개변수 사용을 권장하고 있다.

 

 

 

나머지 매개변수(Rest parameters)

:정해지지 않은 개수의 인수를 배열로 나타낼 수 있다.

function showName(...names){
	console.log(names);
}

showName();//[]
showName('Mike');//['Mike']
showName('Mike', 'Tom');//['Mike', 'Tom']

아무것도 전달되지 않으면 undeifned가 아니라 빈 배열이 반환된다.

 

 

예시로 전달된 모든 수를 더해야 하는데 전달되는 인수의 개수가 정해져 있지 않다고 가정해보자.

function add(...numbers){
	let result = 0;
    numbers.forEach((number) => (result+= number));
    console.log(result);
}

add(1, 2, 3); //6
add(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); //55

여기서 numbers 즉, 나머지 매개 변수는 배열이기 때문에 arguments와 다르게 forEach 같은 배열 내장 메소드 사용이 가능하다.

 

 

이번엔 user 객체를 만들어 주는 생성자 함수를 만들어 보자.

function User(name, age, ...skills){
	this.name = name;
    this.age = age;
    this.skills = skills;
}

cons user1 = new User('Mike', 30, 'html', 'css');
cons user2 = new User('Tom', 20, 'React');
cons user3 = new User('Jane', 10, 'English');

console.log(user1);
console.log(user2);
console.log(user3);

skill을 여러 개 가질 수도 있으니 skill은 나머지 매개변수로 받아와 준다.

주의할 점은 나머지 매개변수는 꼭 마지막에 사용되어야 한다는 것! 

 

 

전개 구문(Spread syntax)


배열
let arr1 = [1, 2, 3];
let arr2 = [4, 5, 6];

let result = [0, ...arr1, ...arr2, 7, 8, 9];
//[0 ,1 ,2 ,3 ,4 ,5, 6, 7, 8, 9]

이렇게 전개 구문을 사용하면 해당 배열 전체를 가져올 수 있다.

 

배열을 합쳐보자.

먼저 전개구문을 사용하지 않고 arr2와 arr1을 [4,5, 6, 1, 2, 3] 순서로 합치려면

let arr1 = [1, 2, 3];
let arr2 = [4, 5, 6];

arr2.reverse().forEach((num) => {
	arr1.unshift(num);
});

console.log(arr1);

이렇게 해야 한다. reverse를 하는 이유는 안 하고 unshift를 할 경우 arr2의 4가 arr1의 1 앞으로 가서 [4, 1, 2 ,3]. 그다음 arr2의 5가 arr1의 앞으로 가서 [ 5, 4, 1, 2 ,3] 이런 식으로 되기 때문이다. 따라서 reverse를 해주었다.

 

근데 이것을 전개 구문을 사용해서 한다면?

let arr1 = [1, 2, 3];
let arr2 = [4, 5, 6];

arr1 = [...arr2, ...arr1];

console.log(arr1);

이렇게 간단하게 해 줄 수 있다.

 

 

 

객체
let arr = [1, 2, 3];
let arr2 = [...arr]; //[1, 2, 3]

let user = {name: 'Mike', age:30};
let user2 = {...user};

user2.name = "Tom";

console.log(user.name); //"Mike"
console.log(usr2.name); //"Tom"

 

user, info, fe, lang이라는 객체가 있을 때 user에 info를 넣고 fe와 lang을 skill로 만들어서 user에 넣어보자.

let user = {name: "Mike"};
let info = {age: 30};
let fe = ["JS", "React"];
let lang =["Korean", "English"];

user = Object.assign({}, user, info, {
  	skills: [],
  }
)

fe.forEach( (item) => {
	user.skills.push(item);
});

lang.forEach((item) => {
	user.skills.push(item);
})

console.log(user);

만약 전개 구문을 사용하지 않는다면 이렇게 만들 수 있다. 

그러면 이렇게 결과가 나온다.

 

전개구문을 사용한다면?

let user = {name: "Mike"};
let info = {age: 30};
let fe = ["JS", "React"];
let lang =["Korean", "English"];

user = {
	...user,   
    ...info,
    skills: [...fe, ...lang],
};

console.log(user);

이렇게 훨씬 간단하게 사용 가능하다!