this 란?
javascript에서 함수의 this
키워드는 다른언어 들과 비교하여 조금 다르게 동작한다. 또한 strict mode
와 non-strict node
사이에서도 조금 다르다.
대부분의 경우, this
의 값은 함수를 호추하는 방법에 의해 결정된다. 실행하는 동안의 할당에 의해 설정될 수 없고, 함수가 호출될 때 마다 다를 수 있다. ES5는 함수의 this
값이 함수가 어떻게 호출되었는지 개의치 않고 설정할 수 있는 bind
메소드를 소개했다.
this의 이해
this
의 값은 어떻게 변화할까? this
가 어떤 값과 연결되는 지는 this
의 바인딩을 통해서 확인해 볼 수 있다. 바인딩이란 this
의 호출 방식에 따라서 this
가 특정 '객체'에 연결되는 것이다. this
의 바인딩은 일반 함수 내부, 메서드 내부, 생성자 함수 내부, call
, Apply
,Bind
를 통한 '호출 방식'으로 나눠서 살펴볼 수 있다.
- 일반 함수 내부에서의
this
는 글로벌 객체와 바인딩 된다. - 메서드 내부에서의
this
는 메서드를 호출한 객체와 바인딩 된다. - 생성자 함수 내부에서의
this
는 생성자 함수가 생성할 인스턴스와 바인딩 된다. - Call, Apply, Bind메서드 사용 시, 메서드에 첫 번째 인수로 전달하는 객체에 바인딩 된다.
일반 함수 내부에서의 this는 글로벌 객체와 바인딩 된다.
console.log(this === window); // true
a = 30;
console.log(window.a); // 30
function x() {
return this;
}
x() === window; // true
메서드 내부에서의 this는 메서드를 호출한 객체와 바인딩 된다.
let kim = {
firstName: "BS",
lastName: "Kim",
driveCar() {
console.log(`${this.firstName} drives a car`);
},
};
kim.driveCar(); // "BS drives a car"
생성자 함수 내부에서 this는 생성자 함수가 생성할 인스턴스와 바인딩 된다.
function person() {
this.firstName = "BS";
this.lastName = "Kim";
this.start = function () {
console.log(`${this.firstName} drives a car.`);
};
}
let person1 = new person();
console.log(person1); // person { firstName: 'Ryan', lastName: 'Kim', start: ƒ (), __proto__: person { constructor: ƒ person() } }
Call, Apply, Bind 메서드 사용 시, 메서드에 첫 번째 인수로 전달하는 객체에 바인딩 된다.
Call
과 Apply
메서드는 기본적으로 함수를 호출하는 역할을 한다. 그렇다면 기존 함수 호출과 차이점은 무엇일까? 그것은 바로 해당 메서드를 사용해 함수를 '실행'하면, 함수의 첫 번재 인자로 전달하는 객체에 this
를 '바인딩'할 수 있다는 것이다. 이를 통해서 유사 배열 arguments
객체에 배열 메서드를 사용할 수 있다. 반면에, bind
는 첫 번째 인자를 this
에 바인딩 하지만 함수를 실행하지 않으며, 새로운 함수를 반환한다.
- Call :
Call
을 사용하면, 함수를 실행하고 함수의 첫 번재 인자로 전달하는 값에this
를 바인딩 한다.
function logName(a, b, c) {
console.log(this.name);
console.log(this.nationality);
console.log(a + b + c);
}
const person = {
name: "BS",
nationality: "South Korea",
};
logName.call(person, 1, 2, 3);
// "BS"
// "South Korea"
// 6
- Apply :
Apply
를 사용하면 함수를 실행하고 함수의 첫 번째 인자로 전달하는 값에this
를 바인딩 한다.call
과의 차이점은 인자를 배열의 형태로 전달하는 것이다. 이 때, 인자로 배열 자체가 전달하는 것이 아니라 배열의 요소들이 값으로 전달된다.
function logName(a, b, c) {
console.log(this.name);
console.log(this.nationality);
console.log(a + b + c);
}
const person = {
name: "BS",
nationality: "South Korea",
};
const nums = [1, 2, 3];
logName.apply(person, nums);
// 'BS'
// 'South Korea'
// 6
// 요즘에는 apply를 사용하지 않고, spread operator와 call을 활용한다.
logName.call(person, ...nums);
// 'BS'
// 'South Korea'
// 6
- Bind :
Bind
는 함수의 첫 번째 인자에this
를 바인딩한다는 점은 같지만, 함수를 실행하지 않고, 새로운 함수를 반환한다. 즉, 반환된 새로운 함수를 실행해야 원본 함수가 실행된다.
function logName(a, b, c) {
console.log(this.name);
console.log(this.nationality);
console.log(a + b + c);
}
const person = {
name: "BS",
nationality: "South Korea",
};
const BS = logName.bind(person, 1); // 새로운 함수
BS(2, 3);
// 'BS'
// 'South Korea'
// 6
Call, Apply, Bind 메서드 정리
Call
메서드는 함수를 실행하고, 첫 번째 인자에this
를 바인딩하며, 이후의 값을 함수의 인자로 전달한다.Apply
메서드는 함수를 실행하고, 첫 번째 인자에this
를 바인딩 하며, 이후의 값을 배열의 형태로 받아 차례로 함수의 인자로 전달한다.bind
메서드는 함수를 실행하지 않으며, 첫 번재 인자에this
를 바인딩한 새로운 함수를 반환한다. 각 메서드를 통해 전달할 수 있는 인자의 갯수에는 제한이 없다.
this 정리
이처럼 this
는 함수 호출 방식에 다라서 동적으로 결정된다. 예시에서 살펴본 것처럼 함수를 일반 함수로 호출할 경우, this
는 글로벌 객체를, 메서드로 호출할 경우 이를 호출한 객체를, 생성자 함수를 호출할 경우, 생성자 함수가 생성할 인스턴스를 가리키게 된다. Call
, Apply
, Bind
메서드 사용 시, 메서드에 첫 번재 인수로 전달하는 객체에 바인딩 된다.
'JAVASCRIPT' 카테고리의 다른 글
[JS][네이티브] 내부 [[Class]] (0) | 2022.01.27 |
---|---|
[JS][네이티브] 네이티브 개요 (0) | 2022.01.27 |
[JS][값][마무리] 값 vs 레퍼런스 (0) | 2022.01.26 |
[JS][값] 특수 값 (0) | 2022.01.26 |
[JS][값] 숫자 (0) | 2022.01.25 |
댓글