this
in Javascript?In most cases, the value of this is determined by how a function is called (runtime binding).
- 함수가 호출될 때
this
의 값이 결정
그냥 쓰이거나 일반함수 안에서 쓰이면 this
는 window를 뜻함
window는 모든 전역변수, 함수, DOM을 보관하고 관리하는 전역객체
strict mode에서, 함수 안에서 쓰이는 this
는 undefined
이다.
Object 자료형 내에 함수들이 있을 수 있는데, 거기서의 this
값은 this를 포함하고 있는 객체 자체를 뜻함 ✅
아래 코드의 cat이라는 객체가 가진 메소드 getName 안에 있는 this
는, cat을 뜻한다.
이벤트리스너 안에서, this
는 e.currentTarget
과 동일
<button id="button">버튼</button>
document.querySelector('#button').addEventListener('click', function(e){
console.log(this)
console.log(e.currentTarget)
// 둘 다 버튼 태그를 출력함
// e.currentTarget은 이벤트리스너가 붙은 객체(=지금 이벤트가 동작하는 곳을)를 말한다.
})
참고. (ES6) Arrow function에서 , this값을 함수 밖에 있던 window객체를 그대로 쓴다는 특징이 있음.
const cat ={
name: 'yaong',
age: 1,
getName: function(){
console.log("cat getName", this)
}
}
cat.getName() //cat getName {name: 'yaong', age: 1, getName: ƒ}
그런데,
const cat ={
name: 'yaong',
age: 1,
getName: function(){
console.log("cat getName", this)
}
}
//cat.getName()
const globalCat = cat.getName;
globalCat(); //Window {window: Window, self: Window, document: document, name: '', location: Location, …}
window
객체가 반환됨/*
차이점:
해당객체를 참조하여 접근연산자(.)를 통한 함수호출
vs.
전역에서(외부로부터) 함수 호출
*/
cat.getName(); // A.b
globalCat(); //b
그렇다면,
const cat ={
name: 'Yaong',
age: 1,
getName: function(){
console.log("cat getName", this)
}
}
//cat.getName() // A.b
const globalCat = cat.getName;
globalCat(); // b
const cat2 = {
name: 'Dundun',
age: 1,
getName: cat.getName
}
cat2.getName() //cat getName {name: 'Dundun', age: 1, getName: ƒ}
알 수 있는 점 :
호출하는 객체에 따라this
가 달라진다.
<button id='button'>this는 누굴까?</button>
const btn = document.getElementById('button');
btn.addEventListener('click', cat.getName);
// <button id='btn'>this는 누굴까?</button>
this
는 함수가 호출될 때 결정이 되는데, 함수를 호출한 객체는 btn 이므로 <button>
가 출력된다.this
를 고정하고 싶다면, bind(객체변수명)
이용
const bindGetname = cat2.getName.bind(cat);
bindGetname();
//cat getName {name: 'Yaong', age: 1, getName: ƒ}
const btn = document.getElementById('button');
btn.addEventListener('click', cat.getName.bind(cat));
//cat getName {name: 'Yaong', age: 1, getName: ƒ}
this
가 고정되어 첫번째 Cat의 이름을 가져온다.this
와 arrow function
(화살표 함수)//innerFunc은 함수안의 함수(내부함수)
//내부 함수가 호출될 때 this값은 어떻게 달라지는가?
const cat3 = {
name: 'Titi',
getName: function(){
console.log('getname', this.name);
const innerFunc = function(){
console.log('innerFunc', this.name);
}
innerFunc();
}
}
cat3.getName()
//getname Titi >> 예측한대로, 결과값 출력. this == cat3
//innerFunc undefined >> 결과값이 없음. this == Window 객체
innerFunc()
도 마찬가지로, 누가 호출했는지 알 수 없으므로,
innerFunc()
자체는 window객체를 호출한다.getName의 this
와 innerFunc의 this
를 같은 값으로 만들려면?
(1) bind()을 사용해도 되고,
(2) innerFunc을 arrow function(화살표함수)로 바꾼다. ✅
const cat3 = {
name: 'Titi',
getName: function(){
console.log('getname', this.name);
const innerFunc = () => { //🔥🔥🔥
console.log('innerFunc', this.name);
}
innerFunc();
}
}
cat3.getName()
//getname Titi
//innerFunc Titi
알 수 있는 점 :
화살표 함수에서this
는, 화살표 함수가 속해있는 곳의 상위this
를 상속받는다.
this
는) 일반함수에서의 this
와 화살표함수에서의 this
가 다름따라서, 화살표함수가 있던 함수(innerFunc)의 상위함수(getName)의 this
(= cat3)를 상속받게 되고, 결과적으로 innerFunct의 this와 getName의 this가 같게 된다.
const ageTest = {
unit: '세',
ageList : [10, 20, 30],
getAgeList : function(){
const result = this.ageList.map(function(age){
return age;
})
console.log(result);
}
}
ageTest.getAgeList(); //[10, 20, 30]
const ageTest = {
unit: '세',
ageList : [10, 20, 30],
getAgeList : function(){
const result = this.ageList.map(function(age){
return age + this.unit; //이렇게 출력하고 싶다면?
})
console.log(result);
}
}
ageTest.getAgeList(); //[NaN, NaN, NaN] 👻👻👻
왜 NaN가 출력되었나?
result함수의 return되는 this
는 Window 객체이다.
따라서, this.unit
== undefined
이고,
(숫자 + undefined == NaN
이므로) age + this.unit
== NaN
이 출력되는 것이다.
이를 해결하려면, this
가 포함된 함수를 일반함수가 아닌 화살표 함수(()=>{})로 바꾼다.
const ageTest = {
unit: '세',
ageList : [10, 20, 30],
getAgeList : function(){
const result = this.ageList.map(age => { // 🔥🔥🔥
return age + this.unit; //이렇게 출력하고 싶다면?
})
console.log(result);
}
}
ageTest.getAgeList(); //['10세', '20세', '30세']
위의 코드과 같이, 화살표 함수에서 this
는, 화살표 함수가 속해있는 곳의 상위 this
를 상속받는다. 즉, this가 포함된 result함수의 상위this(=ageTest)를 상속받아 제대로 출력하게 된다.
(참고) 화살표 함수는 bind()
제공 ❌
this
를 쓰고 싶을 때 일반함수를 쓸까, 화살표함수를 쓸까??
일반적으로, this를 쓰고 싶다면 일반함수를 써라
bind()
로 원하는 객체를 지정해 줄 수 있기 때문하지만 내부함수의 경우 this가 포함되었다면, 화살표 함수를 써라
Reference:
(MDN) this
자바스크립트 this / 코딩알려주는누나(Youtube)