일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 스택
- 알고리즘
- 컨테이너
- C
- 프로세스
- vue3
- 포인터
- alexnet
- 타입스크립트
- 배열
- pytorch
- APOLLO
- 프로그래머스
- 프론트엔드
- 자바스크립트
- 이진탐색
- RxJS
- RT scheduling
- 연결리스트
- cors
- 연결 리스트
- 웹팩
- 자료구조
- 릿코드
- GraphQL
- 큐
- 코딩테스트
- 브라우저
- 해시테이블
- Machine Learning
- Today
- Total
프린세스 다이어리
자바스크립트 this란 무엇인가 본문
this란 함수를 호출할 때 생성되는 실행 컨텍스트 객체다.
this가 가리키는 대상은 어떻게 this가 호출되는지에 따라 다르다. 아래 상황별로 this의 의미를 나눌 수 있다.
→ 전역 공간에서의 this
→ 메서드로서 호출할 때 내부에서의 this
→ 함수로서 호출할 때 내부에서의 this
→ 콜백 함수 호출 시 내부에서의 this
→ 생성자 함수 내부에서의 this
1. 전역 공간에서의 this
전역 공간에서 this는 전역 객체를 가리킴. (this 콘솔에 찍으면 전역객체 나온다는 뜻)
console.log(this) // {alert: f(), atob: f(), blur: f(), ...}
console.log(window) // {alert: f(), atob: f(), blur: f(), ...}
console.log(this === window) // true
→ this를 콘솔에 찍으나, window를 콘솔에 찍으나 똑같음.
특이점은 우리가 var a = 1; 라고 변수 선언하고 1 할당하면, 자바스크립트 엔진은 전역 객체 안의 프로퍼티로 a를 할당함
var a = 1
console.log(a) // 1
console.log(window.a) // 1
console.log(this.a) // 1
→ a를 직접 콘솔에 찍어도 1이 나오는 건 스코프 체인에서 a를 검색하다가 발견한 프로퍼티이기 때문
→ window.a나 this.a가 1인 건 전역 객체 안의 프로퍼티에 a가 있기 때문
그러나 ES6 이후 var 대신 let과 const를 쓰면 다르게 나온다.
let a = 1
console.log(a) // 1
console.log(window.a) // undefined
console.log(this.a) // undefined
2. 메서드로서 호출할 때 그 메서드 내부에서의 this
일단 함수로서 호출하는 경우와 메서드로서 호출하는 경우를 구분하는 방법 소개
var handleThis = function (x) {
console.log(this, x)
}
handleThis(1) // Window {...} 1
var obj = {
thisMethod: handleThis
}
obj.thisMethod(2) // { thisMethod: f } 2
obj['thisMethod'](2) // { thisMethod: f } 2
→ 호출한 익명함수는 똑같은데, 변수에 담아서 호출한 경우와 객체의 프로퍼티에 할당해서 호출한 경우에 this가 달라짐.
→ 함수로서 호출하는 경우와 메서드로서 호출하는 경우를 구분하는 방법은 함수 앞에 점이 있느냐 없느냐를 확인하는 것. 점 앞에 객체가 명시돼 있기 때문
메서드 내부에서의 this는 어떤 값일까?
var obj = {
methodA: function () {
console.log(this)
},
inner: {
methodB: function () {
console.log(this)
}
}
}
obj.methodA() // { methodA: f, inner: {...} } === obj
obj['methodA']() // { methodA: f, inner: {...} } === obj
obj.inner.methodB() // { methodB: f } === obj.inner
obj.inner['methodB']() // { methodB: f } === obj.inner
obj['inner'].methodB() // { methodB: f } === obj.inner
obj['inner']['methodB']() // { methodB: f } === obj.inner
→ 메서드 내부에서의 this는 호출한 주체에 대한 정보임. 여기서 호출한 주체란 함수명(프로퍼티명) 바로 앞의 객체임. 즉 마지막 점 앞에 명시된 객체를 말함.
3. 함수로서 호출할 때 그 함수 내부에서의 this
그냥 함수로서 호출할 때는 this가 지정되지 않음.
var obj1 = {
outer: function() {
console.log(this) // obj1
var innerFunc = function () {
console.log(this) // Window, obj2
}
innerFunc() // 2번
var obj2 = {
innerMethod: innerFunc
}
obj2.innerMethod() // 3번
}
}
obj1.outer() // 1번
→ 1번: obj1.outer() 함수는 메서드로서 호출한 것. 따라서 outer 함수의 this에는 점 앞의 객체인 obj1이 바인딩됨.
→ 2번: innerFunc()는 객체가 아닌 그냥 변수에 담아서 호출했으므로 this에는 아무것도 지정되지 않아 전역 객체가 콘솔에 찍힘.
→ 3번: obj2.innerMethod()는 위에서 선언한 innerFunc() 함수를 obj2라는 객체의 innerMethod라는 프로퍼티에 할당해서 호출했기 때문에 this에는 점 앞의 객체인 obj2가 바인딩됨.
함수 내부에서 직전 컨텍스트의 this를 바라보게 하는 방법
var obj1 = {
outer: function() {
console.log(this) // { outer: f }
var innerFunc = function () {
console.log(this) // Window
}
innerFunc()
var self = this;
var innerFunc2 = function () {
console.log(self) // { outer: f }
}
innerFunc2()
}
}
obj1.outer()
→ 단순히 self (어떤 변수명이어도 상관 없으나, 컨벤션으로 self라고 쓰는 듯함) 변수에 this를 저장한 후, 함수 안에서 self를 출력해보면 된다
→ 단순히 상위 스코프의 this를 저장해서 내부함수에서 활용하기 위한 수단임
물론 arrow function을 쓰는 지금은 그런 우회는 필요 없다
var obj = {
outer: function () {
console.log(this) // 1. { outer: f }
var innerFunc = () => {
console.log(this) // 2. { outer: f }
}
innerFunc()
}
}
obj.outer()
→ 우회할 필요 없이 함수 안에서 this 찍어 보면 바로 현재 컨텍스트의 this가 나옴
4. 콜백 함수 호출 시 그 함수 내부에서의 this
콜백 함수는 다음 장에서 자세히 다룰 것.
콜백 함수도 기본적으로 함수이기 때문에, 특별히 this를 지정하지 않으면 전역객체를 바라봄. 지정된 경우와 지정되지 않은 경우를 보겠음
// 1번 예시: setTimeout 함수
setTimeout( function () {
console.log(this)
}, 300)
// 2번 예시: forEach 메서드
[1, 2, 3, 4, 5].forEach( function (x) {
console.log(this, x)
})
// 3번 예시: addEventListener
document.body.innerHTML += '<button id="a">클릭</button>'
document.body.querySelector('#a').addEventListener('click', function (e) {
console.log(this, e)
})
// '<div id="root"></div><button id="a">클릭</button>'
→ 1번에서는 내부 콜백 함수에서 따로 this를 지정하지 않으므로 전역객체 출력됨
→ 2번에서도 마찬가지로 내부 콜백 함수에서 this를 지정하지 않았으므로 전역객체와 배열요소 한개씩 5번 출력됨
→ 3번에서는 지정한 객체가 있으므로 점 앞의 엘리먼트와, 이벤트 객체 출력됨
5. 생성자 함수 내부에서의 this
생성자 함수란 어떤 공통된 성질을 지니는 객체들을 생성하는 데 사용하는 함수다.
생성자를 클래스(class), 클래스를 통해 만든 객체를 인스턴스(instance)라고 함
생성자 함수 내부에서의 this는 새로 만들 구체적인 인스턴스 자신이 됨
var Cat = function (name, age) {
this.bark = '애용'
this.name = name
this.age = age
}
var choco = new Cat('초코', 7)
var nabi = new Cat('나비', 5)
console.log(choco, nabi)
// Cat { bark: '애용', name: '초코', age: 7 }
// Cat { bark: '애용', name: '나비', age: 5 }
→ 생성자 함수 Cat을 호출하면, 일단 Cat에 대한 prototype 프로퍼티가 있는 객체가 만들어짐. 그리고 미리 준비된 공통 속성을 해당 객체(this)에 부여함.
→ 그래서 this가 각각 choco 인스턴스, nabi 인스턴스를 가리키는 것.
'FE' 카테고리의 다른 글
자바스크립트 변수를 선언하고 값을 할당하는 일련의 과정 설명하기 (0) | 2021.12.01 |
---|---|
CSR(클라이언트 사이드 렌더링) vs SSR(서버 사이드 렌더링) 단골질문 뽀개기 (1) | 2021.11.29 |
이벤트 캡쳐링, 이벤트 버블링 개념, 방지하는 방법 (0) | 2021.11.25 |
이벤트 루프와 콜백 큐가 작동하는 원리 (0) | 2021.10.30 |
자바스크립트는 싱글스레드 언어라면서 어떻게 비동기함수 사용할 수 있나요 (0) | 2021.10.29 |