나머지 매개변수 ... : 남아있는 매개변수를 모두 모아서 하나의 배열에 넣어라
function foo (arg1, arg2, ...args) {
alert(arg1); // first
alert(arg2); // second
alert(args[0]); // third
alert(args[1]); // fourth
}
foo("first", "second", "third", "fourth")
유사 배열 객체인 arguments를 통해서는 인덱스를 통해서 매개변수에 접근 가능하다
function foo(){
alert(arguments[0 // 1
alert(arguments[1]); // 2
}
foo(1, 2)
arguments는 유사 배열이면서 이터러블 객체이다. 다만 배열은 아니기 때문에 배열 메소드를 사용할 수는 없다. 또한 화살표 함수에서도 사용할 수 없다. 배열 메서드를 사용하거나 인수 일부만 사용할 때는 나머지 매개변수를 사용하는게 좋다.
배열을 통째로 매개변수에 넘겨주어야 할 때, 말 그대로 배열을 '전개'하는 연산자 ...를 사용하면 간편하게 넘겨줄 수 있다.
let arr = [1, 2, 3]
alert(Math.max(arr)) // 에러 발생
alert(Math.max(...arr)) // 3
alert(Math.max(...arr, ...arr2)) // 여러개 전달 가능
alert(Math.max(1, ...arr1, 2)) // 일반적인 값과 혼합하여 사용 가능
또한 스프레드 문법을 통해 문자열과 같은 이터러블한 객체를 배열로 바꿀 때 사용할 수도 있음
let str = "hello";
alert([...str, 's']) // 'h','e','l','l','o','s'
스프레드 문법으로 배열과 객체를 복사할 수 있음
let arr = [1, 2, 3]
let arr_copy = [...arr] // 참조가 아닌 복사됨
let obj = { 1: "one", 2: "two" }
let obj_copy = {...obj} // 참조가 아닌 복사됨
let obj_Copy = Object.assign({}, obj); 보다 짧은 코드로 복사 가능
...이 함수 매개변수의 끝에 있는 경우: 인수 목록의 나머지를 배열로 모아주는 '나머지 매개변수’로 사용됨
...이 함수 호출 시 사용되거나 기타 경우: 배열을 목록으로 확장해주는 '스프레드 문법’으로 사용됨
사용 패턴:
인수 개수에 제한이 없는 함수를 만들 때 - 나머지 매개변수를 사용
다수의 인수를 받는 함수에 배열을 전달할 때 - 스프레드 문법을 사용
결론: let, const 써라
브라우저 환경 - window
node.js 환경 - global 로 전역 객체를 부름
전역 객체의 이름을 globalThis로 표준화하자는 얘기도 나오는 추세
결론: 엄청 필요한 경우가 아니라면 쓰지 마라
함수 프로퍼티
foo.name - 함수의 이름 반환
foo.length - 함수 매개변수의 개수 반환. 나머지 매개변수는 포함하지 않음
foo.customPropertyName = "함수프로퍼티" - 함수 프로퍼티를 임의로 만들어 줄 수도 있음
기명 함수 표현식 - 함수 표현식에서 함수 이름을 붙여준 것
일반 함수 표현식
let foo = function(){
// body
}
기명 함수 표현식
let foo = function funcName() {
// body
funcName(); // 가능
}
funcName(); // 불가능
기명 함수 표현식을 사용할 때 다음과 같은 변화가 발생함
1. 함수 표현식 내부에서 해당 이름을 통해 자기 자신을 호출 가능
2. 기명 함수 표현식 외부에서는 그 이름을 사용할 수 없음
setInterval도 setTimeout과 똑같이 사용하면 됨
단 setInterval은 인수로 넘겨준 시간 간격마다 콜백 함수가 실행되는 차이가 있음
일정 시간 간격 마다 콜백 함수를 실행하기 위해 setInterval을 써도 되지면 중첨 setTimeout을 활용해도 됨
// 2초마다 alert창에 "째깍"이 뜸
let timerId = setTimeout(function tick() {
alert("째깍");
timerId = setTimeout(tick, 2000);
}, 2000);
중첩 setTimeout은 setInterval과 달리 유연하게 코드 작성이 가능함
let delay = 5000;
let timerId = setTimeout(function request() {
// 다른 로직 어쩌구 저쩌구,,
if (서버 과부화로 인한 요청 실패){
// 요청 간격을 늘려줌
delay *= 2;
}
timerId = setTimeout(request, delay);
}, delay);
또한 중첩 setTimeout은 setInterval과 달리 지연 간격을 보장함
더 많은 내용은 https://ko.javascript.info/settimeout-setinterval 참고
6.9 패스
객체 메서드롤 콜백 함수로 전달할 때 this를 잃어버리는 경우가 많다. this에 undefined가 들어가는 경우이다. 객체 메서드를 콜백함수로 전달할 때, 컨텍스트도 제대로 유지하려면 어떻게 해야 될까??
해결책 1: 콜백 함수로 래퍼 함수를 전달함
해결책 2: bind 활용
모든 함수에는 this를 수정하게 해주는 내장 메서드 bind가 있음
let boundFunc = func.bind(context);
func.bind(context)는 함수처럼 호출 가능한 '특수 객체(exotic object)'를 반환함. 이 객체를 호출하면 this가 context로 고정된 함수 func가 반환됨.
따라서 boundFunc를 호출하면 this가 고정된 func를 호출하는 것과 동일하게 됨.
또한 bind로 함수 인수까지 고정해줄 수 있음
화살표 함수에는 this가 없다. 따라서 화살표 함수에서 this를 호출할 경우 외부 렉시컬 환경에서 this를 찾는다.
이러한 특성은 자바스크립트에서 함수를 생성하고 전달할 시 함수의 컨텍스트를 잃지 않게 해 줄 수 있다. 화살표 함수 안에서 this를 호출하면, 외부에서 값을 가져오기 때문이다.
let group = {
title: "1모둠",
students: ["보라", "호진", "지민"],
showList() {
this.students.forEach(
student => alert(this.title + ': ' + student)
);
}
};
group.showList();
this.title은 화살표 함수 바깥에 있는 group의 title을 가져온다.
또한 화살표 함수는 유사 배열 객체인 arguments를 지원하지 않는다.
마지막으로 화살표 함수는 this가 없기 때문에 new와 함께 호출할 수 없다 끝!