자바스크립트 딥다이브 북스터디 과정에서 array.map함수를 구현해볼 것을 추천했다. 그 이유는 프로토타입의 this바인딩을 익히고 콜백함수를 익히는데 아주 좋은 연습이라고 했다. 그 당시에는 바쁘기도 하고 이해가 잘 안되어 미뤄두었다가 이번 기회에 구현해보려고 한다.
map메서드는 Array프로토타입의 메서드이다. 즉, Array프로토타입을 갖고있는 값에만 적용할 수 있다. map() 메서드는 배열 내의 모든 요소 각각에 대하여 주어진 함수를 호출한 결과를 모아 새로운 배열을 반환한다. 무엇인가를 반환하기 때문에 값으로 평가되며 이 값은 다른 값으로 할당할 수 있다. 이것이 for문, forEach문과 가장 큰 차이점이라고 할 수 있다.
arr.map(callback(currentValue[, index[, array]])[, thisArg])
MDN 공식문서에 나와있는 map 메서드의 구성이다. currentValue빼고는 모두 생략 가능하다.
currentValue
: 처리할 현재 요소
index
: 처리할 현재 요소의 인덱스.
array
: map()을 호출한 배열.
thisArg
: callback을 실행할 때 this로 사용되는 값.
thisArg
? 좀 생소한 매개변수였다. 왜 나는 그 동안 이 매개변수를 못봤을까? 답은 화살표 함수에 있다.
화살표함수의 큰 특징 중 하나는 화살표함수의 this는 자신의 상위 프로토타입체인을 바라본다. 화살표함수는 this바인딩이 되어있지 않기 때문이다.
const arr = [1,2,3]
const myMap = arr.map((v) => v + 1)
console.log(myMap) // [2,3,4]
이 코드에서는 thisArg 매개변수가 들어가지 않았다. 왜냐하면 콜백과 화살표함수가 그 역할을 대신하기 때문이다. 콜백함수의 매개변수 currentValue
를 v
로 받고 화살표함수(콜백함수)는 외부의 this
를 찾는다. 즉 외부의 this
는 arr
이므로 arr
의 callaback
을 실행할 때 this
로 사용되는 값을 v
로 자동으로 바인딩 시켰다.
항상 해당 메서드를 사용할떄는 화살표함수가 국룰처럼 사용했기 때문에 thisArg
가 바인딩 되는지도 몰랐던 것이다. 그렇다면 해당 식을 화살표 함수가 아닌 일반함수를 콜백함수로 사용하면
const arr = [1,2,3]
const myMap = arr.map(function(v){
return v + this
}, 1)
console.log(myMap) // [2,3,4]
해당 로직으로 바꿀 수 있다.
const customMap = function (callback, thisArg) {
const array = [];
for (const key in this) {
if (Number.isInteger(Number(key))) {
array[key] = callback.bind(thisArg)(this[key], key, this);
} else {
console.error("Invalid key type encountered");
return;
}
}
return array;
};
Array.prototype.customMap = customMap;
console.log([0, 2, 3].customMap((v) => v));
첫번째 매개변수는 콜백함수를 받아서 순회하면서 어떤 값을 반환할지 정하고 두번째 매개변수는 callback
을 실행할 때 this
로 사용될 값을 넣어주었다.
반환될 빈 배열을 array
를 선언해준다.
for...in
반복문을 통해 key
값을 받는다.
key
값은 문자열이기 때문에 숫자로 타입을 변환하고 truethy
값일 경우 반복문을 실행한다.
어처피 순서대로 순환하기 때문에 array[key]
에 순서대로 값을 할당한다.
callback
매개변수는 함수를 받을 것이기 때문에 함수 객체의 bind
메서드를 사용할 수 있다. callback
에서 사용될 this
를 thisArg
로 명시적으로 변환한다.
bind
가 실행된 후에 this
의 매개변수들을 뒤에 그룹연산자로 붙여준다.
this[key]
는 map의 첫번째 매개변수로 현재 순회하는 값을 표현한다.
key
는 map의 두번째 매개변수로 현재 순회하는 인덱싱을 표현한다.
this
는 함수를 호출한 변수를 가리킨다.
Array.prototype
프로퍼티에 명시적으로 할당해준다.
출력해보면 짜자잔
그냥 간단하게 반복문 돌리는거 아니야? 라고 생각했던 나에게 현실은 실전인 것을 깨닫게 해주는 과제였다. bind
와 this
에 대한 이해를 한걸음 나아갈 수 있는 계기가 되었다.