만일 다음과 같은 코드가 있다면,
const str = 'abcde';
[...str].map((e)=>console.log(e));
[...str].forEach((e)=>console.log(e));
map을 이용한 출력문과 forEach를 이용한 출력문은 각각 같은 결과를 낼 것이다.
a
b
c
d
e
여기에 쓰인 스프레드 연산자, map 함수, forEach 함수는 자바스크립트 개발에서 아주 유용하게 쓰이는 것들이다.
iterable은 '반복 가능'하다는 뜻이다. 자바스크립트에서는 주로 for .. of 루프로 내부 요소를 순회할 수 있는 객체를 모두 이터러블 객체라고 부른다. 정확히 얘기하면 Symbol.iterator 메서드를 갖고있는 객체들이다.
이 Symbole.iterator 메서드는 이터레이터(iterator) 객체를 반환하며, 이는 next() 메서드를 가진다. 이 next() 메서드는 { value, done } 형태의 객체를 반환하는데, value는 다음값이고, done은 반복이 끝났는지 여부를 나타낸다. 연결리스트 구현과 비슷하다. 스프레드 연산자는 해당 메서드를 호출하여 이터레이터를 가져오며, next() 메서드를 반복 호출하여 객체의 각 요소에 접근한다.
이터러블 객체의 예시는 다음과 같다. 모두 각 내부 요소를 순차적으로 접근할 수 있는 객체들이다.
스프레드 연산자는 다음과 같이 함수의 인자로 넘겨줄 때도 사용할 수 있다.
function sum(x, y, z) {
return x + y + z;
}
const numbers = [1, 2, 3];
console.log(sum(...numbers));
// Expected output: 6
const chars = ['a', 'b', 'c'];
console.log(sum(...chars));
// Expected output: abc
이 메서드들의 풀네임(?)은 Array.prototype.forEach와 Array.prototype.map 이다.
이 둘은 모두 배열의 각 요소에 대해 함수를 실행시키는 메서드이다.
위의 예시 정도의 간단한 상황에서는 같은 결과를 가져오지만, 두 메서드는 사용 목적과 반환 값이 다르다.
간단히 정리하면, return이 필요하면 map, return 값이 필요 없으면 forEach 를 쓰면 된다.
동작 구조를 이해하는데 있어서, 내부 코드를 살펴보는 것만한게 없음을 경험적으로 알고있다.
Array.prototype.forEach와 Array.prototype.map 메서드의 내부 구현은 자바스크립트 엔진에 따라 다르지만, 대략적으로 동작을 모방하기 위해서는 다음 정도의 코드면 충분하다. (실제 V8 엔진 등에서는 성능 최적화나, 예외 처리 등을 포함하여 더 복잡한 형태를 띄고있다.)
fake_ForEach = function(callback) {
for (let i = 0; i < this.length; i++) {
callback(this[i], i, this); // callback(각 요소, 해당 요소의 index, 배열 자체)
}
}
fake_Map = function(callback) {
let result = [];
for (let i = 0; i < this.length; i++) {
result.push(callback(this[i], i, this));
}
return result;
}
처음에 봤던 가장 간단한 예시를 대입해서 생각해보자.
const str = 'abcde';
[...str].map((e)=>console.log(e));
[...str].forEach((e)=>console.log(e));
JavaScript | 실행 컨텍스트 (1) - 실행 컨텍스트, 호이스팅, 스코프 (0) | 2024.03.26 |
---|---|
가비지 컬렉션(Garbage Collection) (0) | 2024.03.24 |
JavaScript | JS 엔진과 런타임 환경의 구조 (스택, 힙, 이벤트루프 ..) (0) | 2024.01.04 |
JavaScript | 비동기 처리 | async & await 키워드 (1) | 2024.01.01 |
JavaScript | 비동기 처리 | Promise 객체 (0) | 2024.01.01 |