자바스크립트 this 키워드(feat. call, apply, new)

zenoan·2020년 12월 5일
3
post-thumbnail

'this'

  1. 'this' 키워드는 코드 bit를 실행하는 객체를 말한다.
  2. 모든 javascript 함수실행 시 'this'라는 현재의 execution context(실행되는 맥락)를 참조한다. 단, arrow function의 경우 execution context가 없어서 'this'도 사용을 못한다.
  3. Execution context는 '어떻게 함수를 호출하는지'를 의미한다.

즉, 'this' 키워드는 함수 실행시 결정되므로, 'this'를 이해하기 위해서 함수가 언제, 어떻게, 어디서 호출되는지만 알면된다.


Default binding & implicit binding

Default binding :
this 의 기본값은 global 객체이며 브라우저의 경우에는 window 객체. Strict mode에서는 this 의 기본값은 undefined 이다.
Implicit binding :
객체 내에 method 호출로 객체 속성이 경우에는, 그 객체가 method의 this 객체 또는 execution context 객체가 된다.

function car() {
  console.log(this.name);
}

let name = "bmw";
let obj1 = { name: "tesla" };
let obj2 = { name: "mercedes", };

car();           // "bmw"
obj1.car();      // "tesla"

위 코드에서 car()this.name 을 프린트한다. (현재 this(execution context)의 name 속성의 값을 프린트한다).

  • car() 실행 시, this가 지정되지 않아서 기본값인 global context가 지정된다. 따라서 global context 에서 let name = "bmw"; 변수가 존재함으로 "bmw" 를 프린트한다.
  • obj1.car()의 경우, car()obj1의 method 호출이 된다. Execution context가 obj1 이 되면서, this.nameobj1.name 이 된다.
let obj1 = {
  name: "tesla",
  car: function() {
    console.log(this.name);
  }
}
let obj2 = { name: "mercedes", car: obj1.car };
let name = "bmw";
let car = obj1.car;

car();           // "bmw"
obj1.car();      // "tesla"
obj2.car();      // "mercedes"
  • car() 는 똑같이 default binding 적용하면서 전역 객체에 있는 name을 프린트한다.
  • obj1.car() 도 implicit binding을 적용하면서 obj1 객체에 있는 name을 프린트한다.
  • 다시 강조하자면 언제, 어떻게, 어디서 함수를 호출하는 점이 중요하다. obj2 객체에 obj1.car선언 되어있지만 호출은 하지 않는다. 즉, obj2.car() 의 경우에도 implicit binding을 적용하면서 obj2 객체에 있는 name을 프린트한다.

Explicit binding & fixed binding

Explicit binding :
call 그리고 apply method로 함수를 호출 할 경우, 첫번째 parameter(인자)로 받는 것을 execution context / this 로 binding 한다.

function car() {
  console.log(this.name);
}

let name = "bmw";
let obj = { name: "tesla" }

car();           // "bmw"
car.call(obj);   // "tesla"

위 코드에서는 car 함수를 call() method로 호출하면서 obj 를 첫번째 인자로 넣으면 objthis 객체에 할당되고 "tesla" 가 프린트된다. 즉, obj.name 이 프린트된든 것이다.

Fixed binding :
함수를 언제, 어떻게 호출하든 this 객체를 강제로 그대로 고정되게 할 수 있다.

function car() {
  console.log(this.name);
}

let name = "bmw";
let obj1 = { name: "tesla" }
let obj2 = { name: "mercedes" }

let brandCar = car;
car = function() {
	brandCar.call(obj1);
}

car();           // "tesla"
car.call(obj2);  // "tesla"

위 코드에서는, brandCar.call(obj1)car 에 선언했기때문에 아무리 다른 값을 인자에 넣어도 car 를 호출하면 obj1.name 인, "tesla" 를 프린트 한다.


Javascript "new" keyword

  • 생성자 호출은 new 키워드를 이용하면서 object.method() 와 같이 객체 내에 메소드를 호출하는 방법과 비슷하다. 하지만 new 로 만들어진 객체는 instance 라고 부른다. instance.method() 형태의 호출이다.

  • 함수 앞에 new 키워드가 있으면 그 함수 호출은 constructor 호출로 변환된다. 새로운 객체가 생성 되면서 그 함수의 prototype 속성과 연결된다.

  • 함수 호출 context(맥락)에서 생성된 새로운 객체가 this 가 bind 된다.

  • 만약 함수가 return 하는 것이 없으면 return 되는 것은 this 가 bind된 객체가 된다.

function car() {
  var name = "model S";
  this.brand = "tesla";
  console.log(`${this.name}, ${brand}`);  // undefined, mercedes
}

var name = "S class";
var brand = "mercedes";

obj = new car();
console.log(obj.brand); // "tesla"

위 코드에서는, car 함수가 new 키워드와 호출 되면서, car 함수가 return 하는 함수의 this 객체가 obj 에 할당된다 (obj = car 함수의 this). 따라서 console.log(obj.brand)car 함수 안에 있는 this.brand"tesla"를 프린트한다.

또한 this.brandbrand 변수가 서로 다른 것 처럼 this.name 과 그냥 name 변수는 서로 다른 것이다. this.name 은 선언된 적이 없으므로 undefined 가 된다.

profile
프론트엔드 개발자

0개의 댓글