arguments배열과 arguments.callee
함수를 생성하게 되면, 호출객체라 하는 새로운 객체가 생성된다.
생성됨과 동시에 유효범위체인 맨앞에 추가되는데 이 유효범위체인은 말은 어렵지만 쉽게 알수있다.
전역변수, 지역변수, 함수의 유효한 구역을 관할하는것이 유효범위체인이라 볼수있다.
함수가 호출되면서 호출객체는 함수의 arguments객체를 가르키는
arguments프로퍼티로 초기화되는데.. 함수의 이름이명시된 매개변수,var 문으로 선언된 지역변수
들또한 호출객체에 정의된다.
함수를 생성하면서 호출객체가 생성되고 이 호출객체는 argument객체를 가르키는 프로퍼티
각 매개변수와 지역변수를 포함하여 유효범위체인의 맨앞에 정의된다했다. 따라서
이 호출객체는 유효범위 체인 맨앞에 위치하기때문에 함수의 지역변수, 매개변수들과 arguments객체는
모두 함수 내 유효범위에 있게된다.
아주 간단히말하면 아래와 같다
함수생성 -> 호출객체생성(새로운객체) -> 생성과동시 유효범위체인(유효범위지정)맨앞에 위치 ->
함수에 선언된 매개변수, var문으로 선언된 지역변수, arguments객체(실제론 객체를 가르키는 프로퍼티)를
포함하게됨 -> 이 모든것들은 함수 내 유효범위에 있게됨
자 그럼 함수가 생성되며 argument객체를 가르키는 프로퍼티로 초기화 된다했는데
따라서 함수의 몸체안엔 arguments라는 객체가 존재하게 되는것이다.
여기선 배열로 보겠다.
함수도 일종의 배열이지만, 객체로 접근하는게 더욱 바람직하다. 따라서 함수엔 프로퍼티와 메서드가 존재하게 된다.
arguments배열로 접근할수 있는 대표적인 프로퍼티가 몇가지 있는데 여러분이 자주사용하는 length프로퍼티와
많이 궁금해하는 callee프로퍼티이다.
//아래는arguments배열을 활용한 간단한 예제이다.
//arguments의 길이를 계산하여 반복문으로 하나의 문자열로 치환하는 함수이다.
function argsValueCheck(a,b,c,d) {
var name = null;
var argLength = arguments.length;
for(i=0;i<argLength;i++){
//console.log(arguments[i]);
if(i !== argLength-1){
name += arguments[i]+"와";
} else {
name += arguments[i]+"가 있습니다.";
}
}
//console.log(name);
return name;
}console.log(argsValueCheck('uyeong','youngsu','minsu','haha'));
//여기서 사용하는 console.log는 파폭 또는 크롬의 크롬창에서 볼수있다.
//document.write와 alert보다 편하며, 디버깅시 유용하다.
function args(x,y,x) {
console.log(arguments); //전달인자의 데이터
console.log(arguments.length); //전달인자의 배열길이
console.log(arguments.callee.length); //함수가 애초에 기대하는 전달인자 배열길이
}args(1,2); //함수호출
아래와 같이 활용할수있다.
여기서 가정을하자 3개의 전달인자(arguments)를 받는 function이 있다.
이 function은 꼭 3개의 인자를 받아야만한다. 만약 3개의 전달인자를 받지 않으면 데이터의 정확성이
깨진다고 할때, 전달인자를 받은 길이와 애초 함수가 기대하는 전달인자를 비교할수있다.
//전달인자를 체크하는 함수.
function argCheck(args){
var argActual = args.length; //넘어온 전달인자
var argExpact = args.callee.length; //함수가기대하는 전달인자
//넘어온 전달인자와 애초에 기대하는 전달인자의 갯수가 틀리면
if(argActual != argExpact) {
alert("전달인자의 갯수가 맞지 않습니다.");
throw new Error("기대하는 전달인자 : "+argExpact+"이며 넘어온 전달인자는 : "+argActual+"입니다.");
}
}
//3가지 전달인자를 더하는 함수
function argsAdd(a, b, c) {
argCheck(arguments);
return a+b+c;
}
alert(argsAdd(1,2,3)); //6을 반환
alert(argsAdd(2,3)); //throw를 발생시킴
위의 함수처럼 사용가능하지만 callee를 이용하여 클로저의 기능 처럼사용할수있다.
하지만 완벽한 클로저의 기능이 아님을 주의하여야한다.
//일단 아래의 함수를 먼저 보겠다. 전역변수를 카운트변수를 +1해주느 함수이다.
var count = 0;
function countUp() {
return count++;
}
console.log(countUp());
console.log(countUp());
저위의 함수를 사용할경우 전역네임스페이스를 오염시키게 된다.
무슨말이냐 하면, count라는 전역변수는 프로그램내에서 언제 어느때고 생성할수 있는변수이므로
단순히 +1해주는 변수로 전역변수로 사용할경우 후에 다른프로그래머나, 프로그램이 복잡해져
동일한 전역변수를 선언할시 countUp()함수는 신뢰성을 잃게된다.
위의 함수처럼 전역네임스페이스를 어지럽히는대신 함수를 생성할때 새로이 생성되는 호출객체의
임시네임스페이스를 활용하여 다음과같이 작성이 가능하다.
호출객체의 새로운 프로퍼티를 생성함으로써 활용한다.
function countUp2(){
if(!arguments.callee.count) arguments.callee.count = 0;
return arguments.callee.count++;
}
console.log(countUp2());
console.log(countUp2());
하지만 저위 방법은 캡슐화가 불가능하다. 즉 어느어느때고 해당프로퍼티에 접근하여 초기화를할수 있으므로
정확성이 깨지게 된다.
console.log(countUp2());//호출객체의 임시네임스페이스 count프로퍼티에 접근하여 값을가져옴
//함수를 객체로 보면 count는 프로퍼티이므로 다음과같이 접근하여 초기화가 가능하다.
countUp2.count = 0;
console.log(countUp2());//3이 아닌 0이 출력된다.
위와 같은 문제로 private의 기능을 흉내내기위해 클로저를 사용한다.
클로저는 함수내에 익명함수를 선언하여 해당함수를 통해서만 익명함수에 접근할수 있게하는기법으로
캡슐화가 가능하다. 클로저와 중단점을 활용한 클로저는 다음에 설명하기로 하겠다.
끝으로 어렵지 않지만 그 내부의 속성까지 이해하려면 좀 시간을 투자해야할듯하다.
단순히 arguments.length는 길이, callee는 애초에 기대하는 arguments 라고 하면 끝이지만
클로저 기법과, 고급자바스크립트 프로그래머가 되려한다면 심층적인부분이 필요하지 않을까?
출처 : http://uyeong.tistory.com/199

12 Replies to “JS : arguments배열과 arguments.callee”