[코딩애플] JavaScript ES6 강의 정리 (Part1 3강 ~ 4강)

이언덕·2024년 6월 3일

코딩애플

목록 보기
25/37
post-thumbnail

3강 / this 키워드를 알아보자 1. 함수와 Object에서 사용하면?

개발하면서 은근 자주 찾아볼 수 있는 this 키워드는 뜻이 매우 다양하다.
사용하는 환경에 따라서 4개 이상의 각각 다른 뜻을 가지고 있는데
한번 정리해보자.

1-1. 그냥 쓰거나 함수 안에서 쓰면 this는 window를 뜻한다.

그냥 HTML 파일 아무거나 하나 만들고 중간에 <script>태그 열어서
일단 this라는 키워드를 콘솔창에 출력해보자.

 console.log(this)

그러면 this 키워드는 그냥 window {어쩌구} 이런 값이 나온다.




비슷하게 일반 함수 내에서 this라는 값을 불러보면

function test(){
  console.log(this)
}
test();

똑같이 this라는 값은 window 라고 출력된다.
이것이 this의 첫째 뜻이다. 그냥 window이다.

Q. window가 뭔가요?
A. window는 모든 전역변수, 함수, DOM을 보관하고 관리하는 전역객체이다.

라고 구글검색 번역투로 설명하면 이해가 안되니 좀 쉽게 비유해보자면
우리가 쓰는 자바스크립트 함수들
document.getElementById(), alert(), console.log()
이런 함수들을 보관하는 보관소이다. 보관소는 특별한건 아니고 그냥 큰 {오브젝트}일 뿐이다.
또한 우리가 전역변수를 만들었을 때도 이 값을 보관해준다.

let x = 300;

이렇게 변수를 큰 공간에 만들면 x라는 변수는 window라는 큰 오브젝트안에 자동적으로 생성된다.
함수도 마찬가지이다.
아무튼 그냥 보관소이다.

  • 전역변수 : 코드 내 모든 곳에서 참조해서 쓸 수 있는 범용적인, 범위가 넓은 변수이다. 그냥 script태그 내에 쌩으로 let 변수 하나 만들면 그건 자연스레 전역변수가 된다.


1-2. strict mode일 때 함수 안에서 쓰면 this는 undefined 이다.

<script>
  'use strict';

  function test(){
    console.log(this)
  }
  test();

</script>

IE 10버전 이상에선 'use strict'라는 키워드를 페이지 최상단에 추가하면
strict mode로 자바스크립트를 작성가능하다.
strict mode에선 var 키워드 없이 변수를 선언하거나,
변수를 arguments라는 이상한 키워드로 선언하거나 그런 실수를 방지해준다.
strict mode에선 this 키워드를 일반함수 안에서 불렀을 때 undefined라는 값으로 강제로 지정해준다.



object 자료형 내에 함수들이 있을 수 있는데 거기서 this값은 '주인님'을 뜻한다.

우리는 object 자료형에 함수같은거 집어넣을 수 있다는것을 알고 있다.

let testObj = {
  data : 'Kim',
  testFun : function(){ console.log('테스트 중') }
}

글자나 숫자 집어넣듯이 object 내에도 저렇게 함수를 집어넣을 수 있다.

그럼 함수를 어떻게 꺼내쓰냐면

let testObj = {
  data : 'Kim',
  testFun : function(){ console.log('테스트 중') }
}

testObj.testFun();

이렇게 쓰면 된다. 그럼 콘솔창에 '테스트 중'라는 글자가 출력될 것 같다.



object에 들어가는 함수들은 전문용어로 메소드 method라고 칭한다.
근데 method 안에서 this를 쓰면 신기한 값이 나온다. 바로 주인님이라는 값인데

let testObj = {
  data : 'Kim',
  testFun : function(){ console.log(this) }
}

testObj.testFun();

'테스트 중'라는 단어 대신 this라는 키워드를 출력시키면 어떻게될까?
콘솔창에 { data : 'Kim', 간지함수 : f } 뭐 이런값이 출력된다.



이게 뭐냐면 그냥 내가 방금 만든 testObj이다.
그래서 method안에서 this를 쓰면 this는 메소드를 가지고 있는 object를 뜻한다.
쉽게 외우고싶다면 this는 'method의 주인님'을 지칭한다 라고 기억하면 된다.



그럼 밑의 예제의 this는 무슨 값이 출력될까?

let testObj = {
  data : {
    testFun : function(){ console.log(this) }
  }
}
testObj.data.testFun();
console.log(testObj.data)

objectmethod안에서 썼을 때 this는 메소드를 담고있는 주인님을 뜻하기 때문에
testFun()를 담고있는 주인님인 testObj.data 라는게 위의 this랑 동일한 뜻이다.
둘다 각각 출력해보자.



그냥 this라는 뜻은 2번으로 알고 있으면 된다.

1번, 즉 "일반 함수 내에서 썼을 때 this는 window이다" 라는 정의는 굳이 외울 필요가 없다.
왜냐면 여러분이 2번 뜻을 잘 이해했다면 1번도 자연스레 유추가 가능하기 때문이다.
우리가 함수나 변수를 대충 스크립트 태그 안에 만들었을 때, 함수나 변수는 그냥 만들어지는게 아니다.

<script>

  function testFun(){
    console.log()
  }

</script>

방금 만든 testFun()전역변수전역함수를 관리하기 위한 window라는 object에 자동으로 추가가 된다.



그래서 코드(1) 코드(2) 둘다 자바스크립트 입장에서 보면 똑같단 이야기이다.

<script>

  (1)
  function testFun(){
    console.log(this)
  }

  (2)
  window.testFun = function () {
    console.log();
  };
  

</script>

(2)코드window라는 object에 함수 자료를 추가하는 코드일 뿐이다. 어려운거 없다.
결론은 전역함수 만들거나 전역변수 만들거면 저렇게 window {오브젝트} 안에 담긴다는 소리이다.
우리가 일부러 하지 않아도 변수나 함수 쌩으로 만들면 자바스크립트가 자동으로 알아서 window안에 담는다.
(변수 강의시간에 window object에 대해 잠깐 더 알아볼 예정이다!)



그럼 이제 function 문법의 동작원리 하나를 알았으니 다시 한번 this를 여기서 출력해보자.

function testFun() {
  console.log(this);
}
testFun();

여기서 this는 무슨 값이 나올까?
this는 아까 2번에 의하면 내 method를 포함하고 있는 주인님의 object를 출력시켜준다고 했다.
testFun()를 포함하고 있는 주인님 오브젝트가 무엇일까?


우리가 위 글들을 잘 이해하고 있었다면 쉽게 답이 나올 수 있을 것이다.
우리는 현재 전역함수를 만들었기 때문에 testFunwindow {오브젝트}에 담겼을 것이다. 그렇기 때문에 testFun()를 포함하고 있는 주인님window가 된다.




4강 / this 키워드를 알아보자 2. event listener와 constructor

3. constructor 안에서 쓰면 constructor로 새로생성되는 오브젝트를 뜻한다.

자바스크립트에서 object를 비슷한걸 여러개 만들고 싶을 경우
object를 복사하는게 아니라 constructor라는걸 만들어서 사용한다.
쉽게 말하면 constructorobject를 복사해서 생성해주는 기계이다.
기계를 어떻게 만드는지 알아보자.


function testMachine(){
  this.name = 'Kim';
}

이게 기계 만드는 법이다.


함수 문법을 이용해서 만든 후, 안에 this. 어쩌구를 추가해주면 된다.
여기서의 this.는 기계로부터 새로 생성될 object(instance)들을 의미한다.
그럼 this.이름 = 'Kim' 이건 무슨 뜻일까?
새로생성되는 objectname key값에 'Kim'이라는 value를 집어넣어주세요
라는 뜻 아닐까?

▼ 이건 참고로 알아두면 좋은 기계에서 오브젝트 뽑는 법이다.

function testMachine(){
  this.name = 'Kim'
}
let testObj = new testMachine();

이렇게 new 키워드를 이용하면 새로운 object를 꺼낼 수 있다.

그리고 새로운 object{name : 'Kim'} 이라는 값을 가지고 있다. (this 라는 키워드 덕분에!)

new 키워드를 사용하면?

constructor안에 있는 object에 접근할 수 있으며 objectvalue에도 접근할 수 있다. 아래 예시를 봐보자

  • object에 접근
function testMachine() {
  this.name = "Kim";
  this.age = 15;
}
let testObj = new testMachine();
console.log(testObj)

  • value에 접근
function testMachine() {
  this.name = "Kim";
  this.age = 15;
}
let testObj = new testMachine();
console.log(testObj.name);
console.log(testObj.age);

new 키워드를 작성하지 않으면?

object가 꺼내지지 않게 되어 undefined가 출력된다.

function testMachine() {
  this.name = "Kim";
  this.age = 15;
}
let testObj = testMachine();
console.log(testObj);

new 키워드를 이용하여 새로운 object가 어떻게 생기는지 찾아보았다.

위 예제 코드를 단계별로 분석해서 설명할 것이다!

1. 생성자 함수 정의

function TestMachine() {
  this.name = 'Kim';
}
  • 여기서 TestMachine은 생성자(constructor) 함수이다.
  • this 키워드는 생성자 함수 내에서 특별한 의미를 가진다. this는 생성될 새 객체를 참조한다.
  • this.name = 'Kim';은 새로 생성될 객체에 name 속성을 추가하고 그 값을 'Kim'으로 설정한다.

2. new 키워드를 사용하여 객체 생성

let testObj = new TestMachine();
  1. 새로운 빈 객체 생성: new TestMachine()을 호출하면 자바스크립트는 새로운 빈 객체 {}를 만든다. (이 부분 가장 중요!)
  2. this 바인딩: 생성자 함수 TestMachine 내부에서 this는 새로 생성된 빈 객체를 가리킨다.
  3. 프로퍼티 추가: this.name = 'Kim';이 실행되면 새로 생성된 객체에 name 속성이 추가되고, 그 값은 'Kim'이 된다.
  4. 객체 반환: 생성자 함수가 명시적으로 다른 객체를 반환하지 않으면, new 키워드는 자동으로 this (즉, 새로 생성된 객체)를 반환한다.

결국, let testObj = new TestMachine();의 결과로 testObj는 다음과 같은 객체가 된다

{
  name: 'Kim'
}

따라서, new 키워드를 사용하여 생성자 함수를 호출하면 새로운 객체가 생성되고, 그 객체는 생성자 함수 내에서 정의된 속성과 값을 가진다. 이 과정 덕분에 새로운 객체를 쉽게 만들 수 있다.



4. eventlistener 안에서 쓰면 this는 e.currentTarget이라는 의미이다.

document.getElementById('btn').addEventListener('click', function(e){
  console.log(this)
});

여기서 this를 소환하면 이것은 바로 e.currentTarget이라는 뜻과 똑같은 의미이다.
e.currentTarget은 지금 이벤트가 동작하는 곳을 뜻한다.
매우 간단히 설명하면 지금 addEventListener 부착된 HTML 요소를 뜻한다고 보시면 된다.
한번 e.currentTarget, this 이거 두개를 각각 출력해보자.

이게 this의 마지막 뜻이다.



case 1. 이벤트리스너 안에서 콜백함수를 쓴다면 this는?

이런 코드를 쓴다고 가정해보자.

document.getElementById('btn').addEventListener('click', function(e){
  let testArr = [1,2,3];
  testArr.forEach(function(){
    console.log(this)
  });
});

이벤트리스너 안에서 forEach() 라는 반복문을 사용했다.
forEach() 반복문을 사용할 땐 안에 function(){} 콜백함수를 집어넣어서 사용하게 되어있다.
(콜백함수는 그냥 함수 안에 파라미터역할로 들어가는 함수를 뜻한다.)

Q. 위의 코드에서 this를 출력하면 무엇이 나올까?
4번뜻에 의하면.. eventlistener 안에서 쓴 건 아니다.
eventlistener내부는 맞지만 그 안에서 function을 하나 더 만났기 때문에 의미가 변한다.
this의 1번 뜻인 것 같다.
저렇게 쌩으로 있는 콜백함수는 그냥 일반함수랑 똑같기 때문에 window가 출력된다.

this의 값은 this가 어떤 함수안에 들어있는지만 잘 체크하시면 바로 아실 수 있다.



case 2. 오브젝트 안에서 콜백함수를 쓴다면 this는?

이번엔 이런 코드를 쓴다고 가정해봅시다.

let testObj = {
  names: ["김", "이", "박"],
  testFun: function () {
    testObj.names.forEach(function () {
      console.log(this);
    });
  },
};

오브젝트라는 오브젝트 안에 이름들, 함수라는 자료를 각각 저장했다.
함수라는 자료 안에 forEach 반복문을 돌렸는데,

Q 그럼 여기 안에서의 this값을 출력하면 뭐가나올까?
this값을 판단하실 땐 가장 가까이 있는 함수를 살펴보면 된다.
forEach() 안에 있는 함수에 this가 들어있다.
근데 이 함수는 무슨 뭐 특별한 역할을 하는 함수인가?
아니다. 그냥 일반 함수일 뿐이다.
그래서 이것도 window이다.



arrow function

그래서 this값은 function을 만날 때마다 바뀔 수 있기 때문에
내가 원하는 this를 쓰기 힘든 경우가 있다.
그럴 땐 함수arrow function으로 바꿔보면 좋다.

let testObj = {
  names: ["김", "이", "박"],
  testFun: function () {
    testObj.names.forEach(() => {
      console.log(this);
    });
  },
};

자바스크립트 ES6 문법 중,
function () {} 대신 쓸 수 있는 () => {} 이라는 arrow function 문법이 있다.
똑같이 함수 만드는 문법이다.
이걸 쓰면 함수 내부의 this값을 새로 바꿔주지 않기 때문에 this를 사용하실 때 유용하다.

0개의 댓글