제로초님 인간JS되기 강의 보고 정리
자바스크립트의 this는 다른 언어에서의 this와 다르다
콘솔 로그로 this를 찍어보면 윈도우가 나온다
자바스크립트에서 this는 기본적으로 window라고 생각하면 된다
js(브라우저) - window(전역객체)
node - global(전역객체)
이었는데, 최근에는 둘 다 globalThis라는 것으로 합쳐졌다고 한다
(if문으로 분기처리를 하지 않기 위해 통합 되었다고 함)
const obj = {
name : 'soyoung',
sayName(){
console.log(this.name);
}
};
obj.sayName(); // soyoung
이 때 this는 window를 가리키는 것이 아니라, obj객체를 가리킨다
하지만 항상 이렇게 적용 되는 것은 아니고 적절한 판단을 해야 한다
const sayN = obj.sayName; //sayN 에 obj.sayName을 대입해본다
sayN() // 빈칸이 나온다 window.name
this는 함수가 호출될 때 정해진다
this에 특별한 동작을 한 게 없다면, 기본적으로 window가 될 것
만약 함수를 호출하는데 함수 앞에 obj. 이런 식으로 함수 앞에 객체가 붙어있다면 this는 그 객체를 가리킨다
this가 달라지는 경우
화살표함수
//화살표 함수로 바꿔보기
const obj = {
name : 'soyoung',
sayName: ()=>{
console.log(this.name);
}
};
obj.sayName() //빈칸 (window.name)이 나온다
new연산자
new연산자를 사용해서 객체를 생성할 때
이 때 this는 객체 자기 자신이 된다
function sayName(){
console.log(this.name);
}
sayName(); //window.name이 된다 (빈 값이 나옴)
위의 코드에서 this를 바꿔주는 방법에는 다음과 같다
sayName.bind
sayName.call
sayName.apply
bind / call / apply
이 세가지로 this를 바꿔줄 수 있다
bind
sayName.bind({name : 'soyoung'})()
//soyoung
.bind() 괄호안에 this를 바꾸고 싶은 객체를 넣어주고 ()괄호를 써주면 name 값이 출력 된다
이 때 this.name은 bind 안의 객체를 가리킬 것이다
bind는 새로운 함수를 만드는 것 뿐이라 호출을 할 때는 ()가 필요
apply
sayName.apply({name : 'ruru'})
//ruru
apply는 bind처럼 뒤에 ()가 붙지 않는다 => 함수를 바로 실행한다. 함수 생성과 호출까지 한번에 함
call
sayName.call({name : 'nunu'})
//nunu
기본적으로 this는 window이고, this가 바뀌는 경우에는 다음과 같다
함수 앞에 객체가 붙어서 호출될 때
객체의 메서드를 호출할 때
new 붙여서 호출할 때
bind / apply / call => 직접적으로 this를 변경해주는 경우
this는 랙시컬 스코프처럼 처음에 정해지는 것이 아니라, this는 함수를 호출할 때 정해진다
화살표 함수에서의 this
const obj = {
name : 'lulu',
sayName: () => {
console.log(this.name);
}
}
obj.sayName();
//window.name
화살표함수에서의 this는 무조건 전역을 가리키는가?
화살표함수에서의 this는 부모 스코프를 가리키는데 스코프하면 호출이 아니라 선언을 떠올려야 한다!
const obj = {
name : 'lulu',
sayName: () => {
console.log(this.name);
function inner(){
console.log(this.name);
}
inner();
}
}
이 때 inner에 대한 스코프체인은 무엇일까
저번 강의에서 배웠던 것처럼 생각해보자
inner(); 이너 함수 앞에 직선을 그어서 위로 올라가본다
제일 먼저 만나는 것 sayName함수
그렇다면 sayName함수는 어디에 닿이는가 (이 때 obj는 없다고 생각) -> anonymous 전역에 닿인다
랙시컬 스코프 찾기
inner -> sayName -> anonymous
스코프체인이 어떻게 되어있는지 잘 파악해야 한다
스코프체인을 그리는 이유는 inner에서 다른 변수에 접근 가능한가의 여부를 알기위해
sayName의 this.name은 lulu가 나오지만,
inner 함수의 this.name은 window.name(빈 칸)이 나온다
this.name은 obj.sayName()을 호출할 때 실행된다
=> 함수 앞에 obj.가 붙었고(객체), sayName()화살표 함수가 아니므로 obj.name이 되는 것 (this가 obj를 가리키니까)
this.name는 함수 호출할 때의 기준으로 보면, inner() 함수를 호출만 하고 this를 바꿔주는 행동을 따로 하지 않았다
=> 따라서 이때의 this는 window가 된다
this는 함수호출 될 때 정해진다
함수에서 this를 바꿔주는 행동을 했는가 아닌가로 this가 무엇을 가리키는지 정해진다
방금 전의 코드에서 inner를 화살표 함수로 바꾸고 결과를 확인해본다
이 때 inner의 this는 obj가 됐다 (inner의 this.name이 lulu로 나옴)
this가 어떻게 결정되는지 코드를 해석해보자
this는 함수를 호출할 때 this가 어떻게 되는지 정해진다
inner(); //함수가 호출 됨
inner() 함수를 호출할 때 this를 바꿔주는 행동을 하지 않았다
new
obj.메서드
call / apply / bind
const inner = () =>{
console.log(this.name);
}
이 때 여기서 쓰인 화살표함수는 윈도우를 가져오는 것이 아닌, 부모함수의 this를 그대로 가져온다
그렇다면 inner함수의 부모를 찾아 가본다
const obj = {
name : 'lulu',
sayName(){
console.log(this.name);
const inner = () =>{
console.log(this.name);
}
inner();
}
}
sayName함수가 inner//화살표함수의 부모함수이다
그렇다면 sayName의 this는 어떻게 정해지는가? 함수가 호출될 때 정해진다
obj.sayName() //호출
sayName부모함수의 this는 obj가 된다
const obj = {
name : 'lulu',
sayName(){
console.log(this.name);
const inner = () =>{
console.log(this.name);
}
inner();
}
}
inner의 부모함수에서 this를 가져온다고 해도, 파란색 영역에서만 보면 sayName의 this를 찾기는 어렵다
왜냐? 위의 상황에서는 sayName함수를 호출하지 않았기 때문에 sayName의 this가 obj라고 단언할 수 없다.
inner의 부모함수를 찾아서 sayName블럭을 분석하려고 하면,
sayName블럭 자체를 보는게 아니라 sayName이 어떻게 호출 되었는지를 봐야 한다
따라서 this는 함수가 호출될 때 정해진다는 것을 잊지 말기!!!!
호출하는 위치가 아닌, 호출하는 방법에 따라 this가 달라진다
sayN() //기본적인 형태의 함수로 호출하면 window를 가르킨다
obj.sayName(); //호출할 때 객체를 붙여서 호출하면 this는 이 객체가 된다
'Dev. > JavaScript' 카테고리의 다른 글
[레츠기릿JS] 끝말잇기 만들기 (0) | 2023.04.04 |
---|---|
[인간JS되기] this를 분석할 수 없는 케이스 (1) | 2023.03.28 |
[인간JS되기] 호이스팅 (0) | 2023.03.13 |
[인간JS되기] 스코프 체인 (0) | 2023.03.06 |
[인간JS되기] 자바스크립트 호출 스택 (0) | 2023.03.03 |
댓글