일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 |
- 제어컴포넌트
- 조건부스타일
- accordian
- createPortal
- ?? #null병합연산자
- 부모패딩
- CustomHook
- 문제해결
- 부모요소의 패딩 무시
- parent padding
- 이즐 #ezl #욕나오는 #교통카드
- tailwindCSS
- 함수형프로그래밍
- ignore padding
- BFC
- DOM
- react
- vite
- es6
- alias설정
- Carousel
- 서초구보건소 #무료CPR교육
- debouncing
- BlockFormattingContext
- transition
- QueryClient
- useQueryClient
- 리액트
- twoarrow
- 화살표2개
- Today
- Total
프론트엔드 첫걸음
forEach(parent.appendChild.bind(parent)) 이해하기 본문
개요
김민태 React 강의를 보다가 DOM을 추가하는 코드에서 forEach(bind()) 부분이 이해되지 않았다. 처음에는 forEach(child => parent.appendChild(child))는 이해가 됐는데, forEach(parent.appendChild.bind(parent))가 같은 동작을 한다는 점이 납득되지 않았다. 그래서 이 부분을 공부한 내용을 정리해 본다.
function createDOM(vdom) {
const element = document.createElement(vdom.tag); // element가 생성됨
vdom.children
.map(createDOM) // 각 자식 요소를 재귀적으로 DOM 요소로 변환
.forEach(element.appendChild.bind(element)); //변환된 요소들을 부모에 추가
return element; //현재 노드를 반환 → 이게 상위 노드의 자식이 됨
}
const vdom = {
tag: 'p',
children: [
{
tag: 'h1',
children: ["React 만들기"],
},
],
};
const rootElement = createDOM(vdom);
document.querySelector('#root').appendChild(rootElement);
forEach 함수의 특징
forEach는 내부적으로 배열 요소를 콜백 함수의 첫 번째 인자로 전달한다.
array.forEach(callback);
이 코드에서 callback 함수는 item을 매개변수로 받게 된다.
예제
아래 두 코드는 같은 동작을 한다.
const items = ["A", "B", "C"];
items.forEach(console.log);
const items = ["A", "B", "C"];
items.forEach(item => console.log(item));
두 번째 코드는 item을 명시적으로 전달했지만, 첫 번째 코드에서도 forEach()가 내부적으로 배열 요소를 console.log()의 첫 번째 인자로 넘겨준다.
실행 결과:
A B ["A", "B", "C"]
B 1 ["A", "B", "C"]
C 2 ["A", "B", "C"]
이는 console.log가 기본적으로 여러 개의 인자를 받을 수 있기 때문이다. forEach는 (item, index, array) 세 개의 값을 넘겨주기 때문에 console.log에 의해 인덱스와 전체 배열까지 출력된다.
즉, forEach는 내부적으로 item을 자동으로 넘겨준다. 이것이 forEach(parent.appendChild.bind(parent))가 동작하는 핵심 원리다.
bind()를 사용하여 this를 고정
appendChild는 this가 필요하다.
appendChild는 this가 부모 요소를 가리켜야 정상적으로 실행된다.
하지만, forEach(parent.appendChild)를 직접 실행하면 오류가 발생한다.
bind 없이 실행하면 오류 발생
const parent = document.createElement("div");
const child1 = document.createElement("p");
const child2 = document.createElement("span");
[parent, child1, child2].forEach(parent.appendChild); // 오류 발생!
이렇게 하면 appendChild의 this가 parent가 아니라 window나 undefined가 되어서 실행되지 않는다.
bind(parent)로 this 고정
const parent = document.createElement("div");
const child1 = document.createElement("p");
const child2 = document.createElement("span");
[child1, child2].forEach(parent.appendChild.bind(parent));
이제 내부적으로 실행되는 동작은 다음과 같다:
parent.appendChild(child1);
parent.appendChild(child2);
즉, bind(parent)를 하면 this가 parent로 고정되어 올바르게 실행된다.
예시
// 부모 요소 생성
const parent = document.createElement("div");
// 자식 요소 생성
const child1 = document.createElement("p");
const child2 = document.createElement("span");
// 방법 1: 일반적인 forEach 사용
[child1, child2].forEach(child => parent.appendChild(child));
// 방법 2: bind 사용
[child1, child2].forEach(parent.appendChild.bind(parent));
// 결과 확인
console.log(parent.outerHTML);
실행 결과
<div>
<p></p>
<span></span>
</div>
두 방법 모두 같은 결과를 만들어냄을 확인할 수 있다.
결론
- forEach()는 배열 요소를 자동으로 callback의 첫 번째 인자로 전달한다.
- bind(parent)를 사용하면 this를 parent로 고정할 수 있다.
- 결국 forEach(child => parent.appendChild(child))와 forEach(parent.appendChild.bind(parent))는 같은 동작을 한다.
이제 forEach(bind())가 왜 동작하는지 확실히 이해되었다.
화살표 함수는 상위 스코프의 this를 그대로 사용하기 때문에 bind 안해줘도 된다.
나라면 .forEach(child => element.appendChild(child)); 했을 것 같다.
'개발 공부 > React' 카테고리의 다른 글
useLocation (0) | 2023.07.18 |
---|---|
김민태 프론트엔드 강의 - React 만들기 (0) | 2023.03.11 |
[칼럼] React 컴포넌트를 커스텀 훅으로 제공하기 (0) | 2023.02.22 |
QueryClient 대신 useQueryClient 사용하는 이유 (0) | 2023.02.20 |
map으로 순회하는 component마다 ref 를 달 때 (0) | 2023.01.10 |