[JavaScript] this란?

ryan·2021년 1월 29일
6

JavaScript

목록 보기
19/23
post-thumbnail

this란?

javascript에서 함수의 this 키워드는 다른 언어들과 비교하여 조금 다르게 동작한다. 또한 strict modenon-strict mode 사이에서도 조금 다르다.

대부분의 경우, this의 값은 함수를 호출하는 방법에 의해 결정된다. 실행하는 동안의 할당에 의해 설정될 수 없고, 함수가 호출될 때 마다 다를 수 있다. ES5는 함수의 this 값이 함수가 어떻게 호출되었는지 개의치 않고 설정할 수 있는 bind 메소드를 소개했다.

this의 이해

this의 값은 어떻게 변화할까? this가 어떤 값과 연결되는 지는 this의 바인딩을 통해서 확인해 볼 수 있다. 바인딩이란, this의 호출 방식에 따라서 this가 특정 '객체'에 연결되는 것이다. this의 바인딩은 일반 함수 내부, 메서드 내부, 생성자 함수 내부, Call, Apply, Bind를 통한 '호출 방식'으로 나눠서 살펴볼 수 있다.

  1. 일반 함수 내부에서의 this는 글로벌 객체와 바인딩된다.
  2. 메서드 내부에서의 this는 메서드를 호출한 객체와 바인딩된다.
  3. 생성자 함수 내부에서 this는 생성자 함수가 생헐할 인스턴스와 바인딩된다.
  4. Call, Apply, Bind 메서드 사용 시, 메서드에 첫 번째 인수로 전달하는 객체에 바인딩 된다.

1. 일반 함수 내부에서의 this는 글로벌 객체와 바인딩된다.

console.log(this === window); // true;

a = 30;
console.log(window.a); // 30

function x() {
  return this;
}

x() === window; // true

2. 메서드 내부에서의 this는 메서드를 호출한 객체와 바인딩된다.

let ryan = {
  firstName: "Ryan",
  lastName: "Kim",
  driveCar() {
    console.log(`${this.firstName} drives a car.`)
  }
}

ryan.driveCar(); // 'Ryan drives a car.'

3. 생성자 함수 내부에서 this는 생성자 함수가 생성할 인스턴스와 바인딩된다.

function person() {
  this.firstName = "Ryan",
  this.lastName = "Kim",
    this.start = function() {
console.log(`${this.firstName} drives a car.`)};
};

let person1 = new person();
console.log(person1); // person { firstName: 'Ryan', lastName: 'Kim', start: ƒ (), __proto__: person { constructor: ƒ person() } }

4. Call, Apply, Bind 메서드 사용 시, 메서드에 첫 번째 인수로 전달하는 객체에 바인딩 된다.

CallApply 메서드는 기본적으로 함수를 호출하는 역할을 한다. 그렇다면 기존 함수 호출과의 차이점은 무엇일까? 그것은 바로, 해당 메서드를 사용해 함수를 '실행'하면, 함수의 첫 번째 인자로 전달하는 객체에 this를 '바인딩'할 수 있다는 것이다. 이를 통해서 유사 배열 arguments 객체에 배열 메서드를 사용할 수 있다. 반면에, bind는 첫 번째 인자를 this에 바인딩하지만 함수를 실행하지 않으며, 새로운 함수를 반환한다.

Call

Call을 사용하면, 함수를 실행하고 함수의 첫 번째 인자로 전달하는 값에 this를 바인딩한다.

function logName(a, b, c) {
  console.log(this.name);
  console.log(this.nationality);
  console.log(a + b + c);
}

const person = {
  name: 'Ryan',
  nationality: 'South Korea'
}

logName.call(person, 1, 2, 3 );
// 'Ryan'
// 'South Korea'
// 6

Apply

apply를 사용하면 함수를 실행하고 함수의 첫 번째 인자로 전달하는 값에 this를 바인딩한다. call과의 차이점은 인자를 배열의 형태로 전달한다는 것이다. 이 때, 인자로 배열 자체가 전달하는 것이 아니라 배열의 요소들이 값으로 전달된다.

function logName(a, b, c) {
  console.log(this.name);
  console.log(this.nationality);
  console.log(a + b + c);
}

const person = {
  name: 'Ryan',
  nationality: 'South Korea'
}

const nums = [1, 2, 3];

logName.apply(person, nums );
// 'Ryan'
// 'South Korea'
// 6

// 요즘에는 apply를 사용하지 않고, spread operator와 call을 활용한다.
logName.call(person, ...nums);
// 'Ryan'
// 'South Korea'
// 6

bind

bind는 함수의 첫 번째 인자에 this를 바인딩한다는 점은 같지만, 함수를 실행하지 않고, 새로운 함수를 반환한다. 즉, 반환된 새로운 함수를 실행해야 원본 함수가 실행된다.

function logName(a, b, c) { // 원본 함수
  console.log(this.name);
  console.log(this.nationality);
  console.log(a + b + c);
}

const person = {
  name: 'Ryan',
  nationality: 'South Korea'
}

const Ryan = logName.bind(person, 1); // 새로운 함수

Ryan(2, 3);
// 'Ryan'
// 'South Korea'
// 6

Call, Apply, Bind 메서드 정리

Call 메서드는 함수를 실행하고, 첫 번째 인자에 this를 바인딩하며, 이후의 값을 함수의 인자로 전달한다. Apply 메서드는 함수를 실행하고, 첫 번째 인자에 this를 바인딩하며, 이후의 값을 배열의 형태로 받아 차례로 함수의 인자로 전달한다. bind 메서드는 함수를 실행하지 않으며, 첫 번째 인자에 this를 바인딩한 새로운 함수를 반환한다. 각 메서드를 통해 전달할 수 있는 인자의 갯 수에는 제한이 없다.

this 정리

이처럼 this함수 호출 방식에 따라서 동적으로 결정된다. 예시에서 살펴본 것처럼 함수를 일반 함수로 호출할 경우, this는 글로벌 객체를, 메서드로 호출할 경우 이를 호출한 객체를, 생성자 함수를 호출할 경우, 생성자 함수가 생성할 인스턴스를 가리키게 된다. Call, Apply, Bind 메서드 사용 시, 메서드에 첫 번째 인수로 전달하는 객체에 바인딩 된다.

참고

profile
👨🏻‍💻☕️ 🎹🎵 🐰🎶 🛫📷

0개의 댓글