JavaScript의 this

자바스크립트에서 this의 바인딩은 함수의 호출 방식에 따라 결정된다.

  • 객체의 메서드 호출
  • 일반 함수 호출
  • 생성자 함수의 호출
  • callapply를 이용한 this 바인딩
  • ES6의 화살표 함수

객체의 메서드 호출

var obj = {
  organization: "Im-D",
  sayHello: function() {
    return "Welcome to " + this.organization;
  }
};

console.log(obj.sayHello());

객체의 메서드를 호출할 때 this해당 객체에 바인딩된다.

일반 함수 호출

var organization = "Im-D";

function sayHello() {
  var organization = "Kyonggi";
  return "Welcome to " + this.organization;
}

console.log(sayHello());

일반 함수를 호출할 때, 자바스크립트의 this전역 객체(window 객체)에 바인딩 된다.

생성자 함수의 호출

function Organization(name, country) {
  this.name = name;
  this.country = country;
}

var imD = new Organization("Im-D", "South Korea");
var kyonggi = Organization("Kyonggi", "South Korea");

console.log(imD);

console.log(kyonggi);

생성자 함수를 new키워드를 통해 호출할 경우, 새로 생성되는 빈 객체에 바인딩 된다. 단, new키워드를 사용하지 않으면 this는 전역객체에 바인딩된다.

call, apply, bind를 활용한 this바인딩

call

function Module(name) {
  this.name = name;
}

Module.prototype.getName = function() {
  const changeName = function() {
    console.log(this);
    return this.name + "입니다.";
  };
  // return changeName.call(this, 1,2,3,4);
  return changeName.call(this);
};

const module = new Module("BKJang");

console.log(module.getName());

apply

function Module(name) {
  this.name = name;
}

Module.prototype.getName = function() {
  const changeName = function() {
    console.log(this);
    return this.name + "입니다.";
  };

  // return changeName.apply(this, [1,2,3,4]);
  return changeName.apply(this);
};

const module = new Module("BKJang");

console.log(module.getName());

또한 call이나 apply메서드를 활용하여 유사배열 객체를 일반 배열로 바꿀 수도 있다.

function sayHello() {
  console.log(arguments);
  var args = Array.prototype.slice.apply(arguments);
  console.log(args);
}

sayHello("Im-D", "South Korea");

callapply는 내부 함수에서 사용할 this를 설정하고 함수 바로 실행까지 해주지만, bindthis만 설정해주고 함수 실행은 하지 않고 함수를 반환한다.

function Module(name) {
  this.name = name;
}

Module.prototype.getName = function() {
  const changeName = function() {
    console.log(this);
    return this.name + "입니다.";
  };
  let bindChangeName = changeName.bind(this);
  return bindChangeName();
};

const module = new Module("BKJang");

console.log(module.getName());

화살표 함수

var obj = {
  organization: "Im-D",
  outerFunc: function() {
    var that = this;
    console.log(this.organization);

    innerFunc = function() {
      console.log(that.organization);
      console.log(this.organization);
    };

    innerFunc();
  }
};

obj.outerFunc();
var obj = {
  organization: "Im-D",
  outerFunc: function() {
    console.log(this.organization);

    innerFunc = () => {
      console.log(this.organization);
    };

    innerFunc();
  }
};

obj.outerFunc();

ES5에서는 원래 내부 함수에서의 thiswindow객체에 바인딩 되었기 때문에 var that=this;와 같이 선언하여 thatthis를 할당하고 내부 함수에서는 that을 활용하는 방식을 사용했었다.

하지만, ES6에서 등장한 화살표 함수에서는 this가 무조건 상위 스코프의 this를 가리킨다. 이에 따라 내부함수에서 var that=this;와 같은 구문을 사용할 필요가 없다. 이처럼 정적으로 this가 바인딩되기 때문에 Lexical this라고 한다.


🙏 Reference