함수의 전달인자와 매개변수에 대해 알아보겠습니다.
자바스크립트에서는 함수 정의 시 함수 매개변수의 자료형과 함수 호출 시의 전달하는 인자 값의 자료형을 검사하지 않습니다.
심지어 전달인자의 개수도 검사하지 않습니다.
생략 가능한 매개변수
함수 호출 시 본래 정의된 것보다 적은 수의 전달인자가 전달되면 나머지 매개변수는 undefined로 설정됩니다.
1 2 3 4 5 6 7 | function getPropertyNames(o, /*optional*/ a) { if ( a=== undefined ) a = []; //a에 대한 전달인자가 없을 때 새로 배열로 초기화 for(var property in o) a.push(property); return a; } var a = getPropertyNames(o); // 이 경우 새 배열에 o의 속성을 추가 getPropertyNames(p,a); // p의 속성을 a에 추가 | cs |
생략가능한 전달인자를 사용하여 함수를 설계할 때, 생략할 수 있는 인자는 전달인자 목록의 제일 뒤쪽에 두어야 합니다. 첫 번째 인자를 생략하고 두 번째 인자만 전달할 수 없기 때문입니다. 굳이 한다면 첫 번째 인자에는 undefined를 전달해야 합니다.
함수를 정의할 때는 생략할 수 있는 매개변수임을 표시하는 간단한 설명을 주석으로 남겨놓아도 좋을 것 같다고 생각합니다.
가변길이 전달인자 목록 : Arguments 객체
함수가 호출될 때 정의된 매개변수보다 더 많은 인자가 전달되면, 매개변수 이름이 붙지 않은 인자 값을 직접적으로 참조할 방법이 없습니다.
Arguments객체는 이러한 문제에 대한 해결책이 될 수 있습니다.
함수 몸체 내에서 arguments 식별자는 해당 호출에 대한 Arguments 객체를 참조합니다. Arguments 객체는 유사 배열 객체이고 이름이 아니라 인덱스 숫자를 통해 함수의 전달인자를 얻어올 수 있습니다.
1 2 3 4 5 6 7 | function testOneArg(one) { console.log('arguments.length: ', arguments.length); console.log('one: ', arguments[0]); console.log('one: ', one); console.log('arguments[1]: ', arguments[1]); console.log('arguments: ', arguments); } | cs |
자바스크립트는 함수 호출 시 전달인자의 개수를 검사하지 않기 때문에 전달인자가 알맞게 전달되었는지 확인이 필요할때 Arguments 객체를 통해 올바른 개수의 전달인자로 호출되었는지를 확인하는 용도로 사용할 수 있습니다.
전달인자의 개수를 검사하는 것은 보통 불필요하다는 점을 유념해야한다고 합니다. 빠진 전달인자를 undefined 처리하고 여분의 인자는 단순히 무시하는 자바스크립트의 기본 동작은 대부분의 경우에 적합하기 때문입니다.
Arguments 객체의 한 가지 중요한 용도는 임의 개수의 전달인자를 받는 함수를 작성하는 것입니다.
1 2 3 4 5 6 7 8 9 10 | function max() { var max = Number.NEGATIVE_INFINITY; for(var index = 0; index < arguments.length; index++){ if(arguments[i] > max) { max = arguments[i]; } } return max; } | cs |
arguments는 실제로 배열이 아니라 Arguments 객체임을 기억해야합니다.
각 Arguments객체에는 숫자 인덱스가 붙은 배열원소와 length 프로퍼티를 가지고 있습니다.
기술적으로 볼 때 배열이 아니기 때문에 숫자로 된 프로퍼티들을 가지게 된 객체라고 생각하는 편이 더 나을 수 있습니다.
Arguments 객체에는 별난 특징이 하나 있는데요. 비엄격모드에서 만약 함수에 매개변수가 정의되어 있으면, Arguments 객체의 배열 원소는 각 매개변수의 별칭과도 같습니다.
이 말은 Arguements 객체의 배열 원소와 매개변수의 이름은 동일한 값을 가리키는 다른 두 이름입니다.
1 2 3 4 5 | function printArg(x) { console.log('x: ', x); arguments[0] = 'changed'; console.log('x: ', x); } | cs |
callee 와 caller 속성
Arguments 객체는 배열 원소 외에도 callee와 caller 프로퍼티를 정의하고 있습니다.
callee 프로퍼티는 현재 실행되고 있는 함수를 참조합니다.
callee 속성의 초기 값은 실행 중인 Function 개체입니다.이 속성은 익명 함수의 재귀를 허용합니다.
caller는 비표준이지만 많은 자바스크립트 구현체에 보편적으로 구현된 프로퍼티며, 이 함수를 호출한 함수를 참조한다고 합니다. 이름없는 함수를 재귀적으로 호출하는데 유용합니다.
1 2 3 4 5 | function factorial (x) { if(x <= 1) return 1; return x * arguments.callee(x-1); } | cs |
1 2 3 4 5 6 7 8 9 10 11 | function testArg(a, b, c){ console.log('arguments', arguments); console.log('testArg.caller', testArg.caller); console.log('argument.callee', arguments.callee); } function checkCaller(a, b, c) { testArg(a, b, c); } checkCaller(1, 2, 3); | cs |
result
1 2 3 4 5 6 7 8 9 10 11 | arguments [1, 2, 3, callee: function, Symbol(Symbol.iterator): function] testArg.caller function checkCaller(a, b, c) { testArg(a, b, c); } argument.callee function testArg(a, b, c){ console.log('arguments', arguments); console.log('testArg.caller', testArg.caller); console.log('argument.callee', arguments.callee); } | cs |
현재 arguments에 caller 속성은 삭제되어 더이상 작동하지 않습니다. function.caller 의 형태로 사용할 수는 있다고 합니다.
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Functions/arguments/caller
객체의 프로퍼티를 전달인자로 사용하기
어떤 함수에 세 개 이상의 매개변수가 있다면, 이 함수를 호출하는 프로그래머가 인자의 올바른 순서를 기억하기가 어려워질 수 있습니다.
전달인자를 순서에 상관없이 이름/값의 쌍으로 함수에 전달하면 앞의 문제점을 조금 더 효과적으로 해결 할 수 있습니다.
1 2 3 4 | function arrayCopy(from, from_start, to, to_start, length) { // from:array, from_start:index, to:array, to_start:index, length:integer ... } | cs |
1 2 3 4 5 6 7 8 9 10 | function easyCopy(args) { testcopy(args.from, args.from_start || 0, //기본 값을 제공 args.to_start || 0, args.length); } //easycopy() 호출 방법 var a = [1,2,3,4] , b = []; easyCopy({from: a, to: b, length: 4}); | cs |
1 | function max(/*숫자 값...*/ ) { } | cs |
자바스크립트는 매우 유연하며 자료형을 느슨하게 처리하는 언어이기 때문에 때로는 인자 개수와 자료형에 유연한 함수를 작성하는 것이 바람직합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | function flexisum(a) { var total = 0; for(var index = 0; index < arguments.length; i++) { var element = arguments[i], n; if(element == null) continue; // null과 undefined는 if(isArray(element)) n = flexisum.apply(this, element); // 재귀적 방식으로 합계 계산 else if(typeof element === 'functioin') n = Number(element()); else n = Number(element); if(isNaN(n)) //숫자로 변환할 수 없다면, error 발생 throw Error("flexisum() : can't convert " + element + "to number"); total += n; } return total; } | cs |
'javascript' 카테고리의 다른 글
TDZ(Temporal Dead Zone) (0) | 2022.03.26 |
---|---|
this (0) | 2020.09.12 |
기타 연산자들 (0) | 2017.03.12 |
평가 표현식 (0) | 2017.03.12 |
변수 선언 (0) | 2017.02.21 |