java와 C# 등의 객체지향 언어에서의 this
는 현재 객체나 인스턴스 자신을 나타낸다. 이들은 객체 내에서 this
를 씀으로써 자신의 인스턴스 변수나 함수에 접근을 할 수 있다.
하지만 js에서의 this
는 다른 언어들과는 다른 특징을 갖고 있다. js에서의 this
에는 반드시 자기 자신의 객체가 무조건 들어가지는 않는다. 함수를 호출하는 방식에 따라 동적으로 this
가 지칭하는 객체가 달라진다.
즉, js의 this
는 함수가 호출되는 시점의 실행 컨텍스트(Execution Context)이며 함수를 실행하는 환경(호출하는 방법, 환경)이 달라지면 this
도 변한다는 것이다.
this
는 기본적으로 window
객체이다.console.log(this) // window
console.log(this === window) // true
this
는 strict 모드 지정에 따라 다른 값을 가진다. // strict 모드가 아닐 경우
function whatIsThis() {
console.log(this); // window
}
// strict 모드일 경우
function whatIsThis() {
console.log(this); // undefined
}
this
는 객체 자신을 가리킨다.const user = {
name: 'James',
showName: function () {
console.log(this.name); // user.name
},
whatIsThis: function () {
console.log(this); // user
}
};
this
는 생성된 인스턴스를 가리킨다.function Person(name) {
this.name = name;
}
const person1 = new Person('Alice');
console.log(person1.name); // Alice
이러한 this의 유연한 특징은, 개발하는 데 있어서 개발의 다형성을 구현하는 데 도음이 되었다. 하지만 동시에 혼란을 초래할 수 있다는 단점도 가지고 있기에, 이를 개선하기 위해서 ES는 여러 개선점을 추가하였다.
1. ES5
strict mode 도입
strict mode에서는 this
사용을 보다 엄격하게 관리하여 오류를 미리 방지한다.
bind 메서드 도입
함수의 this
를 특정 객체에 바인딩하는 bind
메서드가 도입되어 명시적인 바인딩을 지원한다.
2. ES6 (ES2015)
화살표 함수 (Arrow Function) () => {}
도입
화살표 함수 내부에서 this
는 함수를 둘러싼 스코프의 this
와 같아지며, 외부에서 정의된 this
값을 그대로 사용한다. 즉, 객체의 메서드 정의를 function
이 아닌 화살표 함수를 작성하면 this
는 객체가 아닌 객체의 외부를 스코프한다.
클래스 (class) 도입
class
내부에서 메서드를 작성할 때, 그 메서드 내부의 this
는 해당 클래스의 인스턴스를 가리킨다.
우리는 js의 함수를 작성할 때 마다 해당 함수가 가질 수 있는 함수인 call()
, apply()
, bind()
메서드를 보았을 것이다. 이 기능들은 해당 함수의 this
값을 명시적으로 설정하거나 바인딩하기 위한 메서드들이다. 이들은 함수의 호출 방식과 컨텍스트를 제어하며, this
가 지칭하는 바를 특정해준다.
function greet(firstName, secondName) {
console.log(`Your name is ${firstName} ${secondName}! My name is ${this.name}!`);
}
const person = { name: 'Jayce' };
greet.call(person, 'Bang', 'Junsu'); // Your name is Bang Eunsu! My name is Jayce!
function greet(firstName, secondName) {
console.log(`Your name is ${firstName} ${secondName}! My name is ${this.name}!`);
}
const person = { name: 'Jayce' };
greet.apply(person, ['Bang', 'Junsu']); // Your name is Bang Eunsu! My name is Jayce!
function greet(name) {
console.log(`Hello, ${name}! My name is ${this.name}.`);
}
const person = { name: 'Alice' };
const greetPerson = greet.bind(person);
greetPerson('Bob'); // Hello, Bob! My name is Alice.