대부분의 경우 this의 값은 함수를 호출한 방법에 의해 결정됩니다.
객체는 상태를 나타내는 프로퍼티와 동작을 나타내는 메서드를 하나의 논리적 단위로 묶은 복합적인 자료구조이다.
동작을 나타내는 메서드는 자신이 속한 객체의 상태, 즉 프로퍼티를 참조하고 변경할 수 있어야 한다. 자신이 속한 객체의 프로퍼티를 참조하려면 자신이 속한 객체를 가리키는 식별자를 참조할 수 있어야 한다.
기본적으로 this에는 전역 객체가 바인딩된다.
function order() {
console.log(this);
function count() {
console.log(this);
}
count();
}
order();
전역함수와 중첩 함수를 일반 함수로 호출하면 함수 내부의 this에는 전역 객체인 window가 바인딩된다. this는 객체의 프로퍼티나 메서드를 참조하기 위한 자기 참조 변수이므로 객체를 생성하지 않은 일반함수에서는 this는 아무런 의미를 가지지 않는다.
use strict
는 더 엄격한 문법 및 에러 처리를 적용하여 코드의 안전성을 높인다.
function order() {
'use strict';
console.log(this); // undefined
function count() {
console.log(this); // undefined
}
count();
}
order();
함수 내부의 this값은 전역 객체(window 객체 또는 global 객체)가 아닌 undefined
가 된다. 이는 this를 의도치 않게 전역 객체에 바인딩되는 것을 방지하기 위함이다.
use strict
는 스크립트 최상단에 있어야 한다! 그렇지 않으면 엄격 모드가 활성화되지 않을 수도 있다.
setTimeout(function() {
console.log(this); // window;
}) // 콜백 함수가 일반 함수로 호출되었으므로 전역 객체가 바인딩된다.
const obj = {
value: 100,
getName() {
console.log(this); // {value: 100, getName: f}
}
setTimeout(function () {
console.log(this); // window
console.log(this.value) // 1
}, 100)
}
const obj = {
value: 100,
getName() {
const that = this;
setTimeout(function () {
console.log(that.value); // 100
}, 100)
}
};
obj.getName()
[10, 20, 30].forEach((num) => {
console.log(this, num); // widnow, num;
})
document.body.querySelector('.btn').addEventListener('click', function(e) {
console.log(this, e) //
})
함수가 객체의 프로퍼티 값이면 메서드로서 호출된다. 메서드 내부의 this는 해당 메서드를 소유한 객체, 즉 해당 메서드를 호출한 객체에 바인딩된다.
this에 바인딩될 객체는 호출 시점에 결정된다.
const aurora = {
name: "Charlie",
getName() {
return this.name;
}
};
console.log(aurora.getName()); // Charlie
const bell = {
name: "Dayeon";
}
bell.getName = aurora.getName; // getName 메서드를 bell 객체의 메서드로 할당
console.log(bell.getName()); // Dayeon
const getName = aurora.getName; // getName 메서드를 변수에 할당
console.log(getName()) // '' ==> window.name과 같음!
const obj = {
outer: function() {
console.log(this);
const inner = function() {
console.log(this); // 함수의 실행으로 window
};
inner();
}
};
obj.outer();
암시적으로 바인딩되는 this는 바인딩을 쉽게 예측할 수 없는 상황이 있었다. 이러한 문제를 해결하기 위해 명시적으로 this를 고정하는 방법을 알아보자.
메서드의 호출 주체인 함수를 즉시 실행하도록 하는 명령이다.
function func() {
console.log(this.a);
}
const obj = {a: 2};
func.call(obj); // 2
func(obj); // undefined
함수의 this는 전역객체지만 call
을 사용하면 구체적인 객체를 this로 지정할 수 있다.
call 메서드와 유사한 기능으로 호출 주체 함수를 즉시 실행하지만 call()
은 함수에 전달된 매개변수를 받지만 apply()
는 인수들의 배열을 받는다.
function func(a, b, c) {
console.log(this, a, b, c);
}
const obj = {a: 2};
func.call(obj, 10, 20, 30) // {a: 2} 10 20 30
func.apply(obj, [10, 20, 30]) // {a: 2} 10 20 30
apply, call과는 달리 함수를 호출하지 않고 this로 사용할 객체만 전달한다. 즉 call, apply 메서드는 this를 명시적으로 지정하면서 함수 또는 메서드를 호출하지만 bind 메서드는 this 및 함수에 넘길 인수를 일부 지정해서 새로운 함수를 만든다.
const jasmine = {
name: 'dh',
func(callback) {
setTimeout(callback.bind(jasmine), 100);
}
};
jasmine.func(function() {
console.log('hi, i'm ${this.name}'); // "hi, i'm dh"
})
function movie(year, genre, rating) {
this.year = year;
this.genre = genre;
this.rating = rating;
}
const homeAlone = new movie(1991, 'comedy', 7.7);
const avatar = new movie(2009, 'fantasy', 7.9);
const oneDay = new movie(2011, 'romance', 7);
console.log(homeAlone.year); // 1991
console.log(avatar.genre); // 'fantasy'
console.log(oneDay.rating); // 7
어떤 함수를 new 명령어와 함께 생성자로서 동작하게 된다. 객체지향 언어에서는 생성자를 클래스, 클래스를 통해 만든 객체를 인스턴스라고 한다. 생성자 함수란 new 연산자로 함께 호출해서 인스턴스를 생성하는 함수를 일컫는다. 따라서 생성자는 인스턴스를 만들기 위한 일종의 틀이다. 그리고 생성자 함수로 호출된 경우 this는 새로 만들어진 인스턴스 자신이 된다.
function Movie(year, genre, rating) {
// --- (1)
console.log(this);
// --- (2)
this.year = year;
this.genre = genre;
this.rating = rating;
this.getAge = function() {
return new Date().getFullYear() - this.year + 1;
};
// --- (3)
}
// --- (4)
const homeAlone = new movie(1991, 'comedy', 7.7);
const avatar = new movie(2009, 'fantasy', 7.9);
const oneDay = new movie(2011, 'romance', 7);
console.log(homeAlone.year); // 1991
console.log(avatar.genre); // 'fantasy'
console.log(oneDay.rating); // 7
- 암묵적으로 인스턴스가 생성되고 this에 바인딩된다.
- this에 바인딩되어 있는 인스턴스를 초기화한다.
- 완성된 인스턴스가 바인딩된 this가 암묵적으로 반환된다.
- 인스턴스 생성하고 Movie 생성자 함수는 암묵적으로 this를 반환한다.
화살표 함수는 함수 자체의 this 바인딩을 갖지 않는다. 화살표 함수는 일반적인 바인딩 규칙을 무시하고 Lexical scope로 this를 바인딩한다. 즉 화살표 함수 내부에서 this를 참조하면 상위 스코프의 this를 그대로 참조한다.