: JavaScript는 부여되는 인수의 수가 함수 쪽에서 요구하는 수와 다른 경우에 이를 체크하지 않는다.
function showMessage(value) {
console.log(value);
}
showMessage(); // 결과 : undefined
showMessage('철수'); // 결과 : 철수
showMessage('철수', '영희'); // 결과 : 철수
➡ 인수가 버리지는게 아니라 인수 정보의 하나는 보관/유지되며 나중에라도 이용할 수 있다.
❗ arguments 객체 ❗
: 함수 안(함수를 정의하는 본체 부분)에서만 이용할 수 있는 특별한 객체
1) 인수 정보를 관리 = 호출원으로부터 주어진 모든 인수 값을 보관/유지한다.
2) 실제로 주어진 인수의 수와 요구하는 인수의 수를 비교해 서로 다른 경우에는 에러를 반환할 수 있다.
3) 가변길이 인수의 함수 (2번에서 설명)
function showMessage(value) {
if (arguments.length != 1) { // length : 인수의 개수
throw new Error('인수의 수가 서로 다릅니다:' + arguments.length);
}
console.log(value);
}
try {
showMessage('철수', '영희');
} catch(e) {
window.alert(e.message);
}
🔸 인수의 디폴트 값 설정하기
: 인수의 수를 체크하지 않는다는 의미는 모든 인수가 생략 가능하다. 그렇지만 대다수의 경우 인수가 단지 생략된 것만으로는 거의 대부분 올바르게 동작하지 않아서 디폴트 값을 설정해둘 필요가 있음.
function getTriangle(base, height) {
if (base === undefined) { base = 1; }
if (height === undefined) { height = 1; }
return base * height / 2;
}
console.log(getTriangle(5)); // 결과 : 2.5
➡ 인수가 하나밖에 지정되어 있지 않아 후방의 인수 height는 생략됨 생략할 수 있는 것은 어디까지나 뒤의 인수이다.
: 가변길이 인수의 함수 - 인수의 개수가 미리 정해져 있지 않은 함수
: 호출원의 사정상 인수의 개수가 변동될 가능성이 있는 함수
var showMessage = new Function('msg', 'console.log(msg);'); ⓐ
var getTriangle = new Function('base', 'height', 'return base * height / 2;'); ⓑ
ⓐ 주어진 인수가 2개 (가인수와 처리내용 1개)
ⓑ 주어진 인수가 3개 (가인수 2개와 처리내용 1개)
function printf(format){
// 인수의 2번째 이후를 순서대로 처리
for (var i = 0, len = arguments.length; i < len; i++){
//RegExp는 정규표현식을 만드는 함수.
var pattern = new RegExp('\\{' + (i - 1) + '\\}', 'g');
format = format.replace(pattern, arguments[i]);
}
console.log(format);
}
printf('안녕하세요, {0}씨. 나는 {1}입니다.', '시온', '피카츄');
//결과 : 안녕하세요, 시온씨. 나는 피카츄입니다.
// 제 1인수(서식 문자열)의 플레이스 홀더를 제2인수 이후의 값으로 치환하여 출력
: printf함수는 제 1인수에 지정된 서식 문자열에 포함되는 플레이스 홀더를 제 2인수 이후의 값으로 치환하여 출력하기 위한 함수
: printf 함수의 제 1인수만이 가인수 format으로서 명시적으로 선언되었기 때문에 제 2인수 이후의 인수는 가변길이 인수로 다루어지고 있다.
: arguments 객체로부터 가변길이 인수의 부분을 추출하여 각 순서에 대응하는 플레이스 홀더를 치환하고 있다.
: 명명된 인수 - 호출시에 이름을 명시적으로 지정할 수 있는 인수
: 원래부터 인수의 수가 많은 경우, 생략 가능한 인수가 많고 생략 패턴에도 다양한 조합이 있는 경우에 유효한 방법이다.
getTriangle({ base:5, height:4 }) ⓐ
getTriangle({ height:4 }) ⓑ
getTriangle({ height:4, base:5 }) ⓒ
ⓐ 인수가 많아져도 코드의 의미를 알기 쉽다
ⓑ 앞의 인수만 생략할 수 있다
ⓒ 인수의 순서를 자유롭게 변경할 수 있다
: 함수의 선언 부분에 '가인수 = 디폴트 값'의 형식으로 가인수를 선언한다.
function getTriangle(base = 1, height = 1) {
return base * height / 2;
}
console.log(getTriangle(5)); // 결과 : 2.5
: 디폴트값에는 리터럴 뿐만 아니라 다른 인수, 함수(식)의 결과를 지정할 수 있다.
function multi(a, b = a) {
return a * b;
}
console.log(multi(10, 5)); // 결과 : 50
console.log(multi(3)); // 결과 : 9 (인수 b의 값은 a와 동일하게 3)
❕ 디폴트값이 적용될 경우와 적용되지 않을 경우 ❕
디폴트 값이 적용 되는 경우 : 인수가 명시적으로 건네지지 않았을 경우
디폴트 값이 적용 되지 않을 경우 : null/false/0/빈문자열 등 의미상 비어 있음을 나타내는 값이라도 명시적으로 건네졌을 경우
function getTriangle(base = 1, height = 1) {...}
console.log(getTriangle(5, null)); // 결과 : 0 (5 x null / 2)
function getTriangle(base = 1, height = 1) {...}
console.log(getTriangle(5, undefined)); // 결과 : 2.5 (5 x 1 / 2)
❕ 디폴트값을 갖는 가인수는 인수 리스트의 끝으로 ❕
function getTriangle(base = 1, height) {...}
console.log(getTriangle(10)); // 결과 : NaN (10 x undefined / 2)
: base에 10이 건네짐 그러므로 디폴트 값을 갖는 인수의 뒤족에 디폴트 값을 갖지 않는 인수를 기술해서는 안된다.
: 가인수의 앞에 ...(점 3개)를 부여하면 가변길이 인수가 된다.
1) 함수가 가변길이 인수를 취하는 것을 쉽게 알 수 있다
2) 모든 배열 조작 가능
: '...'연산자는 실인수로 이용함으로써 배열을 각각의 값으로 전개할 수 있다.
console.log(Math.max(15, -3, 78, 1)); // 결과 : 78
console.log(Math.max([15, -3, 78, 1])); // 결과 : NaN
console.log(Math.max(...[15, -3, 78, 1])); // 결과 : 78 ⓐ
console.log(Math.max.apply(null, [15, -3, 78, 1])); // 결과 : 78 ⓑ
ⓐ '...'연산자
ⓑ apply 메소드 - 제 2인수(배열)를 인수로 해서 메소드를 실행한다
: 분할 대입을 이용해서 명명된 인수를 더 간략하게 표현
function getTriangle({ base = 1, height = 1}) {
return base * height / 2;
}
console.log(getTriangle({ base = 1, height = 1})); // 결과 : 10
: 실인수를 객체 리터럴로 건넨다는 점은 변함이 없지만 { 프로퍼티 = 디폴트 값} 형태로 선언함으로써 객체로서 건네진 인수를 분해해 함수 내에서 개별 인수로 액세스할 수 있다.