본문 바로가기

Front-End: Web/JavaScript

[코딩애플] js part 1-2. this 키워드를 알아보자

반응형

this 키워드는 뜻이 사용 용도에 따라서 3~4가지가 된다.

1. 함수와 Object에서 사용하면? => 나를 담고 있는 오브젝트가 나옴

(1) 그냥 쓰거나, 일반 함수 안에서 쓰면, 객체 {window}

❓window란

  • 자바스크립트 기본 함수들을 담고 있는 개체
<div></div>

<script>
  this; ⬅️
</script>

자바스크립트는 **키워드나 변수를 만나면 데이터를 바꾸고 싶어한다**.

자바스크립트의 가장 최상단에서 this 키워드는 무엇을 의미하는지 콘솔 찍어보자.

<div></div>

<script>
  console.log(this); // Window {window: Window, self: Window, document: document, name: '', location: Location, …}
</script>

window가 출력이 된다. 이게 this 키워드의 첫 번째 뜻이다.

this를 출력하는 함수를 생성해보고 실행하자.

<div></div>

<script> 
  function 함수() {
    console.log(this);   
  }
    
  함수(); // Window {window: Window, self: Window, document: document, name: '', location: Location, …}
</script>

동일하게 window가 뜬다. 즉, **그냥 쓰거나 일반 함수에서 쓰면 object {window}이다**.

❗자바스크립트 strict mode에서 쓰면 'undefined'

<div></div>

<script>
  "use strict"; ⬅️

  console.log(this); // Window {window: Window, self: Window, document: document, name: '', location: Location, …}

  function 함수() {
    console.log(this);
  }
  
  함수(); // undefined
</script>
  • 자바스크립트를 엄격하게 쓸 수 있다.
  • 최상단에 **'use strict**' 문자 키워드를 적으면 적용된다.
  • ex. 평소에는 x=300 라고 var 없이 작성할 수 있지만, strict mode에서는 **타입 없이 작성하면 에러**가 난다.
  • strict mode에서 함수 안의 this는 그냥 **undefined**다.
  • 근데 크게 중요하지 않으므로 신경 쓰진 말자.

(2) 오브젝트 안에 있는 함수(=메소드) 안에서 쓰면, "그 함수가 가지고 있는 오브젝트"를 뜻함

object를 생성해보자.

  • 차별화두기 위해서 오브젝트 내 함수를 실행할 땐 소괄호를 쓴다.
<div></div>

<script> 
  var 오브젝트 = {
    data: "kim",
    함수: function () {
      console.log("안녕");
    },
  };

  오브젝트.data;
  오브젝트.함수(); // 안녕
</script>

함수 내 this는 window가 나왔는데, 오브젝트 내의 함수의 this는 뭘까?

<div></div>

<script> 
  var 오브젝트 = {
    data: "kim",
    함수: function () {
      console.log(this);
    },
  };

  오브젝트.data;
  오브젝트.함수(); // {data: 'kim', 함수: f}
</script>

**함수를 포함하는 오브젝트**가 나온다. 왜냐하면 함수는 오브젝트 안에서 메소드로 동작하기 때문이다.

중첩된 object 안의 함수에 this는 뭘까?(오브젝트 안에 오브젝트 안의 함수)

<div></div>

<script> 
  var 오브젝트 = {
    data: {
      함수: function () {
        console.log(this);
      },
    },
  };

  오브젝트.data.함수(); // {함수: f}
</script>

오브젝트.data 객체가 나온다. 왜냐하면 함수를 담고 있는 오브젝트는 '오브젝트.data'이기 때문이다.

❓만약 function을 arrow function으로 바꾸게 되면?

  • 신문법 arrow function
  • this를 새로 만들지 않고, **상위 요소의 this값을 물려받아 쓴다**.
  • 이 경우는 상위의 data 객체의 this를 물려받는다. 그래서 window다.
<div></div>

<script> 
  var 오브젝트 = {
    data: {
      함수: () => {  ⬅️
        console.log(this);
      },
    },
  };

  오브젝트.data.함수(); // Window {window: Window, self: Window, document: document, name: '', location: Location, …}
</script>

🍯Tip! 오브젝트 안에 함수 넣을 때 신문법

<div></div>

<script> 
  var 오브젝트 = {
    data: {
      함수() { ⬅️🍯
        console.log(this);
      },
    },
  };

  오브젝트.data.함수();
</script>
  • 오브젝트 안에 함수를 넣을 떄, 함수: 로 작성할 필요 없이 **바로 함수이름(){}로 작성**하면 된다.

⭐ 요약

사실 (1)와 (2)의 this는 아주 유사하다.

  • (1)은 아무데서나 전역함수에서 쓰면 {window} 출력,
  • (2)는 오브젝트 내 함수에서 쓰면 {날 담고 있는 object} 출력
<div></div>

<script>
  { ⬅️ 
    var 오브젝트 = {
      data: {
        함수() {
          console.log(this);
        },
      },
    };

    오브젝트.data.함수();
  } ⬅️
</script>

우리가 작성하는 자바스크립트 코드는 사실 큰 {객체}로 감싸져 있다. 그게 바로 {window}다.

**우리가 함수나 변수를 전역공간에서 만들면 자동으로 <u>{window}</u>에 보관**한다. 즉, **전역변수 보관소(global object)**역할을 한다.

확인차, 함수를 window.함수();로 실행시켜보자.

<div></div>

<script>
  function 함수() {
    console.log(this);
  }

  함수();         ⬅️
  window.함수();  ⬅️
</script>

**우리가 만든 전역변수는 사실 객체 window: { } 내에 만든 것**이다. window 키워드는 생략해도 되기 때문에 window.함수()와 함수()는 동일하게 동작한다!

window: {
    함수(){
        console.log(this); // Window {window: Window, self: Window, document: document, name: '', location: Location, …}
    }
}

위에서 this는 window 오브젝트가 나온다. 왜냐하면 함수를 담고 있는 객체는 window이기 때문이다.

2. constructor 기계 내에서 사용하면, 오브젝트 생성기계

함수 안에 this를 작성하면 오브젝트 생성기계를 만들 수 있다. (constructor에 대한 설명은 나중에)

<div></div>

<script>
  function 기계() { ⬅️ 오브젝트 생성기계(constructor)
    this.이름 = "Kim"; ⬅️ 새로 생성되는 오브젝트(instance, 인스턴스)
  }

  var 오브젝트 = new 기계();
</script>

![](.\images\07.png)

3. event listener 내에서 사용하면,

event listener란?

다음 코드와 같이 요소에 이벤트를 달아주는 것.

document.getElementById().addEventListener("click", function () {});

예로 들면,

document.getElementById("버튼").addEventListener("click", function () {
    ...
});
  1. id가 '버튼'인 걸 찾아주세요
  1. 그걸 'click'하면
  1. function을 실행해주세요.
<div></div>
<button id="버튼">버튼</button>

<script>
  document.getElementById("버튼").addEventListener("click", function (e) {
    console.log(this); // <button id="버튼">버튼</button>
    console.log(e.currentTarget); // <button id="버튼">버튼</button>
  });
</script>

event listener에서 **this = e.currentTarget**다. 지금 이벤트가 동작하고 있는 HTML Tag가 나온다.

즉,

document.getElementById('버튼')

= this

= e.currentTarget

case study 1. 콜백함수(함수 안에 들어가는 함수)

<div></div>
<button id="버튼">버튼</button>

<script>
  document.getElementById("버튼").addEventListener("click", function (e) {
    var 어레이 = [1, 2, 3];
    어레이.forEach(function (a) {
      console.log(a);
    });
  });
</script>

실행 결과

![](.\images\09.png)

근데 여기서 콘솔에 this를 넣으면 this는 뭘까?

  • 4번) this는 이벤트 리스너 안에서의 e.currentTarget과 같을까? 그러기엔 어레이가 이벤트리스너가 아니므로 4번 뜻은 아니다.
  • 3번) 기계 안의 새로 생성되는 오브젝트를 의미할까? new 키워드도 없고 함수 이름도 없으니까 아닌 듯하다.
  • 2번) 내 함수의 주인, 내 함수를 보관하고 있는 오브젝트일까?
Window {window: Window, self: Window, document: document, name: '', location: Location, …}
Window {window: Window, self: Window, document: document, name: '', location: Location, …}
Window {window: Window, self: Window, document: document, name: '', location: Location, …}

정답은 2번(=1), window가 나온다! 수가 쓰인 위치에 따라서 this가 바뀐다고 했다. 이건 객체 안에 들어있는 것도 아니고, 이벤트 리스너 안에 있는 함수도 아니고 그냥 일반 함수다. 전역함수라서 this는 window다.

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

var 오브젝트 = {
    이름들: ["김", "이", "박"],
    함수: function () {
        오브젝트.이름들.forEach(function () {
            console.log(this);
        });
    },
};
오브젝트.함수();
Window {window: Window, self: Window, document: document, name: '', location: Location, …}
Window {window: Window, self: Window, document: document, name: '', location: Location, …}
Window {window: Window, self: Window, document: document, name: '', location: Location, …}

여기서 콜백함수는 근본없는 일반함수다. 그니까 this는 window다. 그럼 이건 뭘까?

var 오브젝트 = {
    이름들: ["김", "이", "박"],
    함수: function () {
        console.log(this); ⬅️
        오브젝트.이름들.forEach(function () { 
        });
    },
};
오브젝트.함수(); // {이름들: Array(3), 함수: ƒ}

case study3. arrow function 안에서의 this?

arrow function는 **내부의 this값을 변화시키지 않고 위의 this값을 그대로 전해받는다는 특징**이 있다(외부 this값 그대로 재사용).

var 오브젝트 = {
    이름들: ["김", "이", "박"],
    함수: function () {
        오브젝트.이름들.forEach(() => {
            console.log(this);
        });
    },
};
오브젝트.함수(); // // {이름들: Array(3), 함수: ƒ} x 3번

1. 함수와 Object에서 사용하면? => 나를 담고 있는 오브젝트가 나옴

(1) 그냥 쓰거나, 일반 함수 안에서 쓰면, 객체 {window}

❓window란

  • 자바스크립트 기본 함수들을 담고 있는 개체
<div></div>

<script>
  this; ⬅️
</script>

자바스크립트는 **키워드나 변수를 만나면 데이터를 바꾸고 싶어한다**.

자바스크립트의 가장 최상단에서 this 키워드는 무엇을 의미하는지 콘솔 찍어보자.

<div></div>

<script>
  console.log(this); // Window {window: Window, self: Window, document: document, name: '', location: Location, …}
</script>

window가 출력이 된다. 이게 this 키워드의 첫 번째 뜻이다.

this를 출력하는 함수를 생성해보고 실행하자.

<div></div>

<script> 
  function 함수() {
    console.log(this);   
  }
    
  함수(); // Window {window: Window, self: Window, document: document, name: '', location: Location, …}
</script>

동일하게 window가 뜬다. 즉, **그냥 쓰거나 일반 함수에서 쓰면 object {window}이다**.

❗자바스크립트 strict mode에서 쓰면 'undefined'

<div></div>

<script>
  "use strict"; ⬅️

  console.log(this); // Window {window: Window, self: Window, document: document, name: '', location: Location, …}

  function 함수() {
    console.log(this);
  }
  
  함수(); // undefined
</script>
  • 자바스크립트를 엄격하게 쓸 수 있다.
  • 최상단에 **'use strict**' 문자 키워드를 적으면 적용된다.
  • ex. 평소에는 x=300 라고 var 없이 작성할 수 있지만, strict mode에서는 **타입 없이 작성하면 에러**가 난다.
  • strict mode에서 함수 안의 this는 그냥 **undefined**다.
  • 근데 크게 중요하지 않으므로 신경 쓰진 말자.

(2) 오브젝트 안에 있는 함수(=메소드) 안에서 쓰면, "그 함수가 가지고 있는 오브젝트"를 뜻함

object를 생성해보자.

  • 차별화두기 위해서 오브젝트 내 함수를 실행할 땐 소괄호를 쓴다.
<div></div>

<script> 
  var 오브젝트 = {
    data: "kim",
    함수: function () {
      console.log("안녕");
    },
  };

  오브젝트.data;
  오브젝트.함수(); // 안녕
</script>

함수 내 this는 window가 나왔는데, 오브젝트 내의 함수의 this는 뭘까?

<div></div>

<script> 
  var 오브젝트 = {
    data: "kim",
    함수: function () {
      console.log(this);
    },
  };

  오브젝트.data;
  오브젝트.함수(); // {data: 'kim', 함수: f}
</script>

**함수를 포함하는 오브젝트**가 나온다. 왜냐하면 함수는 오브젝트 안에서 메소드로 동작하기 때문이다.

중첩된 object 안의 함수에 this는 뭘까?(오브젝트 안에 오브젝트 안의 함수)

<div></div>

<script> 
  var 오브젝트 = {
    data: {
      함수: function () {
        console.log(this);
      },
    },
  };

  오브젝트.data.함수(); // {함수: f}
</script>

오브젝트.data 객체가 나온다. 왜냐하면 함수를 담고 있는 오브젝트는 '오브젝트.data'이기 때문이다.

❓만약 function을 arrow function으로 바꾸게 되면?

  • 신문법 arrow function
  • this를 새로 만들지 않고, **상위 요소의 this값을 물려받아 쓴다**.
  • 이 경우는 상위의 data 객체의 this를 물려받는다. 그래서 window다.
<div></div>

<script> 
  var 오브젝트 = {
    data: {
      함수: () => {  ⬅️
        console.log(this);
      },
    },
  };

  오브젝트.data.함수(); // Window {window: Window, self: Window, document: document, name: '', location: Location, …}
</script>

🍯Tip! 오브젝트 안에 함수 넣을 때 신문법

<div></div>

<script> 
  var 오브젝트 = {
    data: {
      함수() { ⬅️🍯
        console.log(this);
      },
    },
  };

  오브젝트.data.함수();
</script>
  • 오브젝트 안에 함수를 넣을 떄, 함수: 로 작성할 필요 없이 **바로 함수이름(){}로 작성**하면 된다.

⭐ 요약

사실 (1)와 (2)의 this는 아주 유사하다.

  • (1)은 아무데서나 전역함수에서 쓰면 {window} 출력,
  • (2)는 오브젝트 내 함수에서 쓰면 {날 담고 있는 object} 출력
<div></div>

<script>
  { ⬅️ 
    var 오브젝트 = {
      data: {
        함수() {
          console.log(this);
        },
      },
    };

    오브젝트.data.함수();
  } ⬅️
</script>

우리가 작성하는 자바스크립트 코드는 사실 큰 {객체}로 감싸져 있다. 그게 바로 {window}다.

**우리가 함수나 변수를 전역공간에서 만들면 자동으로 <u>{window}</u>에 보관**한다. 즉, **전역변수 보관소(global object)**역할을 한다.

확인차, 함수를 window.함수();로 실행시켜보자.

<div></div>

<script>
  function 함수() {
    console.log(this);
  }

  함수();         ⬅️
  window.함수();  ⬅️
</script>

**우리가 만든 전역변수는 사실 객체 window: { } 내에 만든 것**이다. window 키워드는 생략해도 되기 때문에 window.함수()와 함수()는 동일하게 동작한다!

window: {
    함수(){
        console.log(this); // Window {window: Window, self: Window, document: document, name: '', location: Location, …}
    }
}

위에서 this는 window 오브젝트가 나온다. 왜냐하면 함수를 담고 있는 객체는 window이기 때문이다.

2. constructor 기계 내에서 사용하면, 오브젝트 생성기계

함수 안에 this를 작성하면 오브젝트 생성기계를 만들 수 있다. (constructor에 대한 설명은 나중에)

<div></div>

<script>
  function 기계() { ⬅️ 오브젝트 생성기계(constructor)
    this.이름 = "Kim"; ⬅️ 새로 생성되는 오브젝트(instance, 인스턴스)
  }

  var 오브젝트 = new 기계();
</script>

![](.\images\07.png)

3. event listener 내에서 사용하면,

event listener란?

다음 코드와 같이 요소에 이벤트를 달아주는 것.

document.getElementById().addEventListener("click", function () {});

예로 들면,

document.getElementById("버튼").addEventListener("click", function () {
    ...
});
  1. id가 '버튼'인 걸 찾아주세요
  1. 그걸 'click'하면
  1. function을 실행해주세요.
<div></div>
<button id="버튼">버튼</button>

<script>
  document.getElementById("버튼").addEventListener("click", function (e) {
    console.log(this); // <button id="버튼">버튼</button>
    console.log(e.currentTarget); // <button id="버튼">버튼</button>
  });
</script>

event listener에서 **this = e.currentTarget**다. 지금 이벤트가 동작하고 있는 HTML Tag가 나온다.

즉,

document.getElementById('버튼')

= this

= e.currentTarget

case study 1. 콜백함수(함수 안에 들어가는 함수)

<div></div>
<button id="버튼">버튼</button>

<script>
  document.getElementById("버튼").addEventListener("click", function (e) {
    var 어레이 = [1, 2, 3];
    어레이.forEach(function (a) {
      console.log(a);
    });
  });
</script>

실행 결과

1
2
3

근데 여기서 콘솔에 this를 넣으면 this는 뭘까?

  • 4번) this는 이벤트 리스너 안에서의 e.currentTarget과 같을까? 그러기엔 어레이가 이벤트리스너가 아니므로 4번 뜻은 아니다.
  • 3번) 기계 안의 새로 생성되는 오브젝트를 의미할까? new 키워드도 없고 함수 이름도 없으니까 아닌 듯하다.
  • 2번) 내 함수의 주인, 내 함수를 보관하고 있는 오브젝트일까?
Window {window: Window, self: Window, document: document, name: '', location: Location, …}
Window {window: Window, self: Window, document: document, name: '', location: Location, …}
Window {window: Window, self: Window, document: document, name: '', location: Location, …}

정답은 2번(=1), window가 나온다! 수가 쓰인 위치에 따라서 this가 바뀐다고 했다. 이건 객체 안에 들어있는 것도 아니고, 이벤트 리스너 안에 있는 함수도 아니고 그냥 일반 함수다. 전역함수라서 this는 window다.

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

var 오브젝트 = {
    이름들: ["김", "이", "박"],
    함수: function () {
        오브젝트.이름들.forEach(function () {
            console.log(this);
        });
    },
};
오브젝트.함수();
Window {window: Window, self: Window, document: document, name: '', location: Location, …}
Window {window: Window, self: Window, document: document, name: '', location: Location, …}
Window {window: Window, self: Window, document: document, name: '', location: Location, …}

여기서 콜백함수는 근본없는 일반함수다. 그니까 this는 window다. 그럼 이건 뭘까?

var 오브젝트 = {
    이름들: ["김", "이", "박"],
    함수: function () {
        console.log(this); ⬅️
        오브젝트.이름들.forEach(function () { 
        });
    },
};
오브젝트.함수(); // {이름들: Array(3), 함수: ƒ}

case study3. arrow function 안에서의 this?

arrow function는 **내부의 this값을 변화시키지 않고 위의 this값을 그대로 전해받는다는 특징**이 있다(외부 this값 그대로 재사용).

var 오브젝트 = {
    이름들: ["김", "이", "박"],
    함수: function () {
        오브젝트.이름들.forEach(() => {
            console.log(this);
        });
    },
};
오브젝트.함수(); // // {이름들: Array(3), 함수: ƒ} x 3번
반응형