자바스크립트에서 this는 호출한 객체를 가리키는 키워드이다.
호출한 객체가 명시되어있지 않을 때에는 기본 값으로 this는 window 객체를 가리킨다.
let person = {
name : 'cho',
age : 20,
printPerson: function () {
console.log(this);
console.log(this === person);
console.log(this.age);
}
};
위와 같이 person 객체를 선언한 뒤, 함수를 호출하는 방식에 따라 this의 값은 달라진다.
person.printPerson(); //person 에 의해 호출
-----------------------------------------------------------------
{name: 'cho', age: 20, printPerson: f} //person 객체 출력
true
20
person 객체에 의해 함수를 호출하는 경우, 당연하게 this는 person 객체를 가리키게 된다.
let prt = person.printPerson;
prt();
-----------------------------------------------------------------
Window {....} //window 객체 출력
false
호출하는 객체가 명시되어있지 않은 경우에는 window 객체가 기본 값으로, this는 window 객체를 가리키게 된다.
window는 자바스크립트로 브라우저를 제어할 수 있도록 브라우저에서 제공하는 전역 객체라고 볼 수 있다. 우리가 보통 사용하는 DOM 의 최상위 요소인 document도 window하위에 있으며, 대부분 window. 는 생략된다.
html에 버튼을 추가했다고 가정해보자. 버튼에 click 이벤트를 만들고, this를 출력해보면 누구를 가리킬까?
let btn = document.querySelector('button');
btn.addEventListener('click', function() {
console.log(this);
console.log(this === btn);
}
-----------------------------------------------------------------
<button>버튼</button>
true
버튼을 누르면, click 이벤트를 감지하고 콜백으로 함수가 실행되어진다. 정확히는 함수를 호출하는게 버튼이 아니다.
그럼에도 불구하고 this가 window객체가 아니라 button인 이유는 콜백 함수가 메소드 내부에서 btn에 의해 다시 호출되었거나, 내부에서 이 this를 button으로 설정하는 작업이 이루어졌을 것이라고 추측해볼 수 있다.
우리 마음대로 this를 다른 객체로 바꿀 수 있을까? ES5 에서 this를 설정하는 bind 메소드가 정의되었다.
function prt() {
console.log(this);
}
let person1 = { name: '홍길동' };
let person2 = { name: '김길동' };
prt(); //window //호출한 객체가 없기 때문에 default인 window를 가리킨다.
let print1 = prt.bind(person1); //this에 person1이 바인딩된 prt()함수를 반환한다.
print1(); //{name: '홍길동'}
let print2 = print1.bind(person2); //바인딩된 함수에 한번 더 바인딩 시도
print2(); //{name: '홍길동'} //bind는 각 함수에 한번만 사용할 수 있다.
bind 메소드를 통해 this에 원하는 객체를 바인딩 할 수 있는데, 함수별로 한 번 만 사용할 수 있다.
let person = {
name: 'cho',
age: 20,
hello: function () {
setTimeout(function () {
console.log(this);
console.log(this.name);
console.log(this.age);
}, 1000);
},
};
person.hello();
-----------------------------------------------------
window
undefined
undefined
let person = {
name: 'cho',
age: 20,
hello: (function () {
setTimeout(function () {
console.log(this);
console.log(this.name);
console.log(this.age);
}).bind(this), 1000); //bind 시점에서 this는 person이다!!
},
};
person.hello();
-----------------------------------------------------
{name: 'cho', age: 20, hello: f}
cho
20
bind되는 시점과 호출하는 시점을 잘 파악하여 적절히 bind해주어야 한다.
대부분은 this가 호출한 객체를 가리키는데, 예외의 경우도 있다.
1) 화살표함수 (Arrow Function)
화살표 함수는 ES6에서부터 나왔다. 자신을 포함하고 있는 외부 scope에서 this를 계승받는다.
let person = {
name: 'cho',
print: function () {
setTimeout(function () {
console.log(this); //이 때 this는 window 객체이다
}, 1000);
}
};
let person = {
name: 'cho',
print: function () {
setTimeout(() => {
console.log(this); //이 때 this는 person 객체이다
}, 1000);
}
};
*화살표 함수를 사용하면 안되는 경우
let person = {
name: 'cho',
print: () => {
console.log(this); //이 때 this는 window
}
};
let btn = document.querySelector('button');
btn.addEventListener('click', () => {
console.log(this); //이 때 this는 window
});
객체 메서드를 선언할 때 화살표 함수를 사용하게되면, 외부 스코프로부터 this가 window임을 계승받게 된다. 객체 메서드에서는 this.name 과 같이 내부 변수를 사용해야하는 경우가 많은데, this가 window가 되어버리면 내부 변수를 사용할 수 없게 되므로, 이 때에는 화살표 함수를 사용하지 않는 것이 좋다.
addEventListener로 함수를 등록할 때에도 마찬가지로 this는 window가 되어 화살표 함수를 지양할 필요가 있다.
2) Strict Mode(엄격 모드)
Strict Mode에서는 호출한 객체가 없을 때, default가 window객체가 아니라 undefined이다.
function prt() {
consol.log(this);
}
prt(); //window 객체
'usepstrict';
function prt() {
consol.log(this);
}
prt(); //undefined
이 포스팅은 프론트엔드 날개달기: Vue, React 배우기 전에 꼭 알아야하는 지식 강의를 수강하며 작성되었습니다.
[지금 무료] 프론트엔드 날개달기: Vue, React 배우기 전에 꼭 알아야하는 지식 | 짐코딩 - 인프런
짐코딩 | 이 강의를 통해 Webpack, NPM 등 프론트엔드 개발자가 되기 전에 꼭 알아야할 지식을 탄탄히 다질 수 있습니다., 백그라운드 지식을 확실히 알아야,진짜 프론트엔드 개발자가 될 수 있어요
www.inflearn.com
'JavaScript' 카테고리의 다른 글
[JavaScript] 이벤트 캡쳐링 & 버블링 (0) | 2024.06.14 |
---|---|
[JavaScript] 즉시 실행 함수 (IIFE) (0) | 2024.06.13 |
[JavaScript] JS파일 효과적으로 가져오는 방법 (load, defer, async) (0) | 2024.06.09 |
[JavaScript] 브라우저 객체 모델 BOM (Browser Object Model) (1) | 2024.06.06 |
[JavaScript] 문서 객체 모델 DOM (Document Object Model) (0) | 2024.05.30 |