072DATA

자바스크립트에서 this란 본문

Anything/끄적끄적

자바스크립트에서 this란

0720 2024. 7. 31. 23:26

this

객체지향언어에서는 클래스를 정의한 인스턴스를 의미하는데

자바스크립트의 this는 독특하게 어떤 상황에서는 a라는 의미였다가

어떤 상황에서는 b라는 의미가 될 수 있습니다.

 

this는 실행 컨텍스트가 생성될 떄 결정되는데 이 말을 this를 bind된다 라고 합니다

this는 어떤 것을 가리키는지 윈도우와 노드에서 this를 확인해봅시다.

 

윈도우에서 this

 

 

 

브라우저의 개발자 도구에서 this를 출력해보고

this와 window가 같은지 확인했더니 true가 반환됐네요

브라우저에서 this는 윈도우 객체라는 것이 확인 되었습니다.

 

 

그럼 Node에서도 this는 윈도우 객체인지 확인 해보겠습니다.

 

노드에서 this

 

 

노드에서의 this는 글로벌 객체라는 것이 확인 되었습니다.

이 두 사실은 자바스크립트 코드의 동작 방식과 컨텍스트에 큰 영향을 미칩니다. 따라서

 

 

  • 브라우저: 최상위 스코프에서의 this는 window 객체를 가리킵니다.
  • Node.js: 최상위 스코프에서의 this는 빈 객체를 가리킵니다.

 

이 차이를 이해함으로써 개발자는 의도하지 않은 전역 변수의 사용을 피하고,

모듈 시스템을 적절하게 활용하여 코드의 유지보수성과 재사용성을 높일 수 있습니다

 

메서드와 함수에서 this

 

 

this는 메서드로서 호출될 때와 함수로서 호출될 때

어떤 차이점이 있는지도 알아야 합니다.

 

함수와 메서드는 비슷해 보이지만 엄연한 차이가 존재합니다

그 중 하나는 독립성입니다.

 

함수는 메서드와 다르게 그 자체로서 독립적인 기능을 수행하고

메서드는 자신을 호출한 대상 객체에 대한 동작을 수행합니다.

 

함수로서 호출과 메서드로서 호출의 구분 기준은 호출의 주체가 있느냐 없느냐인데

.(dot)이나 [](대괄호)로 호출의 기준을 정할 수 있습니다.

 

var obj = {
    methodA: function () { console.log(this) },
    inner: {
        methodB: function () { console.log(this)},
    }
};

obj.methodA();   // this === obj
obj['methodA'](); // this === obj

obj.inner.methodB(); // this === obj.inner
obj.inner['methodB'](); // this === obj.inner
obj['inner'].methodB(); // this === obj.inner
obj['inner']['methodB'](); // this === obj.inner

 

위 코드를 보면 .으로 호출하든 []로 호출하든 어쨌든 결과는 같다는 것도 확인할 수 있습니다.

 

 

 

함수로서 호출할 때 내부에서의 this

 

함수 내부에서의 this는

  • 어떤 함수를 함수로서 호출할 경우, this는 지정되지 않습니다( 호출 주체가 알 수 없기 때문에)
  • 실행 컨텍스트를 활성화할 당시 this가 지정되지 않은 경우, this는 전역 객체를 의미합니다.
  • 따라서, 함수로서 '독립적으로' 호출할때는 this는 항상 전역 객체를 가리킨다 는 것을 주의해야 합니다

메서드의 내부함수 에서의 this는

  • 메서드의 내부라고 해도, 함수로서 호출한다면 this는 전역 객체를 의미합니다.

 

호출에 대한 주체에 대해서 알아보면 a 라는 객체 안에 b라는 함수가 있다면 

그 함수를 불러오기 위하여 a.b(); 라는 코드를 입력해야 합니다.

b() 라는 함수를 불러오기 위하여 필요한 주체는 a가 될 것이며 이를 호출 주체라고 이야기 합니다.

 

var obj1 = {
    outer: function () {
        console.log("TEST =>", this) // 1. outer를 포함하는 객체 obj1이 찍힘
        
        var innerFunc = function() {
            console.log(this); // 2. 함수로서의 호출 이는 노드 환경이기 떄문에 글로벌 객체를 출력함
        };
        innerFunc(); // 함수 실행

        var obj2 = {
            innerMethod: innerFunc,
        };
        obj2.innerMethod(); // 3. 메서드로서 호출 되었기 때문에 obj2가 찍힘
    },
};

obj1.outer(); // 함수 실행

//실행 결과

//메소드로서 호출 => { outer: [Function: outer] }


// 함수로서 호출 => <ref *1> Object [global] {
//   global: [Circular *1],
//   clearImmediate: [Function: clearImmediate],
//   setImmediate: [Function: setImmediate] {
//     [Symbol(nodejs.util.promisify.custom)]: [Getter]
//   },
//   clearInterval: [Function: clearInterval],
//   clearTimeout: [Function: clearTimeout],
//   setInterval: [Function: setInterval],
//   setTimeout: [Function: setTimeout] {
//     [Symbol(nodejs.util.promisify.custom)]: [Getter]
//   },
//   queueMicrotask: [Function: queueMicrotask],
//   structuredClone: [Function: structuredClone],
//   atob: [Getter/Setter],
//   btoa: [Getter/Setter],
//   performance: [Getter/Setter],
//   fetch: [Function: fetch],
//   crypto: [Getter]
// }

// 함수로서 호출 => { innerMethod: [Function: innerFunc] } 
// 함수 내부에 콘솔이 찍히지만 어쨌든 객체안의 함수를 호출하였기 때문에 obj2가 찍힘

 

 

위 실행 결과를 보면 메소드로서 호출된 함수의 this는 obj1 객체를 출력하고

 innerFunc()  함수 내부에서 this는 global 객체를 출력합니다

 

그러나 다시 글로벌 객체를 출력하는 함수 innerFunc() 를 메소드로서 출력했더니

obj2가 출력되는 것을 알 수 있었습니다.

 

이는 함수로서의 호출은 메소드 내부에 있더라도 예외가 아니라는 것 

즉, 자바스크립트의 this 바인딩 규칙이 메서드 내부에서 정의된 함수에 대해서도

동일하게 적용된다는 것을 의미합니다.

 

다시 말해 함수가 메서드 내부에 정의되었더라도 그 함수가 호출되는 방식에 따라 this가 결정됩니다.