안녕하세요.
오늘은 자바스크립트에서 사용하는 apply(), call(), bind()에 대해 알아보도록 하겠습니다.
들어가기 전에
자바스크립트의 강력함은 그 유연성에 있으며, 이 유연성의 핵심 요소 중 하나는 함수 콘텍스트입니다. 때로는 우리가 이 콘텍스트를 직접 제어해야 할 때가 있습니다. 이때 call(), apply(), bind()가 등장합니다. 이들은 함수 호출 방식과 this가 참조하는 대상을 조작할 수 있도록 하는 메서드입니다.
자바스크립트에서 this는 무엇일까요?
this는 함수 호출방식에 따라 동적으로 결정됩니다.
일반함수로 호출한 경우
Global 객체
Method로 호출할 경우
호출한 객체
생성자 함수를 호출할 경우
생성자 함수가 생성할 인스턴스
call() / apply() / bind()에서 호출할 경우
메서드에 첫번째 인수로 전달하는 객체
this를 예제와 함께 이해해 보기
function greet() {
console.log("안녕하세요, 저는 " + this.name + "입니다.");
}
const person = { name: "Poki" };
greet.call(person);
안녕하세요, 저는 Poki입니다.
여기서 this는 greet() 함수를 호출하는 객체를 참조합니다. 함수 내에서는 person 객체를 가리키며 person.name을 사용하게 됩니다.
예제와 함께 call(), apply(), bind() 알아보기
function calculateSize(sizeInfo) {
return this.width * this.height;
}
const sizeInfo = { width: 15, height: 10 };
const area = calculateSize(sizeInfo);
console.log(area);
NaN
왜 생각했던 결과 150이 나오지 않았을까요? 여기서 calculateSize()는 직접 호출되면서 이때의 this는 전역 객체(일반적으로 브라우저에서는 window 객체)가 되었기 때문입니다. 여기서는 width와 height 속성이 없으므로 (window.width, window.height) 결과는 NaN입니다.
call() 메서드 - Context를 명시적으로 실행하기
call()의 기본적인 사용법
functionName.call(thisArgument);
예제와 함께 보기
function calculateSize() {
return this.width * this.height;
}
const sizeInfo = { width: 15, height: 10 };
const area = calculateSize.call(sizeInfo);
console.log(area);
150
call() 메서드를 통해 sizeInfo의 객체를 함수에 전달하여 this가 이제 sizeInfo.width, sizeInfo.height 값을 참조하여 결괏값이 예상했던 150이 나오게 됩니다.
apply() 메서드 - 배열로 된 인수
apply()의 기본적인 사용법
functionName.apply(thisArgument, argumentsArray);
예제와 함께 보기
function calculateSize(width, height) {
console.log("this.width: " + this.width + " this.height:" + this.height);
console.log("width: " + width + " height:" + height);
return width * height;
}
const sizeInfo = { width: 15, height: 10 };
const area = calculateSize.apply(sizeInfo, [2, 4]);
console.log(area);
this.width: 15 this.height:10 width: 2 height:4 8
apply() 메서드를 통해 this에는 sizeInfo의 값을 전달하고, calculateSize()에는 배열에 담긴 값 [2, 4]가 각각 width, height 값으로 전달되어 계산됩니다.
bind() 메서드 - 바인딩
bind() 기본 사용법
functionName.bind(thisArgument);
예제와 함께 보기
function calculateSize() {
return this.width * this.height;
}
const area1 = calculateSize.bind({ width: 2, height: 4 });
const area2 = calculateSize.bind({ width: 3, height: 7 });
console.log(area1());
console.log(area2());
8 21
bind() 메서드를 통해 area1()은 width가 2, height가 4의 값이 this 값으로 바인딩되었고, area2()는 width가 3, height가 7이 this값으로 바인딩되었습니다. area1()과 area2()는 호출 때마다 같은 값을 출력하게 됩니다.
bind()의 특별한 기능 - 함수 커링(Currying)
커링(Currying)이란?
다중 인수 함수를 단일 인수 함수로 바꾸는 것
예제와 함께 이해하기
function add(x, y) {
return x + y;
}
const add5 = add.bind(null, 5);
console.log(add5(10));
console.log(add5(13));
15 18
결과에서 보인 것처럼 add() 함수는 x, y 두 개의 인수를 갖고 있습니다. add5에는 값을 1개만 지정하였습니다. 그럼 현재 add5의 상태는 어떠한 상태일까요? 현재 add5는 add(x=5, y)가 되어 있습니다. 즉, add5()에 값을 넣으면 그 값에 기본값으로 x에 고정된 5 값에 y값이 더해진 값이 결괏값으로 나오게 됩니다.
마치며
하나씩 뜯어서 보면 쉽지만 계속 헷갈리는 함수 콘텍스트를 제어할 수 있는 call(), apply(), bind()에 대해 알아보았습니다. 이를 통해 조금 더 유연하고 재사용 가능한 코드를 작성할 수 있게 되길 바랍니다.
긴 글 읽어주셔서 감사합니다.
레퍼런스
'Web > 지식창고' 카테고리의 다른 글
[Web/Javascript] 화살표 함수 vs 일반 함수 (0) | 2024.06.17 |
---|---|
[Web/Javascript] 프로토타입 (Prototype)에 대해서 (0) | 2024.06.17 |
[Web/Javascript] 클로저(Closure) 알아보기 (0) | 2024.06.17 |
[Web/Javascript] var, let, const 알아보기 (0) | 2024.06.17 |
[Web] 모바일 기기 Chrome DevTools 실시간 확인방법 (0) | 2024.06.17 |