[javascript] This

mook9288·2021년 1월 15일
0

javascript 기초 정리

목록 보기
9/9

This

자바스크립트에서의 this는 어디서든 사용할 수 있고, 상황에 따라 this가 바라보는 대상이 달라진다.
기본적으로 실행 컨텍스트가 생성될 때 함께 생성된다. 즉, this는 함수가 호출될 때 결정된다.
함수 안에서만 사용 가능하고 약속된 변수라고 할 수 있다. 변수처럼 작동하지만, this는 수정될 수 없다.

상황에 따라 달라지는 this

전역 공간에서의 this

  • this는 전역객체(window / global)을 가르킨다.
  • 전역 컨텍스트를 생성하는 주체가 전역객체이기 때문이다.
console.log(this);
console.log(window);
console.log(this === window); // true

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

  • this는 전역객체(window / global)을 가르킨다.
// 함수 내부에서 this 호출
function a() {
  console.log(this);
}
a();

// 외부함수 b의 내부함수 c 내부에서 this 호출
function b() {
  function c() {
    console.log(this);
  }
  c();
}
b();

// d 객체 내의 메소드 e 안에 있는 f함수 내부에서 this 호출
var d = {
  e: function() {
    function f() {
      console.log(this);
    }
    f();
  }
}
d.e();

메소드 호출할 때 메소드 내부에서의 this

  • this는 메소드 호출하는 주체를 가르킨다.
  • 메소드 명 dot 바로 앞이 this가 된다.
var a = {
  b: function() {
    console.log(this);
  }
}
a.b(); // a 객체를 가르킨다. {b: f()}
var a = {
  b: {
    c: function() {
      console.log(this);
    }
  }
}
a.b.c(); // a.b의 객체를 가르킨다. {c: f()}

함수는 전역객체의 메소드다 라고 생각하면 편하다..ㅎ

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

  • this는 기본적으로 함수 내부에서와 동일하다.(기본적으로 함수의 this와 같다.)
  • 제어권을 가진 함수가 callbackthis를 명시한 경우 그에 따른다.
  • 개발자가 this를 바인딩한 채로 callback을 넘기면 그에 따른다.
var callback = function() {
  console.dir(this);
};

var obj = {
  a: 1,
  b: function(cb) {
    cb(); // window
    cb.call(this); // 전혀 다른 결과
  }
};

obj.b(callback);

setTimeout(callback, 100);
setTimeout(callback.bind(obj), 100);


bind가 없었던 시절에는 한 번 더 감싸서 변수를 이용하는 방식으로 활용했다.

생성자 함수 내부에서의 this

  • this는 인스턴스(instance)를 가르킨다.
function Person(n, a) {
  this.name = n;
  this.age = a;
}

var mook = new Person("mook", 30);
console.log(mook);


콜백함수에서의 명시적인 this 바인딩

call, apply, bind 메소드에 대해 이해를 해야한다.

function a(x, y, z) {
  console.log(this, x, y, z);
}

var b = {
  c: "eee"
};

a.call(b, 1, 2, 3);
a.apply(b, [1, 2, 3]);

var c = a.bind(b);
c(1, 2, 3);

var d = a.bind(b, 1, 2);
d(3);

결과는 ▸Object {c: "eee") 1 2 3으로 동일하게 출력된다.

call

func.call(thisArg[, arg1[, arg2[, ...]]])
즉시 호출을 하는 명령이다.
첫번째 인자는 this를 받고, 두번째 인자부터 쭉 나열해서 받는다.

apply

func.apply(thisArg, [argsArray])
즉시 호출을 하는 명령이다.
첫번째 인자는 this를 받고, 두번째 인자는 매개변수를 담은 배열을 받는다.

bind

func.bind(thisArg[, arg1[, arg2[, ...]]])
callapply와 달리 bind는 새로운 함수를 생성(currying)할뿐 호출을 담당하지는 않는다.
첫번째 인자는 this를 받고, 두번째 인자부터 쭉 나열해서 받는다.


예제

this 예제 1

내부함수에서의 우회법

var a = 10;
var obj = {
  a: 20,
  b: function() {
    console.log(this.a); // 20

    function c() {
      console.log(this.a); // 10
    }
    c();
  }
}
obj.b();

obj.b()는 메소드 호출이라 obj 객체를 가리키고, c()는 일반함수 호출이라 전역의 a를 가르킨다.

그렇다면 함수 c안에서 obj을 바로볼 수 있게 this를 사용할 수는 없을까?

결론부터 말하자면, 스코프 체인(Scope Chain)을 이용해 우회가 가능하다.

var a = 10;
var obj = {
  a: 20,
  b: function() {
    var self = this;
    console.log(this.a); // 20

    function c() {
      console.log(self.a); // 10
    }
    c();
  }
}
obj.b();

위와 같이 thisself라는 변수에 담고, 변수 self를 활용하면 내부함수는 자신의 스코프에서 self을 바라보고 찾다가 없으면 스코프 체인을 타고 상위로 올라가며 this를 탐색한다.

this 예제 2

var a = 10;
var obj = {
  a: 20,
  b: function() {
    console.log(this.a);
  },
  c: () => {
    console.log(this.a);
  }
}
obj.b(); // 20
obj.c(); // 10

화살표 함수는 실행컨텍스트 생성시 this를 바인딩하지 않는다.
화살표함수 내부에 this가 존재하지 않기 때문에 스코프 체인에 따라 상위 컨텍스트의 this에 접근하게 된다.
따라서 obj.c()는 상위 컨텍스트의 this가 전역객체를 가리키기 때문에 10이 된다.


🔎 참고자료 🔎
- MDN
- 생활코딩
- PoiemaWeb
- javascript info
- 코어 자바스크립트
- 러닝 자바스크립트
- 인사이드 자바스크립트

0개의 댓글