[Effective javascript] 변수를 사용하여 argumentes의 참조를 저장하자

김범식·2023년 7월 6일
0

Effective JavaScript

목록 보기
2/33
post-thumbnail

javascript의 iterator 란?


반복 가능한 객체를 다루기 위해 사용되는 iterator(반복자) 입니다. iterator는 일련의 값을 순차적으로 반환할 수 있는 객체입니다. 이 객체는 next() 메소드를 가지며, 각 호출마다 값을 가진 객체를 반환합니다. 반환되는 객체는 {value, done} 입니다. value는 현제 반복 위치의 값이고, done은 반복이 완료 되었는지를 나타내는 boolean 값입니다.



Symbol.iterator

iterable(반복 가능한) 객체는 ‘Symbol.iterator’ 라는 특별한 메소드를 구현해 Iterator 객체를 반환합니다.

const arr = [1,2,3]

const iterator = arr[Symbol.iterator]();
console.log(iterator.next()}; //  { value : 1, done: false }
console.log(iterator.next()}; //  { value : 2, done: false }
console.log(iterator.next()}; //  { value : 3, done: false }
console.log(iterator.next()}; //  { value : undefined, done: true }

위 예시에서는 arr[Symbol.iterator]() 를 호출하여 배열 arr의 iterator객체를 얻습니다. 그리고 iterator.next()를 호출하여 iterator객체를 통해 순차적으로 값을 얻습니다. done의 참 거짓 여부를 통해 반복문이 완료됨을 알수도 있습니다.



for… of

for…of 를 사용해 Iterator루프를 편리하게 사용할 수 있습니다. for…of 루프는 자동으로 Iterable객체의 Iterator를 가져와 값을 반복합니다.

const arr = [1,2,3]

for(const value of arr){
	console.log(value);
}

각 요소를 순회하면서 value에 값을 할당하여 출력합니다.



변수를 사용하여 arguments의 참조를 저장하라


임의 숫자를 인자로 받고 그 값으로 이터레터를 만드는 편리함 함수를 만들고 싶다고 가정해봅시다.

var it = values(1,2,3,4,5,6,3,4) ;
it.next(); //1
it.next(); //2
it.next(); //3
it.next(); //4

values 함수는 인자가 몇개인지 관계없이 모두 받아들일 수 있어야 하므로 arguments 객체의 요소들을 열거하기 위해 다음과 같은 iterator 객체를 만들 것입니다.

function values(){
	var i = 0, n = arguments.length;
	return{
		haseNext:function(){
			return (i < n)
		},
		next:function(){
			if(i>=n){
				throw new Error("end of iterator");
			}else{
				return arguments[i++];//잘못된 arguments 
			}
		}
		
	}
}

다음 코드는 잘 못되었습니다. 실제로 실행해 보면

var it = values(1,2,3,4,5,6,3,4) ;
it.next(); // undefined
it.next(); // undefined
it.next(); // undefined
it.next(); // undefined

문제는 각 함수의 본문에서 새로운 arguments 변수가 암묵적으로 바인딩 된것이 문제 입니다. 이게 무슨 소리냐면 next 함수에서 사용된 arguments는 values함수의 arguments가 아니라 next의 arguments로 암묵적으로 바인딩 되었다는 말입니다.



해결방법

내가 사용할 arguments 객체를 지역변수에 담아 명시적으로 어느 arguments를 사용하는지 확실히 하면 됩니다.

function values(){
	var i = 0, n = arguments.length; **a = arguments**
	return{
		haseNext:function(){
			return (i < n)
		},
		next:function(){
			if(i>=n){
				throw new Error("end of iterator");
			}else{
				return **a[i++]**;
			}
		}
		
	}
}
var it = values(1,2,3,4,5,6,3,4) ;
it.next(); //1
it.next(); //2
it.next(); //3
it.next(); //4



기억할 점

  • arguments를 참조할 때 함수의 포함 관계에 주의하자
  • 다른 함수 안에 포함된 감싸인 함수에서 arguments를 참조하려면, 명시적으로 스코프가 정해진 arguments의 참조를 바인딩하자
profile
frontend developer

0개의 댓글