Javascript this

Minho Yoo·2022년 8월 22일
1
post-thumbnail

this란?

this란 함수를 호출할 때 생성되는 실행 컨텍스트 객체이다.
this가 가리키는 대상은 어떻게 this가 호출되는지에 따라 다른데 아래 상황별로 의미를 나눌 수 있다.

  1. 전역 공간에서의 this
  2. 메서드로서 호출할 때 내부에서의 this
  3. 함수로서 호출할 때 내부에서의 this
  4. 콜백 함수 호출 시 내부에서의 this
  5. 생성자 함수 내부에서의 this

전역 공간에서의 this

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

console.log(this); // {alert: f(), atob: f(), blur: f(), ...}
console.log(window); // {alert: f(), atob: f(), blur: f(), ...}
console.log(this === window); // true

구글 크롬에서 F12키를 눌러 콘솔에 this를 입력해보면 Window가 나오는것을 볼 수가 있다.

우리가 변수 a를 선언하고 변수 a에 1을 할당하면, 자바슴클비트 엔진은 전역 객체 안의 프로퍼티로 a를 할당한다.

var a = 1;
console.log(a); // 1
console.log(window.a); // 1
console.log(this.a); // 1

전역 프로퍼티 안에 변수 a를 선언하였기 때문에 window.a를 찍던 this.a를 찍던 결과값은 똑같이 나온다.

  • ES6 이후 var 대신 let과 const를 쓰면다르게 나온다.
let a= 1;
console.log(a);
console.log(window.a); // undefined
console.log(this.a); // undefined

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

// 일반 함수로 호출하는 경우
var handleThis = function(x) {
  console.log(this, x);
}

handleThis(1);

// 메서드로 함수를 호출하는 경우
var obj = {
  thisMethod: handleThis
};

obj.thisMethod(2); // { thisMethod: f } 2
obj['thisMethod'](2); // { thisMethod: f } 2

일반 함수로 호출하는 경우와 메서드로 함수를 호출하는 경우에 함수의 값은 똑같지만, this는 서로 다르다.

// 메서드 내부에서의 this
var obj = {
  methodA: function() {
    console.log(this);
  },
  inner: {
    methodB: function() {
      console.log(this);
    }
  }
};

obj.methodA() // { methodA: f, inner: {...} } === obj
obj['methodA']() // { methodA: f, inner: {...} } === obj

obj.inner.methodB() // { methodB: f } === obj.inner
obj.inner['methodB']() // { methodB: f } === obj.inner
obj['inner'].methodB() // { methodB: f } === obj.inner
obj['inner']['methodB']() // { methodB: f } === obj.inner

메서드 내부에서의 this는 호출한 주체에 대한 정보이다.

호출된 주체란 함수명(프로퍼티명) 바로 앞의 객체를 뜻한다.
즉 마지막 점앞에 명시된 객체를 말한다.
obj.methodA();

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

함수로만 호출할 때는 this가 지정되지 않는다.

var obj1 = {
  outer: function() {
    console.log(this)  // obj1 
    var innerFunc = function () {
      console.log(this)  // Window, obj2
    }
    innerFunc()  // 2번 
    var obj2 = {
      innerMethod: innerFunc
    }
    obj2.innerMethod()  // 3번
  }
}

obj1.outer()  // 1번

1번은 메서드로 호출하였기에 outer 함수의 this는 obj1이 바인딩된다.
2번은 innerFunc() 라는 객체가 아닌 일반 변수에 담아 호출하였기에 this는 전역 객체(window)가 찍힌다.
3번은 obj2.innerMethod()는 위에서 선언한 innerFunc() 함수를 obj2라는 객체의 innerMethod라는 프로퍼티에 할당해서 호출하였기 때문에 this는 obj2가 바인딩된다.

var obj1 = {
  outer: function() {
    console.log(this)  // { outer: f }
    var innerFunc = function () {
      console.log(this)  // Window
    }
    innerFunc()
    var self = this;
    var innerFunc2 = function () {
      console.log(self)  // { outer: f }
    }
    innerFunc2()
  }
}

obj1.outer()

위 방법은 함수 내부에서 직진 컨텍스트의 this를 바라보게 하는 방법이다.
self라는 변수를 선언하여 self의 값을 this로 지정을 하여 사용하는 방법인데 단순히 상위 스코프의 this를 저장해서 내부함수에서 활용하기 위한 수단이다.

ES6 부터는 arrow function을 이용하면 self라는 변수를 만들 필요 없이 this가 지목이 된다.

var obj = {
  outer: function () {
    console.log(this)           // 1. { outer: f }
    // arrow function 사용법
    var innerFunc = () => {
      console.log(this)         // 2. { outer: f }
    }
    innerFunc()
  }
}
obj.outer()

콜백 함수 호출 시 그 함수 내부에서의 this

콜백 함수(Call back function)도 기본적으로 함수이기 때문에, this를 지정하지 않으면 전역객체(window)를 바라본다.

setTimeout(function() {
  console.log(this);
}, 300);

[1, 2, 3, 4, 5].forEach(function(x) {
  console.log(this, x);
})

document.body.innerHTML += '<button id="a">Click !</button>'
document.body.querySelector('#a').addEventlistener('click', function() {
  console.log(this, a);
});

setTimeout() 함수에서는 this를 지정하지 않았기 때문에 전역객체가 출력된다.
forEach() 함수도 this를 지정하지 않았기 때문에 전역객체가 출력된다.
addEventlistener()은 앞에 지정한 객체가 있으므로 해당 엘리먼트와, 이벤트 객체가 출력된다.

생성자 함수 내부에서의 this

생성자 함수란 어떤 공통된 성질을 지니는 객체들을 생성하는 데 사용하는 함수이다.
생성자를 클래스(class)라고 하고 클래스를 통해 만든 객체를 인스턴스(instance)라고 한다.
생성자 함수 내부에서의 this는 새로 만들 구체적인 인스턴스 자신이 된다.

var Cat = function(name, age) {
  this.bark = '야옹',
  this.name = name,
  this.age = age,
}
  
var choco = new Cat('초코', 7);
var nabi = new Cat('나비', 5);
  
console.log(choco, nabi);

// Cat { bark: '야옹', name: '초코', age: 7 }
// Cat { bark: '야옹', name: '나비', age: 5 }

Cat을 호출하면 Cat에 대한 prototype 프로퍼티가 있는 객체가 만들어지고, 미리 준비된 공통 속성을 해당 객체(this)에 부여한다.
그래서 this는 각각의 인스턴스를 가르키게 된다.

profile
Always happy coding 😊

0개의 댓글