Skip to main content

Command Palette

Search for a command to run...

this, call, apply, bind

Updated
View as Markdown
this, call, apply, bind

this가 결정되는 시점

this는 기본적으로 실행 컨텍스트가 생성될 때 함께 결정됩니다. 실행 컨텍스트는 함수를 호출할 때 생성되므로, 바꿔 말하면 this는 함수를 호출할 때 결정된다고 할 수 있습니다.

함수와 메서드의 차이

함수는 그 자체로 독립적인 기능을 수행하는 반면, 메서드는 자신을 호출한 대상 객체에 관한 동작을 수행합니다. 흔히 메서드를 ‘객체의 프로퍼티에 할당된 함수’로 이해하지만 객체의 메서드로서 호출할 경우에만 메서드로 동작하고, 그렇지 않으면 함수로 동작합니다.

메서드로서 호출할 때 그 메서드 내부에서의 this가 가리키는 대상

this에는 호출한 주체에 대한 정보가 담깁니다. 어떤 함수를 메서드로 호출하는 경우 호출 주체는 바로 함수명(프로퍼티명) 앞의 객체입니다. 점 표기법의 경우 마지막 점 앞에 명시된 객체가 곧 this가 되는 것입니다.

함수로서 호출할 때 그 함수 내부에서의 this가 가리키는 대상

어떤 함수를 함수로서 호출할 경우에는 this가 지정되지 않습니다. this가 지정되지 않은 경우 this는 전역 객체를 바라보게 됩니다. 따라서 함수에서의 this는 전역 객체를 가리킵니다.

메서드의 내부함수에서의 this가 가리키는 대상

메서드 내부함수를 함수로서 호출할 수도 있고 메서드로서 호출할 수도 있습니다. this 바인딩에 관해서는 함수를 실행하는 당시의 주변 환경(메서드 내부인지, 함수 내부인지 등)은 중요하지 않고, 오직 해당 함수를 호출하는 구문 앞에 점 또는 대괄호 표기가 있는지 없는지가 관건입니다.

메서드 내부 함수에서의 this를 우회하는 방법

내부 함수의 상위 스코프에서 self라는 변수에 this를 저장한 이후 내부 함수에서 사용하는 방식이 있습니다.

화살표 함수의 this

함수 내부에서 this가 전역 객체를 바라보는 문제를 보완하고자 ES6에서는 this를 바인딩하지 않는 화살표 함수를 도입했습니다. 화살표 함수는 실행 컨텍스트를 생성할 때 this 바인딩 과정 자체가 빠지게 되어, 상위 스코프의 this를 그대로 활용할 수 있습니다.

콜백 함수 호출 시 그 함수 내부에서의 this가 가리키는 대상

콜백함수도 함수이기 때문에 기본적으로 this가 전역객체를 참조하지만, 제어권을 받은 함수에서 콜백 함수에 별도로 this가 될 대상을 지정한 경우엔 그 대상을 참조하게 됩니다.

// (1) 전역 객체 출력: 대상이 될 this를 지정하지 않음
setTimeout(function () { console.log(this); }, 300); 

// (2) 전역 객체 출력: 대상이 될 this를 지정하지 않음
[1, 2, 3, 4, 5].forEach(function (x) { // (2)
    console.log(this, x);
});

// (3) elements 출력: addEventListener 메서드는 콜백함수를 호출할 때 자신의 this를 상속하도록 되어 있음.
document.body.innerHTML += '<button id="a">클릭</button>';
document.body.querySelector('#a')
    .addEventListener('click', function (e) { // (3)
        console.log(this, e);
    });

생성자 함수 내부에서의 this가 가리키는 대상

자바스크립트는 함수에 생성자로서의 역할을 함께 부여했기 때문에 new 명령어와 함께 함수를 호출하면 해당 함수가 생성자로서 동작하게 됩니다. 그리고 어떤 함수가 생성자 함수로서 호출된 경우 내부에서의 this는 곧 새로 만들 인스턴스 자신이 됩니다.

명시적으로 this를 바인딩하는 방법

메서드도 마찬가지로 임의의 객체를 this로 지정할 수 있습니다.

call 메서드와 apply 메서드의 차이점

apply 메서드는 call 메서드와 기능적으로 완전히 동일한데, 메서드의 호출 주체인 함수를 즉시 실행시키는 역할을 수행합니다. call 메서드는 첫 번째 인자를 this로 바인딩하고 나머지 모든 인자들을 호출할 함수의 매개변수로 지정하는 반면, apply 메서드는 두 번째 인자를 배열로 받아 그 배열의 요소들을 호출할 함수의 매개변수로 지정한다는 점에서만 차이가 있습니다.

bind 메서드

bind 메서드는 ES5에서 추가된 기능으로, call과 비슷하지만 즉시 호출하지는 않고 넘겨받은 this 및 인수들을 바탕으로 새로운 함수를 반환하기만 하는 메서드입니다. 다시 새로운 함수를 호출할 때 인수를 넘기면 그 인수들은 기존 bind 메서드를 호출할 때 전달했던 인수들의 뒤에 이어서 등록됩니다. 즉 bind 메서드는 함수에 this를 미리 적용하는 것과 부분 함수를 구현하는 두 가지 목적을 모두 지닙니다.

유사배열객체에 배열 메서드를 적용하려면?

var obj = {
    0: 'a',
    1: 'b',
    2: 'c',
    length: 3
}

Array.prototype.push.call(obj, 'd')
console.log(obj); // { 0: 'a', 1: 'b', 2: 'c', 3: 'd', length: 4 }

var arr = Array.prototype.slice.call(obj);
// slice 메서드에 매개변수를 넘기지 않으면 원본의 얕은 복사본을 반환함
console.log(arr); // [ 'a', 'b', 'c', 'd' ]

객체에는 배열 메서드를 직접 적용할 수 없지만 유사배열객체의 경우 call 또는 apply 메서드를 이용해 배열 메서드를 차용할 수 있습니다. 함수 내부에서 접근할 수 있는 arguments 객체 혹은 NodeList도 유사배열객체이므로 위의 방법으로 배열로 전환해서 활용할 수 있습니다. 문자열의 경우 length 프로퍼티가 읽기 전용이기 때문에 원본 문자열에 변경을 가하는 메서드(push, pop, shift, splice 등)는 에러를 던집니다.

사실 call/apply를 이용해 형변환하는 것은 ‘this를 원하는 값으로 지정해서 호출한다’라는 본래 메서드의 의도와는 다소 동떨어진 활용법이라 할 수 있습니다. 이에 ES6에서는 유사배열객체 또는 순회 가능한 모든 종류의 데이터 타입을 배열로 전환하는 Array.from 메서드를 새로 도입했습니다.

여러 인수를 묶어 하나의 배열로 전달하는 방법

apply 메서드를 사용하면 여러 인수를 묶어 하나의 배열로 전달할 수 있습니다. ES6에서는 펼치기 연산자(spread operator)를 이용하면 더욱 간편하게 작성할 수 있습니다.

bind 메서드의 name 프로퍼티

bind 메서드를 적용해서 새로 만든 함수는 한 가지 독특한 성질이 있습니다. name 프로퍼티에 동사 bind의 수동태인 ‘bound’라는 접두어가 붙는다는 점입니다. 어떤 함수의 name 프로퍼티가 'bound xxx'라면 이는 곧 함수명이 xxx인 원본 함수에 bind 메서드를 적용한 새로운 함수라는 의미가 되므로 기존의 call이나 apply보다 코드를 추적하기에 더 수월해진 면이 있습니다.

상위 컨텍스트의 this를 내부함수나 콜백함수에 전달하는 방법

self 등의 변수를 활용한 우회법과 더불어 call, apply, bind 메서드를 이용하는 방법이 있습니다. 또한 콜백 함수에 대해서도 bind 메서드를 이용하면 this 값을 사용자의 입맛에 맞게 바꿀 수 있습니다.

More from this blog

이터레이션/이터러블/이터레이터

이터레이션 프로토콜 (Iteration protocols) 순회할 수 있는 데이터 컬렉션(배열, 문자열, 유사 배열 객체, DOM 컬렉션 등)을 만들기 위해 ES6에서 도입한 규칙입니다. ES6 이전에도 순회 가능한 데이터 컬렉션들은 통일된 규약 없이 각자 나름의 구조를 가지고 for 문, for...in 문, forEach 메서드 등 다양한 방법으로 순회할 수 있었습니다. 하지만 ES6에서 순회 가능한 데이터 컬렉션을 이터레이션 프로토콜을 준...

Apr 3, 2023
이터레이션/이터러블/이터레이터

자바스크립트의 함수는 일급 객체

일급 객체란 일급 객체란 다른 객체들에 일반적으로 적용 가능한 연산을 모두 지원하는 객체입니다. 다음과 같은 조건을 만족하는 객체를 일급 객체라 합니다. 무명의 리터럴로 생성할 수 있다. 즉, 런타임에 생성이 가능하다 변수나 자료구조(객체, 배열 등)에 저장할 수 있다 함수의 매개변수에 전달할 수 있다 함수의 반환값으로 사용할 수 있다 자바스크립트의 함수는 위의 조건을 모두 만족하므로 일급 객체입니다. // 1. 함수는 무명의 리터럴...

Feb 21, 2023
자바스크립트의 함수는 일급 객체

클로저 Closure

클로저 어떤 함수 A에서 선언한 변수 a를 참조하는 내부함수 B를 외부로 전달할 경우 A의 실행 컨텍스트가 종료된 이후에도 변수 a가 사라지지 않는 현상을 말합니다. 다른 표현들 함수를 선언할 때 만들어지는 유효범위가 사라진 후에도 호출할 수 있는 함수 이미 생명 주기가 끝난 외부 함수의 변수를 참조하는 함수 자신이 생성될 때의 스코프에서 알 수 있었던 변수들 중 언젠가 자신이 실행될 때 사용할 변수들만을 기억하여 유지시키는 함수 va...

Dec 12, 2022
클로저 Closure

콜백 함수 Callback function

콜백함수 다른 코드(함수 또는 메서드)에게 인자로 넘겨줌으로써 그 제어권도 함께 위임한 함수입니다. 콜백 함수를 위임받은 코드는 자체적인 내부 로직에 의해 이 콜백 함수를 적절한 시점에 실행할 것입니다. 콜백 함수 내부에서 this가 가리키는 대상 콜백 함수도 함수이기 때문에 기본적으로는 this가 전역객체를 참조하지만, 제어권을 넘겨받을 코드에서 콜백 함수에 별도로 this가 될 대상을 지정한 경우에는 그 대상을 참조하게 됩니다. setTim...

Dec 12, 2022
콜백 함수 Callback function

EuiJin's blog

10 posts

프론트엔드 개발자