반응형

 

 

자바스크립트에서 this가 가리키는 대상은 동적으로 변합니다.

 

자바스크립트에서 this의 바인딩은 동적입니다. 그래서 this가 어떤 객체를 가리키는지 예측이 어렵다는 단점이 있습니다. 이런 단점을 극복하려면 this를 통제된 패턴으로만 사용하여 바인딩되는 대상을 예측 가능하도록 코드를 작성하는 것이 좋습니다. React.js와 같은 라이브러리를 사용하면 this를 사용할 용도가 명확하게 정해져 있어 통제 가능한 상태의 this만을 사용하기도 합니다. 어쨌든 바닐라 자바스크립트를 기준으로 this의 동적 바인딩에 대해서 정리해보는 시간도 한번 가지면 좋을 것 같아서 포스팅을 시작하게 되었습니다.

 

 

 

this의 바인딩 규칙

 

1. 메소드에서 사용된 this는 자신을 호출한 객체를 가리킨다.

 

* 예시 코드

var cocoder = {
    name : "cocoder"
};
cocoder.method = function(){
    return "My name is " + this.name;
}

console.log(cocoder.method); // My name is cocoder

 

 

2. 함수를 호출할 때 this는 자신을 호출한 객체가 window객체이므로 this는 window 객체를 가리킨다.

 

함수가 객체의 프로퍼티 값인 경우 그 프로퍼티를 메소드라고 합니다. 반면 특정 객체의 프로퍼티가 아닌 그냥 함수는 엄밀히 말하면 전역 객체인 window의 메소드가 됩니다. 따라서 this는 window를 가리키게 됩니다.

 

* 예시 코드

function func(){
  if(window === this){
  	console.log("window === this");
  } 
}
func(); // window === this
window.func(); // 사실은 전역변수 window의 메소드이다.

 

참고로 브라우저에서는 window가 전역 객체이지만 node.js에서는 global이 전역 객체입니다.

 

 

3. 내부 함수에서의 this는 전역 객체 window를 가리킨다.

 

메소드 안에서 내부 함수에서의 this도 자기를 호출한 객체를 가리키지 않고 window를 가리킵니다.

 

* 예시 코드

cocoder.outer = function outer(){
  function inner(){
    console.log(this);
  }
  inner();
}
cocoder.outer(); // window

 

 

4. 내부 함수에서 외부 함수의 this값을 사용하려면 외부 함수의 this를 다른 변수에 할당한 다음 그 변수로 접근해야 한다.

 

말이 조금 복잡한데 메소드의 내부 함수에서도 외부 함수에서의 this, 즉, 메소드를 호출한 객체를 this로 바인딩하여 사용하고 싶다면 외부 함수에서 this를 다른 변수에 할당해서 그 변수를 사용하라는 의미입니다.

 

* 예시 코드

cocoder.outer = function outer(){
  var that = this;
  function inner(){
    console.log(that);
  }
  inner();
}
cocoder.outer(); // cocoder

 

 

5. 생성자 함수로 객체를 생성한 경우 생성자 함수 내의 this는 객체가 생성되었을 때 그 객체를 가리킨다.

 

* 예시 코드

var thisVal = null;
function constructor(){
	thisVal = this;
}
constructor();
console.log(thisVal === window); // 함수의 this는 전역객체 window를 가리킨다. 따라서 출력결과는 true

var obj = new constructor(); // 생성자 내부에서의 this는 그 객체를 가리킨다. 즉, obj에 this가 바인딩됨.
console.log(thisVal === obj); // true

 

 

6. apply, call을 이용하면 this의 값을 마음대로 명시할 수 있다.

 

apply와 call은 this에 바인딩할 객체를 명시하여 함수를 실행시킬 수 있는 Function.prototype 객체의 메소드입니다.

apply와 call은 용도가 똑같은 메소드입니다. 단지 사용법이 약간 다를 뿐입니다. 둘의 차이는 파라미터에 있습니다. 

 

* apply와 call 함수의 파라미터

apply(thisArg, argArray);
call(thisArg, arg, arg, ...);

 

두 메소드 모두 첫 번째 파라미터는 호출한 함수 내부에서 사용한 this에 바인딩할 객체를 받습니다.

그다음 파라미터로는 호출한 함수에 전달될 값들을 받습니다.

apply는 전달될 값으로서 배열을 넣는 것이고,

call은 전달될 값으로서 배열을 넘기는 게 아니라 각각의 파라미터마다 따로따로 값으로 넣습니다.

예를 들면 인자로 1, 2, 3을 전달할 때 두 메소드에서 다음과 같이 사용됩니다.

 

* apply와 call의 파라미터 사용 차이점

function func() {};

func.apply(thisArg, [1,2,3]);
func.call(thisArg, 1, 2, 3);

 

this를 명시하지 않을 수도 있는데 그러려면 null을 넣어주면 됩니다.

 

function sum(a,b){
    return a+b;
}
console.log(sum.apply(null, [1, 2])); // 3

 

 

 

  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기