[javascript] this
✅ 개념
- this는 자신이 속한 객체 또는 자신이 생성할 인스턴스를 가리키는 자기 참조 변수다.
- this를 통해 자신이 속한 객체 또는 자신이 생성할 인 스턴스의 프로퍼티나 메서드를 참조할 수 있다.
(자바스크립트 엔진에 의해 암묵적으로 생성, 코드 어디서든 참조 가능)
- this 바인딩은 함수 호출 방식에 의해 동적으로 결정된다.
✅ 간단한 예제
//1번 예제
const circle = {
// 프로퍼티: 객체 고유의 상태 데이터
radius:: 5,
getDiameter() {
return 2 * circle.radius
}
}
console.log(circle.getDiameter()); //10
// 2번 예제
const circle = {
// 프로퍼티: 객체 고유의 상태 데이터
radius:: 5,
getDiameter() {
return 2 * ????.radius
}
}
this를 사용한 예제
const circle = {
// 프로퍼티: 객체 고유의 상태 데이터
radius:: 5,
getDiameter() {
return 2 * this.radius
}
}
console.log(circle.getDiameter()); // 10
// this를 사용한 생성자 함수 예제
function Circle(radius){
this.radius = radius;
}
Circle.prototype.getDiamneter = function () {
return 2 * this.radius;
}
const circle = new Circle(5);
console.log(circle.getDiameter()); // 10
✅ this 바인딩은 함수 호출 방식, 함수가 어떻게 호출되었는지에 따라 동적으로 결정된다.
- 함수를 호출하는 방식은 다양하다
1. 일반 함수 호출
- 기본적으로 this에는 전역 객체 window가 바인딩 된다.
// 일반함수 호출 this 예제
function foo() {
console.log(this) // window
function bar() {
console.log(this) // window
}
bar()
}
foo();
// use strict모드의 일반함수 호출 this
function foo() {
'use strict';
console.log(this) // undefined
function bar() {
console.log(this) // undefined
}
bar()
}
foo();
2. 메소드 호출
- 메서드 내부의 this에는 메서드를 호출한 객체,
- 즉 메서드를 호출할 때 메서드 이름 앞의 마침표 연사자 앞에 기술한 객체가 바인딩 된다.
//1번 예제
const person = {
name: 'Lee',
getName(){
return this.name
}
}
//person이 바인딩 된다.
console.log(anotherPerson.getName()); // Lee
//2번 예제
const anotherPerson = {
name: 'Kim'
}
//anotherPerson이 바인딩된다.
anotherPerson.getName = person.getName;
console.log(anotherPerson.getName()); //kim
//3번 예제
const getName = person.getName();
// 일반 함수로 호출되었기 때문에 getName의 함수 내부의 this.name은 window.name이 된다.
// 현재 window.name은 없기에 기본값인 ''
// Node.js에서는 undefined
console.log(getName()); // ''
3. 생성자 함수 호출
- 생성자 함수 내부의 this에는 생성자 함수가 생성할 인스턴스가 바인딩 된다.
function Circle(radius){
this.radius = radius;
this.getDiameter = function(){
return 2 * this.raduis;
}
}
// 반지름이 5인 Circle 객체
const circle5 = new Circle(5);
// 반지름이 10인 Circle 객체
const circle10 = new Circle(10);
console.log(circle5.getDiameter()) // 10
console.log(circle10.getDiameter()) // 20
// but..
// new 연사자와 함께 생성자 함수를 호출하지 않으면 생성자 함수가 아니라 일반함수로 동작한다.
const circle3 = Circle(3);
console.log(circle3) // undefined
// 일반 함수로 호출된 Circle 내부의 this는 전역 객체를 가리킨다.
console.log(radius) //3
3. call, apply, bind
- 함수 호출 방식과 관계없이 this를 지정할 수 있음
- call 메소드는 모든 함수에서 사용할 수 있으며, this를 특정 값으로 지정할 수 있습니다.
const mike = {
name: 'mike'
}
function showThisName() {
console.log(this.name)
}
showThisName() // "" window.name은 빈값
showThisName.call(mike); // mike 나옴
function update(birthYear, occupation){
this.birthYear = birthYear;
this.occupation = occupation;
}
update.call(mike, 1999, "signer")
console.log(mike); // {birthYear: 1999, name: "mike", occupation: "signer"}
- apply는 함수 매개변수를 처리하는 방법을 제외하면 call과 완전히 같습니다.
- call은 일반적인 함수와 마찬가지로 매개변수를 직접 받지만, apply는 매개변수를 배열로 받는다.
// 1번 예시
const mike = {
name: 'mike'
}
function update(birthYear, occupation){
this.birthYear = birthYear;
this.occupation = occupation;
}
update.apply(mike, [1999, "signer"])
console.log(mike); // {birthYear: 1999, name: "mike", occupation: "signer"}
// 2번 예시
const nums = [3,10,1,6,4];
const minNum = Math.min.apply(null, nums);
// 이거와 같은 것들은
// const minNum = Math.min.call(3,10,1,6,4);
// const minNum = Math.min.call(...nums);
const maxNum = Math.max.apply(null, nums);
console.log(minNum);
console.log(maxNum);
- bind() 메소드가 호출되면 새로운 함수를 생성한다.
- 받게 되는 첫 인자의 value로는 this 키워드를 설정하고, 이어지는 인자들은 바인드 된 함수의 인수에 제공된다.
// 1번 예시
const module = {
x: 42,
getX: function() {
//this가 여기 있다
return this.x;
}
};
const unboundGetX = module.getX;
console.log(unboundGetX()); // The function gets invoked at the global scope
// undefined
const boundGetX = unboundGetX.bind(module);
console.log(boundGetX()); // 42
// 2번 예시
function list() {
return Array.prototype.slice.call(arguments);
}
const list1 = list(1, 2, 3); // [1, 2, 3]
// 선행될 인수를 설정하여 함수를 생성
const leadingThirtysevenList = list.bind(null, 37);
const list2 = leadingThirtysevenList(); // [37]
const list3 = leadingThirtysevenList(1, 2, 3); // [37, 1, 2, 3]
✅ 정리
- this는 자기 참조 변수이며, this 바인딩은 함수 호출 방식에 의해 동적으로 결정된다.(호출할 때마다 다르다)
- 크게 4가지로 보게 되면, 일반 함수, 메서드 호출, 생성자 함수, call, apply, bind를 호출할 때마다 다르게 바인딩한다.
출처:
모던 자바스크립트 Deep Dive 22장
https://www.youtube.com/watch?v=KfuyXQLFNW4
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Operators/this