티스토리 뷰
자기 참조 변수 🤔
new 키워드를 통해 생성자를 호출하면, 암묵적으로 자기 자신을 가리키는 this가 제공됩니다.
이러한 용도를 지닌 식별자를 자기 참조 변수(self-referencing variable)라 부릅니다.
자바스크립트에서는 this가 가리키는 값이 호출 방식에 따라 동적으로 결정됩니다.
TYI - 바인딩: 식별자와 값(메모리 공간의 주소)을 연결하는 과정을 의미합니다.
함수 호출 방식에 따른 this 바인딩 ✏️
함수는 다양한 방식으로 호출할 수 있으며, 방식에 따라 this가 가리키는 값이 다릅니다.
const foo = function () {
console.log(this);
};
foo(); // window
new foo(); // foo {}
const obj = { foo };
obj.foo(); // obj
함수를 일반적인 방식으로 호출한다면, this는 함수가 어떻게 중첩되어 있든 모두 전역 객체(window)를 가리킵니다. 그 외에 메소드나 생성자를 통해 호출할 때는 생성된 객체를 제대로 가리킵니다. 함수형 프로그래밍에서는 함수 단위로 로직을 설계할 때, 콜백(callback)과 같은 보조 함수를 많이 사용하게 되는데 함수를 호출할 때 this가 전역 객체를 가리킨다면 문제가 될 수 있습니다. 따라서 스코프 내부에서는 항상 같은 객체를 가리킬 수 있도록 맞춰줄 필요가 있습니다.
함수 프로토타입의 메소드인 call, apply, bind를 사용해서 가리키고 있는 값을 명시적으로 지정할 수 있습니다.
const obj = {
x: 123,
foo() {
setTimeout(function () {
console.log(this.x);
}.bind(this), 100);
},
};
obj.foo();
이 외에도 내부의 this가 항상 상위 스코프의 this를 가리키는 화살표 함수를 사용해서 해결할 수 있습니다.
const obj = {
x: 123,
foo() {
setTimeout(() => {
console.log(this.x);
}, 100);
},
};
obj.foo();
call, apply, bind 메소드 사용법 탐구하기 ✏️
call, apply, bind 이 3개의 메소드는 this 바인딩과 관련된 Function.prototype의 메소드입니다.
interface Function {
// typescript
apply(this: Function, thisArg: any, argArray?: any): any;
call(this: Function, thisArg: any, ...argArray: any[]): any;
bind(this: Function, thisArg: any, ...argArray: any[]): any;
...
}
call과 apply는 본질적으로 함수 호출의 목적을 지니고 있으며, 첫 번째 인자로 바인딩할 객체를 지정할 수 있습니다.
function getThis() {
console.log(arguments);
return this;
}
const obj = { x: 123 };
// [Arguments] {}
// window
console.log(getThis());
// [Arguments] { '0': 1, '1': 2, '2': 3 }
// { x: 123 }
console.log(getThis.apply(obj, [1, 2, 3]));
// [Arguments] { '0': 1, '1': 2, '2': 3 }
// { x: 123 }
console.log(getThis.call(obj, 1, 2, 3));
두 메소드는 인자를 전달하는 방식에만 차이를 가지고 있습니다. 그리고 이 메소드들을 사용하는 대표적인 상황은 유사 배열 객체(Array-like object)를 다룰 때입니다. 유사 배열 객체는 length 프로퍼티를 지니고 있어 반복문을 통해 요소를 순회할 수는 있지만, 실질적으로 배열 관련 메소드는 사용할 수 없는 것을 지칭합니다.
유사 배열인 arguments 객체는 배열 메소드를 사용할 수 없는데, apply나 call과 함께라면 가능합니다.
function argsToArray() {
const newArray = Array.prototype.slice.call(arguments);
return newArray;
}
// [1, 2, 3]
console.log(argsToArray(1, 2, 3));
마지막으로 소개할 bind 메소드는 단순히 this 바인딩 대상만 변경하는 메소드입니다. call, apply 메소드와 달리 기본적으로 함수를 호출하지 않기 때문에, 호출하고자 한다면 명시적으로 뒤에 ()를 붙여야 합니다.
function getThis() {
console.log(arguments);
return this;
}
const obj = { x: 123 };
// [Arguments] {}
// { x: 123 }
console.log(getThis.bind(obj)());
'Tech Stack > 자바스크립트' 카테고리의 다른 글
문자열 속의 패턴을 찾는 방법, 정규 표현식 (0) | 2021.05.14 |
---|---|
배열을 다룰 때 내가 주로 사용하는 방법 (0) | 2021.05.14 |
strict mode (0) | 2021.05.12 |
호이스팅 (Hoisting) (0) | 2021.05.11 |
단축 평가 (Short-circuit Evaluation) (0) | 2021.05.11 |