취준때의 노고(?)

this

M9 2020. 9. 24. 02:43

자바스크립트에서 this는 다른 언어들과 다르게 작동 방식이 달라 까다롭다.

 

이 this는 함수를 호출한 주체가 누구인지(함수를 호출한 방식)에 따라 결정되기도 하고,

use strict 사용 여부에 따라 달라지기도 하고

화살표 함수에 따라 달라지기도 한다.

+ node.js에서 this와 웹 브라우저의 this도 다르다...

(매우 귀찮게 한다 증말......)

 

node.js의 this와 브라우저의 this를 혼용해서 정리하면 너부 복잡하니깐 

이번 글에서는 웹 브라우저에서의 this만 정리하겠다.

 

 

 

 

 

 

 

전역공간에서의 this

 먼저 전역 공간에서의 this는 use stirct(엄격 모드) 사용 유무와 관련 없이 전역객체를 가리킨다.

 

console.log(this===window); //true

전역 공간에서의 this는 전역 객체인 window를 가리킨다.

 

 

 

그런데, 

var a=100;
console.log(a===window.a); //true
            

let b= 105;
console.log(b===window.b); //false   , window.b===undefined

 

 

전역공간에서 var변수로 선언한 a는 전역객체에 포함된다. 

그래서 window.a의 값과 a의 값이 같은것을 볼 수 있다.

 

하지만,

let과 const로 선언한 변수는 전역객체에 포함되지 않는다.

window.b를 호출하면 undefined가 출력된다.

 

이러한 차이점이 있다.

 

 

 

 

 

단순 함수 호출

 

단순 함수 호출 같은 경우는 엄격모드일 때와 아닐때가 구분된다.

 

 

엄격 모드 미사용

function test(){
  
  return this;
  
}

console.log(test()===window); //true

 

엄격 모드 미사용시에는 전역 공간에서 함수를 호출한 것이므로 함수를 호출한 주체가 전역 객체(window)가 된다. 즉 window.test() 이렇게 호출된다.

 

 

엄격 모드 사용

'use strict';
function test(){
  
  return this;
  
}

console.log(test()===window); //false  , test()===undefined

 

하지만 엄격 모드를 사용하는 경우에는

객체(이 코드에서는 window) 를 통해서가 아닌 test()함수를 직접 호출한 것이된다. 

즉, 전역 객체나 어떠한 객체를 거치지않고 함수 자체를 직접 호출한 것이다.

그래서 정의되어있지 않는 undefined가 출력되는 것이다.

 

 

 

 

 

 

화살표 함수에서의 this

지금까지 this는 함수를 호출한 방식(함수를 호출한 주체(객체))에 따라 this의 값이 달라졌다.

 

하지만, 화살표 함수는 몇가지가 다르다.

 

첫째,  화살표 함수에서의 this는 자신을 감싸고 있는 범위에 따라 달라진다.

둘째, call, bind, apply 함수를 통해 this 값을 지정해도 무시된다. 즉, 지정되지 않는다.

 

const obj={
 fc: ()=> this,
 fc2: function(){return this;},
  test:"test"
}
console.log(obj.fc()===window);  //true
console.log(obj.fc2()===window); //false

 

 

 

 

 

 

 

 

 

 

 

 

 

코드를 통해 살펴보자.

 

경우 1

const who={
    name:'m9',
    whoAreYou:function(){
        console.log(this);
    }
};
who.whoAreYou();
//결과 { name: 'm9', whoAreYou: [Function: whoAreYou] }

이 코드에서는 this의 호출은 whoAreYou에서 이루어지고 있다.

그러면 whoAreYou를 호출하고 있는 것은 어떤 것인가.

바로 'who' 라는 객체이다.

 

즉, who라는 객체가 whoAreYou() 함수를 호출함으로써 this도 호출한 것이다.

그러므로 who가 this를 호출한 주체로써 this는 who(객체)를 가리키게 된다.

 

 

 

 

 

경우2

const who={
    name:'m9',
    whoAreYou:function(){
        console.log(this);
    }
};
who.whoAreYou();
//결과 { name: 'm9', whoAreYou: [Function: whoAreYou] }


const me=who.whoAreYou;
me();
me()의 결과
/*Object [global] {
  global: [Circular *1],
  clearInterval: [Function: clearInterval],
  clearTimeout: [Function: clearTimeout],
  setInterval: [Function: setInterval],
  setTimeout: [Function: setTimeout] {
    [Symbol(nodejs.util.promisify.custom)]: [Function (anonymous)]
  },
  queueMicrotask: [Function: queueMicrotask],
  clearImmediate: [Function: clearImmediate],
  setImmediate: [Function: setImmediate] {
    [Symbol(nodejs.util.promisify.custom)]: [Function (anonymous)]
  } */

결과부터 말하자면 this는 전역 객체(nodejs면 global, javascript 면 window)를 가리키고 있다.

그 이유는 간단하다.

me가 전역 공간에 선언되었고, me에 who.whoAreYou 함수를 할당했다.

그리고 me를 통해 this값을 불러오는 함수를 호출했다.

그래서 전역공간에 있는 me가 this를 호출한 것이므로 this는 전역 객체를 가리키게 된다.

me변수에 who.whoAreYou 를 할당한 후, me()를 통해 this를 호출해보았다.

 

 

 

 

경우 3

const btn=document.getElementById('btn');
btn.addEventListener('click',who.whoAreYou);

 이번에는 button이 존재한다고 가정하자.

그리고 this를 호출하는 함수인 who.whoAreYou를 매개변수로 넘겨 버튼을 클릭했을 때 this를 호출시키게 했다..

 

이 경우일 때 this는

button을 가리키게 된다.

this를 호출하는 함수를 매개변수로 넘겼을 뿐, 결국 this를 실행시키기 위해서 button이 작동해야 한다. 그리고 그 버튼이 클릭되었을 때 매개변수로 넘긴 함수가 실행되므로, 

결국, button이 this를 호출한 것이므로 

this는 button을 가리키게 된다.

 

 

 

 

이러한 경우들로 보아서

처음에 말했듯이 this는

 this를 호출한 주체가 누구인지에 따라 결과가 달라지는 것을 볼 수 있다. 

 

 

 

 

 

 

 

 

하지만 호출한 주체와 상관없이 this를 고정되게 가리키게 하는 방법도 있다.

 

const haha=who.whoAreYou;

const bindTest = haha.bind(who);
bindTest();
//결과 { name: 'm9', whoAreYou: [Function: whoAreYou] }

전역 공간으로 선언되어있는 haha에 bind함수를 통해 who(객체)를 인자로 넘겨주었다.

 

위에서 말했던 방법으로는 haha가 전역 공간에 선언되었으므로 this는 전역 객체를 가리켜야 한다.

 

하지만.

bind를 사용하면 this가 가리키는 값을 고정시킬 수 있다.

bind의 매개변수로 who라는 객체를 넘겨주었고, 이는 who를 this의 값으로 고정하라는 설정이다.

그래서 bindTest()의 this값이 who라는 객체의 값을 가리키는 것을 볼 수 있다.

 

 

 

 

마치며:

this 맨날 헷갈렸는데 밑에 참고자료 강의보고 드디어 이해됐다..... 굳

 

 

참고자료: developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Operators/this

'취준때의 노고(?)' 카테고리의 다른 글

auto_increment  (0) 2020.09.30
기본키 추가 삭제  (0) 2020.09.30
box-sizing  (0) 2020.09.18
html 구조 설계에 사용하는 대표 태그들  (0) 2020.09.17
html 내에서 javascript의 위치에 따른 효율성(asyn, defer)  (0) 2020.09.17