기록
JavaScript Engine - 3. this 본문
this
this는 함수가 호출될 때 결정된다! -> 비동기에서도 마찬가지this
는 함수가 호출될 때 호출 방식에 따라 정해진다.(동적)
1. JS에서 this
는 기본적으로 window이다.(브라우저에서)
- window가 아닌 경우는 다음 2~4번과 같다.
- Node.js에서는 global
- 최근에는 브라우저, 노드 모두 globalThis
로 통합됨
console.log(this); // window
function a() {
'use strict';
console.log(this);
}
a(); // undefined
'use strict';
가 있으면 window가 아닌 undefined
2. 객체의 메서드가 호출될 때, 해당 메서드를 호출한 객체에 바인딩
- 단, 반드시 .
앞 객체에 바인딩된다고 단언할 수만은 없다.
- 아래 예시처럼 변수에 할당하는 경우는 다른 결과가 나온다.
const obj = {
name: 'mina',
sayName() {
console.log(this.name);
},
};
obj.sayName(); // this = obj
const sayN = obj.sayName;
sayN(); // =window.name
// 메서드를 꺼내서 변수에 대입하고 호출하면, 이 경우는 this가 window니까
// 즉, 함수가 호출될 때마다, 호출되는 방법에 따라 달라지는 것
3. 화살표 함수는 상위 스코프(부모 스코프)의 this를 가리킨다.
즉, 선언할 때 this에 바인딩될 객체가 결정됨(정적)
코드를 작성하는 순간 정해짐
const obj = {
name: 'mina',
sayName: () => {
console.log(this.name);
},
};
obj.sayName(); // this = window
4. 함수에 new를 붙여서 호출할 때(생성자함수)
이때 this는 앞으로 생성될 인스턴스 자체를 가리킴
5. bind, call, apply로 this에 바인딩할 객체를 변경할 수 있다.
function sayName() {
console.log(this.name);
}
sayName(); // window.name
sayName.bind({ name: 'mina' })(); // mina
또는
sayName.call({ name: 'mina' }); // mina
bind
는 함수를 선언하는 거라서 호출을 추가로 해줘야 함.()
call
,apply
는 함수를 호출하는 메서드call(this에 바인딩할 객체, 넘길 인자)
call
: 하나의 인자를 전달apply
: 인자를 배열(Array)로 묶어서 전달
function sayName() {
console.log(this.name);
}
sayName(); // window.name
sayName.apply({ name: 'mina' }); // mina
sayName.call({ name: 'mina' }); // mina
화살표함수
- 예시 1
함수선언식+함수선언식
const obj = {
name: 'mina',
sayName() {
console.log(this.name);
function inner() {
console.log(this.name);
}
inner();
},
};
obj.sayName(); // mina window.name
// scopechain: inner의 부모는 -> sayName의 부모는 -> anonymous
- 예시 2
화살표함수+함수선언식
const obj = {
name: 'mina',
sayName: () => {
console.log(this.name);
function inner() {
console.log(this.name);
}
inner();
},
};
obj.sayName(); // window.name window.name
- 예시 3
함수선언식+화살표함수
const obj = {
name: 'mina',
sayName() {
console.log(this.name);
const inner = () => {
console.log(this.name);
};
inner();
},
};
obj.sayName(); // mina mina
this
는 함수가 호출될 때 정해진다!!obj.sayName()
즉, this에 바인딩되는 객체는 obj- 화살표 함수의 this는 상위 스코프(sayName)의 this에 바인딩 되기 때문에
sayName()
메서드의this.name
은, 호출될 때 결정된 'mina'- 따라서 inner 스코프의 this.name 또한 'mina'가 됨
- 스코프에 집중하면 간단하게 알 수 있는 내용
- this가 호출될 때 결정되니까 호출스택을 그릴 줄 알아야 함
// 호출스택
log: mina
inner: this=obj
log: mina
obj.sayName: this=obj
anonymous: this=window
- 예시 4
함수선언식+함수선언식+객체바인딩
const obj = {
name: 'mina',
sayName() {
console.log(this.name);
function inner() {
console.log(this.name);
}
// inner() // window.name
inner.call(obj); // 객체 바인딩
},
};
obj.sayName(); // mina mina
이벤트리스너에서 this
const header = document.querySelecor('#header');
header.addEventListener('click', function () {
console.log(this);
});
// <h1 id="header">헤더</h1>
addEventListener
함수를 호출- 그리고 그 안에 함수 선언을 인자로 담은 것(호출하는 것이 아님)
- 그러면 이 함수 선언을 어디에서 호출하는지 분석할 수가 없음
addEventListener
안에서 어떻게 실행되는지를 알 수 없음- 따라서 this가 호출되는 방식을 외워야 함!
- 어떤 방식으로 this가 결정되는지 알 수 없기 때문
addEventListener
함수로 호출할 경우 this는header
자리에 오는 객체이다.- A.addEventListener() 에서 this는 A라고 암기
- 내부에서 어떻게 동작하는지는 알 수 없기 때문에 정확하게 몰라도 됨
- 사실 addEventListener는 c++로 만들어지는데, addEventListener 내부에서 어떻게 실행되는지 js로 추측해보자.
const header = {
addEventListener: function (eventName, callback) {
// callback(); // this가 window이므로 틀림
callback.call(header); // this가 header
callback.call(this); // 이렇게 작성해도 동일함
// 어쨌든 this에 이렇게 바인딩할거라는 것
},
};
header.addEventListener('click', function () {
console.log(this); // header
});
- 즉,
obj.method(callback)
과 같은 경우에서 callback에 this가 어떤 객체일지는 아무도 모른다! 왜냐면 this는 함수가 호출될 때 동적으로 결정되기 때문 - 만약 함수 선언을 화살표 함수로 한다면?
선언할 때 정적으로 this 바인딩 객체가 결정된다.(상위 스코프)
const header = document.querySelecor('#header');
header.addEventListener('click', () => {
console.log(this);
});
// window
const header = {
addEventListener: function (eventName, callback) {
callback(); // 화살표함수에서는 그냥 즉시 실행됨. call 붙일 수 없음. 선언할 때 this가 결정되므로.
},
};
출처: https://youtu.be/0yJsvly3nuk
'JS > etc' 카테고리의 다른 글
commonjs vs module (0) | 2022.06.13 |
---|---|
JavaScript Engine - 5. 비동기 시작(callback, promise) (0) | 2022.03.23 |
JavaScript Engine - 2(호출 스택, 스코프, TDZ, 선언, 초기화...) (0) | 2022.03.22 |
JavaScript Engine - 1 (0) | 2022.03.21 |
[복습] 자바스크립트 동작 원리 (0) | 2022.03.17 |
Comments