자바스크립트 함수형 언어에서 this의 특징

보통 자바언어와 같이 class 를 사용하는 내부에서 this 키워드는 해당 객체를 참조하게 된다. 하지만 자바스크립트는 함수형 언어로서 함수 내에서 this를 사용하면 경우에 따라 다른 context를 참조하게 되는데 이를 알아보자.

추가 : this는 객체의 context를 가리키는 키워드로서 자바스크립트에서는 작성 시점이 아닌 런타임 시점에 바인딩 되며 함수 호출 당시 상황에 따라 콘텍스트가 결정된다. 즉, 함수 선언 위치와 상관없이 this 바인딩은 오로지 어떻게 함수를 호출했느냐에 따라 정해진다.

전역(window)를 참조하는 this

일반 전역상태에서 this를 사용하게 되면 전역 객체인 window를 참조하게 된다.

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

단순 호출함수에서의 this

함수를 이름을통해 단순 호출하는 경우에도 window 전역 객체를 참조하게 된다. (node js 에서는 global)

1
2
3
4
5
function f1() {
  return this;
}
console.log(f1 === window);
// true

객체의 메소드 호출에서의 this

어떤 객체의 메서드인 함수를 호출하게 되면 this는 그 객체를 참조한다.

1
2
3
4
5
6
7
8
var o = {
  prop: 37,
  f: function () {
    return this.prop;
  },
};
console.log(o.f());
// 37

new 키워드를 사용한 함수에서의 this

new 키워드를 통해 생성자 방식으로 함수를 생성하면 this 할당된 객체를 참조한다.

1
2
3
4
5
6
function C() {
  this.a = 37;
}
var o = new C();
console.log(o.a);
// 37

bind를 통한 함수호출의 this

bind(someObject) 를 통해 함수를 호출하게 되면 해당 함수의 this는 someObject 를 고정적으로 참조하게 된다.(다시 호출해서 변경 안됨)

1
2
3
4
5
6
7
8
9
10
11
12
function f() {
  return this.a;
}

var g = f.bind({ a: 'azerty' });
console.log(g()); // azerty

var h = g.bind({ a: 'yoo' }); // bind는 한 번만 동작함!
console.log(h()); // azerty

var o = { a: 37, f: f, g: g, h: h };
console.log(o.a, o.f(), o.g(), o.h()); // 37, 37, azerty, azerty

call, apply 를 통한 함수 호출에서의 this

call 이나 apply로 함수를 호출하는 방식은 인자로 전달한 객체를 참조하게 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
function add(c, d) {
  return this.a + this.b + c + d;
}

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

// 첫 번째 인자는 'this'로 사용할 객체이고,
// 이어지는 인자들은 함수 호출에서 인수로 전달된다.
add.call(o, 5, 7); // 16

// 첫 번째 인자는 'this'로 사용할 객체이고,
// 두 번째 인자는 함수 호출에서 인수로 사용될 멤버들이 위치한 배열이다.
add.apply(o, [10, 20]); // 34

화살표 함수(arrow function) 호출에서의 this

화살표 함수의 this는 항상 자신의 유효범위인 정적 범위(lexical context)를 참조한다.

화살표 함수는 call, apply, bind를 사용하더라도 context가 바뀌지 않고 정적 범위만 참조한다. 따라서 call, apply 의 첫 번째 매개변수(context 인자)를 null로 설정해야 한다.

1
2
3
4
5
6
7
8
9
10
11
12
// 객체로서 메서드 호출
var globalObject = this; //현재 전역 context 저장
var foo = () => this;
var obj = { func: foo };
console.log(obj.func() === globalObject); // true

// call을 사용한 this 설정 시도
console.log(foo.call(obj) === globalObject); // true

// bind를 사용한 this 설정 시도
foo = foo.bind(obj);
console.log(foo() === globalObject); // true

함수형 언어에서 어떠한 방식으로 함수를 호출하여 context를 바인딩할지를 아는것이 함수형 언어의 강점을 최대로 활용하는 방식이므로 알아두는게 중요하다고 생각된다.

참고문서 https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Operators/this