[TIL] 2022-03-31 / 9일차

미음제

·

2022. 3. 31. 17:15

 

오늘 배운 내용

 

this를 new 키워드 없이 작성한 경우

 

우선 this의 정의를 살펴보면 다음과 같다. (this에 대한 정의는 "모던 자바스크립트" 책의 내용이고, 해당 내용은 링크의 블로그를 참고했습니다.)

 

this의 정의

 

'this'는 자신이 속한 객체 또는 자신이 생성할 인스턴스를 가리키는 자기 참조 변수'다. this를 통해 자신이 속한 객체 또는 자신이 생성할 인스턴스의 프로퍼티나 메서드를 참조할 수 있다. <모던 자바스크립트> - 이웅모

 

다시, new 생성자 키워드를 사용하지 않고 this를 사용하면 어떻게 될까?

 

function Cat(name, age){
    this.name = name;
    this.age = age;
}
const hong3 = Cat("홍삼이", 4);
console.log(hong3.name, hong3.age)

 

홍삼이, 4라고 출력되어야 할 것처럼 보이지만, 실행시키면 에러가 발생한다. 

 

TypeError: Cannot read properties of undefined (reading 'name')

 

이 경우의 this는 전역 객체를 가리킨다. 바인딩을 하지 않은 상태에서의 this는 항상 window라는 전역 객체를 가리킨다. 여기서 전역 객체는 전역 범위에 존재하는 객체이다(Node.js에서는 global).

 

console.log(globalThis.name, globalThis.age)

 

이렇게 전역 객체의 name과 age를 출력해보면, "홍삼이", 4가 출력된다. 이렇게 올바르게 사용하지 않은 경우에 전역 객체에 의도치 않게 접근하게 되고, 수정할 수 있게 된다. 올바르게 사용하기 위해서는 생성자 함수를 사용할 때는 반드시 new 키워드를 사용해야 한다.

 

function Cat(name, age){
    this.name = name;
    this.age = age;
}
const hong3 = new Cat("홍삼이", 4);
console.log(hong3.name, hong3.age)

 

new 키워드로 생성자 함수를 생성하면 Cat 생성자 함수가 객체를 만들고 이 생성자 함수에서 this가 해당 객체를 가리키게 된다.

 


 

this가 참조하는 곳은?

 

우선 자바스크립트에서 함수를 분리하면 다음과 같다.

 

  • 일반 함수 : 전역에 선언되어 있는 함수
  • 메서드 : 객체 안에 선언된 함수

 

앞서 말했듯 전역 객체는 window이다. 전역으로 생성된 함수도 이 window 객체에 포함되어 있기 때문에 모든 함수는 객체 내부에 있다고 할 수 있다.

 

그렇다면 함수 내부의 this는 무엇을 가리키는가? 함수를 실행하는 객체를 가리키게 된다.

 

let profile = {
    name : "MJ",
    age : 27,
    say : function(){
        console.log(this.name, this.age)
    }
}
profile.say()

 

위 예제의 결과는 "MJ 27"이 출력된다. profile 객체의 say 함수를 실행하면 console.log()가 실행되는데 이때 this는 say 함수를 실행하는 객체 profile을 가리킨다. 따라서 this.name은 "MJ"가 되고, this.age는 27이 되는 것이다.

 

let profile = {
    name : "MJ",
    age : 27,
    say: function(){
        console.log(this.name)
    },
    cats: {
        catName : "홍삼이",
        say: function(){
            console.log(`${this.name}'s cat name is ${this.catName}`)
        }
    }
}
profile.say()   // MJ
profile.cats.say()  // undefined's cat name is 홍삼이

 

다시 코드를 조금 수정해서, profile 객체에 cats 객체를 추가했다. 그리고 profile.cats.say()를 실행하면 결과는 "undefined's cat name is 홍삼이"가 출력된다.

 

this는 앞에서 말했듯 함수를 실행한 객체를 가리키게 된다. say 함수는 cats 객체에 있고, 이때 this는 cats 객체를 가리킨다. 따라서 this.name을 출력하면 undefined가 출력된다.

 

이럴 때, this.name을 원하는 대로 출력하고 싶다면 어떻게 해야 하는가?

 

console.log(`${profile.name}'s cat name is ${this.catName}`)

출력 부분에서 profile 객체의 name을 가져오도록 수정해 준다.

 


 

클로져

 

2022.03.23 - [프로그래머스/데브코스 프론트엔드] - [자바스크립트] 클로저(Closure)

 

[자바스크립트] 클로저(Closure)

클로저 클로저는 함수와 함수가 선언된 어휘적 환경의 조합이다. 클로저를 이해하려면 Javascript가 어떻게 변수의 유효 범위를 지정하는지(Lexical Scoping)를 먼저 이해해야 한다. 클로저 - JavaScript |

mieumje.tistory.com

 

지난번에 정리해둔 클로져에서 예제를 조금 더 확장해서 배웠다.

 

const words = ['a','b','c'];
for(var i=0; i<words.length; i++){
    setTimeout(function (){
        console.log(words[i], i);
    }, 1000)
}

 

이런 예제 코드가 있을 때, 실행 결과로 예상되는 값은? (a 0), (b 1), (c 2)가 출력될 것으로 생각되지만 "undefined 3"이 3번 출력된다. for loop를 돌며 각 i 마다 setTimeout이 실행될 것으로 보이지만, setTimeout이 실행될 때에는 이미 loop가 종료되었고, i는 loop를 마친 후 3이 되어 있다. 따라서 배열의 index 3을 참조하려 했기 때문에 undefined가 나왔고 i는 3으로 계속 출력된 것이다.

 

이를 해결하기 위한 방법은?

  • IIFE(즉시 실행 함수)
  • var 키워드 대신 let을 사용
  • for loop 대신 forEach 사용

 

IIFE를 사용하면 i가 증가할 때마다 각각 function scope로 가두어 처리하게 되고 setTimeout 함수는 실행 시점에 참고하는 i 값은 IIFE에서 인자로 넘긴 i 값을 이용해 원하는 결과를 얻을 수 있다.

 

var 대신 let을 사용하면 scope가 function scope에서 block scope로 변하게 되고 i는 증가할 때마다 각기 다른 block이기 대문에 원하는 결과를 얻을 수 있다. IIFE로 해결한 것과 유사하다.

 

forEach를 사용하게 되면 배열을 순회하면서 각각의 값에서 function을 만들기 때문에 3번의 function이 각기 다르게 실행되는 것과 동일해지고 원하는 결과를 얻을 수 있다.

 


 

부족한 점

  • IIFE
  • bind()
  • arrow function

 

느낀 점

 

"볼수록 익숙해지는 것." 자바스크립트 this에 대해서 만난 것을 횟수로 정의해보자면 3번째 만남이라고 할 수 있다. 우아한테크코스 프리코스 당시, Udemy 강의 수강 당시, 그리고 현재 프로그래머스 데브코스를 진행하며 3번째 만났다. this가 나오면 벌벌 떨기부터 했던 것 같다. 정확하게 어떻게 사용되는지? 왜 결과가 다른지? 생성자 함수를 new를 사용하지 않고 사용했을 때 this를 왜 사용 못했는지? 등 많은 이유로 힘들어했다. 예제를 사전 테스트로 풀어보고 해설 강의를 듣고 난 후 조금은 익숙해졌다..! 아직 완벽하게 이해했다, 다른 사람에게 설명할 수 있다 수준은 아니지만, 낯설고 어렵게만 느껴지던 게 이제는 감이 잡혔다고 할까?

 

참고

 

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Operators/this

 

this - JavaScript | MDN

JavaScript에서 함수의 this 키워드는 다른 언어와 조금 다르게 동작합니다. 또한 엄격 모드와 비엄격 모드에서도 일부 차이가 있습니다.

developer.mozilla.org

https://oneroomtable.tistory.com/entry/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-this%EB%9E%80-%EB%8C%80%EC%B2%B4-%EB%AC%B4%EC%97%87%EC%9D%BC%EA%B9%8C#0h

 

자바스크립트 this 의 개념과 바인딩 설명

자바스크립트 this 란 대체 무엇일까요? 그리고 this 를 이해하는 일은 유독 어려운 것일까요? 이번 포스팅에서는 this 의 정의와 바인딩에 대해 살펴보도록 하겠습니다. this의 정의 this 는 '자신이

oneroomtable.tistory.com

 

반응형

'프로그래머스 > 데브코스 프론트엔드' 카테고리의 다른 글

[TIL] 2022-04-04 / 11일차  (0) 2022.04.04
[TIL] 2022-04-01 / 10일차  (0) 2022.04.01
[TIL] 2022-03-30 / 8일차  (0) 2022.03.30
[TIL] 2022-03-29 / 7일차  (0) 2022.03.30
[TIL] 2022-03-28 / 6일차  (0) 2022.03.28