this와 call, apply, bind, arrow function

🌊·2022년 1월 13일

기술공부

목록 보기
2/4
post-thumbnail

this

  • 객체와 연관이 깊다.
  • 현재 실행 컨텍스트를 기반으로 호출자가 누구인지를 나타내는 식별자.

Context 객체

  • this가 바라보고 있는 어떤 객체

this 동작 방식

기본 바인딩 (전역 객체)

  • 기본적으로 this는 전역 객체(window)를 Context 객체로 갖는다.
  • 전역 스코프에서 정의한 변수들은 전역 객체에 등록된다.
let a = 10; // 전역 스코프에서 정의한 변수

console.log(this.a); // == window.a와 동일하다.

this.b = 10; // 의미적으로 let b = 10과 동일하다.

function f1() {
  return this;
}

// 크롬 개발자 도구
f1() === window; // true

// Node.js
f1() === global; // true

크롬 브라우저의 경우 this를 출력해보면 window 객체가 전역 객체로 나온다.

암시적 바인딩

  • 어떤 객체를 통해 함수가 호출된다면 그 객체가 바로 this의 Context 객체가 된다.
let obj = {
  a: 20,
  func: function() {
    console.log(this.a);
  }
};

obj.func(); // 20

기본 바인딩 + 암시적 바인딩

let b = 100;

let obj = {
  a: 20,
  func: function() {
    console.log(this.b)   
  }
};

obj.func(); // undefined
let globalFunc = obj.func;
globalFunc() // 100

처음 obj.func()는 Context 객체가 obj이므로 obj에서 b 변수를 찾을 수 없다.
하지만 globalFunc는 전역스코프에서 정의한 변수이기 때문에 Context 객체가 window 객체이다. window 객체에서 b가 선언되었기 때문에 해당 값을 출력할 수 있다.

this는 어디서 호출 되었는지가 매우 중요하다.

let obj = {
  func: function() {
    return this;
  }
};

let obj2 = {
  method: obj.func
};

console.log( obj2.method() === obj2 ); // true
console.log( obj.fn() === obj ); // true

this가 obj2.method로 부터 호출을 받았기 때문에 this의 Context 객체는 obj2가 맞다.
obj.fn()도 obj.fn()로 부터 호출을 받았기 때문에 해당 this의 Context 객체는 obj이다.

명시적 바인딩

  • 함수(함수 객체)는 call, apply, bind 메소드를 가지고 있는데, 첫 번째 인자로 넘겨주는 것이 this Context 객체가 된다.

call(), apply()

  • this의 값을 한 문맥에서 다른 문맥으로 넘기려면 사용한다.
  • 첫 번째 매개변수로 객체를 제공하면 this가 그 객체에 묶인다.
let obj = { txt: 'in Obj'};

let txt = 'global';

function func() {
  return this.txt;
}

func(); // global
func().call(obj); // in Obj
func().apply(obj); // in Obj

call()

function add(c, d) {
  return this.a + this.b + c + d;
}

let o = {a: 1, b: 3};

add.call(o, 5, 7); // 16

첫 번째 매개변수 뒤에 이어지는 인수들은 함수 호출에 사용할 매개변수이다.

apply()

function add(c, d) {
  return this.a + this.b + c + d;
}

let o = {a: 1, b: 3};

add.apply(o, [10, 20]);

call과 apply의 유일한 차이점은 apply는 인자를 배열로 만들어서 넣는다.

bind()

  • 메서드가 호출되면 새로운 함수를 생성한다.
  • 함수가 가리키는 this만 바꾸고 호출하지는 않는 것이다.
  • call과 apply와 비슷하지만 호출은 하지 않고 함수만 반환한다.
this.x = 9;
let obj = {
  x: 81,
  getX: function () {
    return this.x;
  },
};

obj.getX(); // 81
let globalfunc = obj.getX;

let bindFunc = globalfunc.bind(obj);
bindFunc(); // 81

bind 함수에서 obj와 바인딩 된 this가 있는 새로운 함수를 생성한다.
bindFunc에서 this.x는 obj와 바인딩 된 x를 가리킨다.
만약 obj2 객체에서 x가 40이고 bindFunc이 obj2를 바인딩한 새로운 함수를 생성하면 obj2의 x를 가리키게 된다.

화살표 함수에서 this

  • 화살표 함수에서 this는 자신을 감싼 정적 범위이다.
  • call(), bind(), apply()를 사용해 호출 할 때 this 값을 인수로 넘겨줘도 무시된다.
  • function 키워드는 해당 객체를 바인딩하여 this의 값을 변경하는 것
  • 화살표 함수는 상위 객체의 this를 그대로 이어 받아서 (스스로의 this 바인딩을 제공하지 않는다). 사용한다.
var obj = {
 i:10,
 b: () => console.log (this.i,this), //undefined, window
 c: function() {
  console.log(this.i, this) //10, obj
  }
} 

화살표 함수는 this를 가지지 않는 것은 아니다. 해당 객체보다 상위 객체의 this를 그대로 이어 받는다.
새롭게 해당 객체를 바인딩하지 않기 때문에 화살표 함수에서의 this는 function 키워드의 this와 다르게 나타난다.

출처
https://velog.io/@nayeon/Javascript%EC%97%90%EC%84%9C%EC%9D%98-this-%EC%99%80-call-apply-bind-%EB%A9%94%EC%84%9C%EB%93%9C

0개의 댓글