자바스크립트에서의 this는 어떻게 호출되었는지, 호출 패턴에 따라 값이 결정된다.
다른 언어와는 개념이 다르며, 선언이 되어있는 곳이 아닌 호출에 따라 달라진다 !!
this가 호출되어있을 때, 어떻게 달라질까?
1. global에서 this 호출
크롬 콘솔 창에 this를 입력하면 window
라고 나온다. 기본적으로 this는 window인 것을 알 수 이있다.
그럼 일반 함수에서의 호출은 어떨까?
2. 일반 함수에서의 호출
1
2
3
4
5
function exFunction() {
console.log(this);
}
exFunction(); // window
1
2
3
4
5
6
7
'use strict';
function exFunction() {
console.log(this);
}
exFunction(); // undefined
기본 함수에서 작성한 것과 use strict
모드에서는 값이 다르게 나온다.
❓ strict 모드는 undefiend
일까?
use strict
는 ES5에서 도입된 것으로 예측하지 못하는 오류를 좀 더 쉽게 해결할 수 있게 해준다.
그래서 전역 객체를 실수로 변경할 경우 방지해주고, this를 항상 참조하는 것이 아닌 undefined
로 설정하여 함수가 기대하지 않은 컨텍스트에서 실행되는 것을 방지해준다.
3. 메서드에서의 호출
1
2
3
4
5
6
7
let obj = {
a: function () {
console.log(this);
},
};
obj.a(); // obj
객체의 메서드를 호출할 때 this를 해당 객체에 바인딩해준다.
❓ 메서드 안에 함수를 호출하면?
1
2
3
4
5
6
7
8
9
10
11
12
let obj = {
a: function () {
console.log(this); // obj
function aInnerB() {
console.log('aInnerB 호출 this >> ', this); // window
}
aInnerB();
},
};
obj.a();
this는 기본적으로 전역 객체에 바인딩이 되기 때문에, 메서드 내의 내부함수일 경우에도 window
에 바인딩된다.
4. 생성자 함수로서의 호출
1
2
3
4
5
6
7
8
9
10
function Person(name, age) {
this.name = name;
this.age = age;
}
let sine = new Person('sieun', 24);
console.log(sine); // Person { name: 'sieun', age: 24 }
let sine2 = Person('sieun', 24);
console.log(sine2); // undefined
new
키워드를 사용해서 객체를 생성해야만 생성자 함수이고, 키워드를 붙이지 않으면 일반 함수다. sine2에서 undefined
가 나온 이유는 현재 함수의 리턴 값이 없기 때문!
또한 많은 사람들이 new 키워드를 사용하지 않아 ES6부터가 class가 도입되었다.
❓ 그럼 위에 생성자 함수 로직은 어떨까?
1
2
3
4
5
6
7
8
9
function Person(name, age) {
// 생성자 함수 코드 실행 전 ①
this.name = name; // ②
this.age = age; // ②
// 생성된 함수 반환 ③
}
let sine = new Person('sieun', 24);
console.log(sine.name); // sieun
5. call/apply/bind 호출
call
, apply
, bind
는 자바스크립트 내장 객체다. 얘네를 사용하면 명시적으로 this를 바꾸게하고, 객체를 가리키게 한다.
[메서드 호출할 때 공통으로 사용할 함수]
1
2
3
function sineDesc(name, year) {
console.log(`My name is ${name}, and ${year} year ${this.gender}`);
}
call
1
2
let sine = { gender: 'woman' };
sineDesc.call(sine, 'Sieun', 24); // My name is Sieun, and 24 year woman
call 사용할 때는 맨 처음에 this로 설정할 값을 넣어주고 그 뒤에 함수에게 전달해줄 인자들을 적어야 한다.
apply
1
2
let sine = { gender: 'woman' };
sineDesc.apply(sine, ['Sieun', 24]); // My name is Sieun, and 24 year woman
apply는 call과 비슷하게 사용되지만, 함수에게 전달해줄 인자들을 배열[]
로 감싸서 넘겨줘야 한다.
bind
1
2
3
4
let sine = { gender: 'woman' };
let bindSineDesc = sineDesc.bind(sine);
bindSineDesc('Sieun', 24); // My name is Sieun, and 24 year woman
bind는 함수의 this 값을 특정 값으로 새로운 함수를 반환해준다. 이렇게 생성된 함수는 원할 때마다 사용이 가능하다.
🔖 결론
- 기본 함수에서 this를 호출하면
window
, strict 모드에서 this를 호출하면undefined
!! - 내장 함수는 선언이 되어있는 곳 상관없이 언제든 this를 전역 객체에 바인딩한다.
call
,apply
,bind
를 사용하여 this를 특정 객체에 명시적으로 바인딩할 수 있다.
Reference