function sum(a,b) {
return a+b;
}
console.log(sum(1,2,3,4,5,6,7));
// output -> 3
위의 예시처럼 sum 함수 정의 시 매개변수를 두개만 선언해주고, 호출 시 그보다 많은 인수를 전달한다면 전달한 인수에서 앞의 두개만 선택되어 반환값이 도출된다.
...
이다. function showName(firstName, lastName, ...titles) {
alert( firstName + ' ' + lastName ); // Bora Lee
// 나머지 인수들은 배열 titles의 요소가 됩니다.
// titles = ["Software Engineer", "Researcher"]
alert( titles[0] ); // Software Engineer
alert( titles[1] ); // Researcher
alert( titles.length ); // 2
}
showName("Bora", "Lee", "Software Engineer", "Researcher");
위의 예시에서는 매개변수로 두개의 변수를 받고, ...titles
가 세번째 매개변수로 온다.
이후 호출 시 네개의 인수를 넘겨줬다.
그럼 앞에서부터 변수에 각각 할당을 해준 뒤,
남아있는 모든 인수는 ...배열
에 묶어서 담기게 된다.
...
뒤에 오는 이름은 배열명이 된다. 여기서 주의해야 할 사항은!
이러한 나머지매개변수는 각각의 매개변수에 인수를 할당한 뒤, 뒤에 남은 인수를 묶어서 저장하는 역할이기 때문에 반드시 함수 매개변수의 가장 마지막에 와야 한다.
(중간에 올 경우 에러 발생!)
arguments
배열에 담기게 된다고 이해하자. arguments[0]
두번째 인수는 arguments[1]
이런식으로 접근할 수 있다. ex-
function kopis() {
console.log(arguments.length);
console.log(arguments[2]+"\n");
for (let arg of arguments) {
console.log(arg);
}
}
함수가 이렇게 정의되었을 때,
kopis("숭","빈","서","혜","민");
이렇게 호출할 경우 Output은
5
서
숭
빈
서
혜
민
만약 접근하는 인덱스에 비해 인수 개수가 부족할 땐?
kopis("숭","빈");
output은 아래와 같고, arguments에서 접근할 수 없는 인덱스는 undefined
처리가 된다.
2
undefined
숭
빈
위에서 다룬 내용이 여러 인수를 하나의 배열로 묶어서 처리하는 방식이었다면,
스프레드 문법은 하나의 배열을 인수로 전달해도 각 요소가 쪼개서 사용되는 방식을 얘기한다.
...
를 사용하지만 하는 일은 반대라는 점!...arr
를 함수 정의 시 매개변수 자리에 넣어줬지만, ...arr
를 함수 호출 시 인수 자리에 넣어준다. let arr = [3, 5, 1];
alert( Math.max(...arr) ); // 5
여기서 arr는 배열이지만, max 메소드의 인수로 ...arr를 넣어주면, 실제로 max 메소드가 실행될 때는 arr 배열의 요소들의 각각의 인수로 분리되어서 인수로 담기게 된다.
즉,
로 확장해주는 것이 스프레드 문법의 역할이다.
이렇게 각 요소를 알알이 분리시켜주기 때문에 배열이나 새로운 값과의 결합도 용이하다.
let arr1 = [1, -2, 3, 4];
let arr2 = [8, 3, -8, 1];
alert( Math.max(...arr1, ...arr2) ); // 8
let arr = [3, 5, 1];
let arr2 = [8, 9, 15];
let merged = [0, ...arr, 2, ...arr2];
alert(merged); // 0,3,5,1,2,8,9,15 (0, arr, 2, arr2 순서로 합쳐집니다.)
스프레드 문법은 배열 외의 모든 iterable 객체에도 사용할 수 있다.
대표적인 문자열의 경우, 문자열에 스프레드 문법을 적용하면 배열의 요소가 각각 분리되듯이, 각각의 글자들이 분리되어 쓰인다.
배열과 객체를 복사하는 방법인 Object.assign()
외에도, 스프레드 문법을 활용하는 방식이 있다.
let arr = [1, 2, 3];
let arrCopy = [...arr]; // 배열을 펼쳐서 각 요소를 분리후, 매개변수 목록으로 만든 다음에
// 매개변수 목록을 새로운 배열에 할당함
// 배열 복사본의 요소가 기존 배열 요소와 진짜 같을까요?
alert(JSON.stringify(arr) === JSON.stringify(arrCopy)); // true
// 두 배열은 같을까요?
alert(arr === arrCopy); // false (참조가 다름)
// 참조가 다르므로 기존 배열을 수정해도 복사본은 영향을 받지 않습니다.
arr.push(4);
alert(arr); // 1, 2, 3, 4
alert(arrCopy); // 1, 2, 3
위의 예시에서
1. ...arr
를 통해 배열의 탈을 벗고
2. n개의 각 요소들이 분리되어 just '여러개의 값'으로 존재하다가
3. arrCopy라는 새로운 변수에 할당되며 '여러개의 값'이 다시 합쳐지게 되면
arr와 arrCopy는 참조가 다르기 때문에 복사본이 된다.
let obj = { a: 1, b: 2, c: 3 };
let objCopy = { ...obj }; // 객체를 펼쳐서 각 요소를 분리후, 매개변수 목록으로 만든 다음에
// 매개변수 목록을 새로운 객체에 할당함
// 객체 복사본의 프로퍼티들이 기존 객체의 프로퍼티들과 진짜 같을까요?
alert(JSON.stringify(obj) === JSON.stringify(objCopy)); // true
// 두 객체는 같을까요?
alert(obj === objCopy); // false (참조가 다름)
// 참조가 다르므로 기존 객체를 수정해도 복사본은 영향을 받지 않습니다.
obj.d = 4;
alert(JSON.stringify(obj)); // {"a":1,"b":2,"c":3,"d":4}
alert(JSON.stringify(objCopy)); // {"a":1,"b":2,"c":3}