JavaScript/함수

[JavaScript]함수와 this(Function and this)

DevStory 2022. 7. 4.

전역 객체

JavaScript 함수 내부에서 this를 사용한 경우 this는 전역 객체에 바인딩되며, Chrome과 같은 브라우저에서 JavaScript 코드를 실행하는 경우 전역 객체는 window 객체입니다.

 

다음 예제를 Chrome 개발자 도구 콘솔 창에서 실행 후 함수 내부의 this가 어떻게 바인딩되는지 확인해봅시다.

function show() {
  console.log(window === this);
}

show();

[실행 결과]

Chrome과 같은 브라우저에서 전역 객체는 window 객체라고 설명했으며, 함수 내부의 this는 전역 객체에 바인딩된다고 언급했습니다.

 

즉, 브라우저에서 함수 내부의 this는 window 객체입니다.

 

다음은 함수가 아닌 변수를 선언하는 경우에 대해 알아봅시다. 다음 예제는 브라우저에서 변수를 선언 후 window 객체의 프로퍼티로 호출합니다.

var name = '홍길동';
var age = 30;

console.log('name: ' + name + ' / age: ' + age);
console.log('name: ' + window.name + ' / age: ' + window.age);

[실행 결과]

전역 변수인 name과 window.name이 동일한 값을 출력합니다. 동일한 값이 출력되는 이유는 전역 변수가 window 객체의 프로퍼티로 저장되기 때문입니다.


내부 함수의 this

JavaScript에서 객체의 프로퍼티가 함수인 경우 메서드라고 말합니다.

 

다음 예제는 this를 사용하는 객체의 메서드를 호출합니다.

let obj = {
  strValue: 'Hello',
  normalFunc: function() {
    console.log(this.strValue)
  }
}

obj.normalFunc(); // Hello

위 예제를 통해 메서드에서 사용된 this는 메서드를 호출한 객체로 바인딩된다는 것을 확인할 수 있습니다.

 

메서드와 this에 대한 내용은 아래 포스팅에서 자세하게 설명합니다.

 

[JavaScript]메서드와 this

JavaScript에서 객체의 프로퍼티가 함수인 경우에는 해당 프로퍼티를 메서드라고 말합니다. 이번 포스팅은 메서드에서 this가 어떻게 동작하는지 설명합니다. this 바인딩 메서드에 사용된 this는 메

developer-talk.tistory.com

그렇다면, 메서드 내부에 함수가 존재하고 this를 사용하는 경우 어떻게 될까요?

 

다음 예제를 실행해봅시다.

var num = 10;

var obj = {
  num: 1,
  func1: function() {
    this.num += 1; // 메서드에서 this 사용
    console.log('func1() 호출! this.num의 값: ' + this.num);
    
    // 메서드 내부에 선언된 내부 함수
    function func2() {
      this.num += 1; // 내부 함수에서 this 사용
      console.log('func2() 호출! this.num의 값: ' + this.num);
    }
    
    // 내부 함수인 func2() 함수 호출
    func2();
  }
};

obj.func1(); // func1() 메서드 호출

전역 변수인 num이 존재합니다. 그리고 객체 obj에는 num이라는 프로퍼티와 func1() 함수가 존재하고 func1() 함수 내부에는 func2() 내부 함수가 존재합니다.

 

객체 obj의 func1() 메서드를 호출하면 func1() 내부의 func2() 함수가 실행됩니다.

 

위 예제를 실행하면 3이 출력될 것으로 예상되지만, 생각과는 다른 출력 결과를 보여줍니다.

[실행 결과]

예상했던 생각과 다르게 출력된 이유는 func1()는 객체 obj에 의해 호출되었으므로 메서드로 취급되지만, func2()는 점 표기법 또는 대괄호 표기법 없이 호출되었으므로 일반 함수로 취급됩니다.

 

즉, func2() 함수는 일반 함수이므로 func2() 함수 내부의 this는 전역 객체에 바인딩됩니다.

 

소스 코드의 this가 바인딩되는 과정을 그려보면 다음과 같습니다.

반응형

내부 함수의 this 해결 방법

정리하자면, 메서드의 내부 함수의 특징은 다음과 같습니다.

  • 객체의 프로퍼티가 아니므로 일반 함수로 취급됩니다.
  • 점 표기법 또는 대괄호 표기법 없이 호출되었으므로 일반 함수로 취급됩니다.
  • 메서드의 내부 함수는 일반 함수이므로 내부 함수의 this는 전역 객체로 바인딩됩니다.

내부 함수인 func2()에서 this가 원하는 대로 동작하지 않으므로 func1()에서 this 값을 저장하는 변수가 필요합니다.

 

내부 함수는 부모의 함수의 변수에 접근할 수 있기 때문입니다.

 

위 내용은 내부 함수와 클로저에 대한 개념을 알고 계신다면, 쉽게 이해할 수 있습니다.

 

[JavaScript]클로저(Closure) 개념

이번 포스팅은 JavaScript의 클로저(Closure)에 대해 소개하며, 클로저를 소개하기 전에 중첩 함수와 함수 반환을 소개합니다. 중첩 함수 JavaScript에서 함수 안에 또 다른 함수를 정의하는 것을 중첩

developer-talk.tistory.com

다음 예제는 메서드 func1()에서 this 값을 저장하는 that이라는 변수를 선언합니다. 그리고 내부 함수인 func2()는 this가 아닌 부모 함수의 변수 that을 접근합니다.

var num = 10;

var obj = {
  num: 1,
  func1: function() {
    var that = this;
    this.num += 1;
    console.log('func1() 호출! this.num의 값: ' + this.num);
    
    function func2() {
      that.num += 1;
      console.log('func2() 호출! that.num의 값: ' + that.num);
    }
    
    func2();
  }
};

obj.func1();

[실행 결과]

위 예제의 실행 결과는 의도했던 값이 출력되었으며, 이렇게 this 값을 다른 변수에 저장하여 내부 함수에서 this 바인딩의 한계를 극복할 수 있습니다.

반응형

댓글