Function에 구현되어 있는 bind 함수는 두 가지 용도로 사용할 수 있다.
1) 함수의 수신자 객체 지정 (이펙티브 자바스크립트 아이템 25)
this는 자바스크립트에서의 기묘한 개념 중 하나다. 흔히 접하는 언어들과 달리 자바스크립트의 Scope는 코드 블록( {}로 구분되는 )이 아닌 '객체' 단위다. 때문에 아래와 같은 이상한 현상이 발생한다.
let buffer = {
entries: [],
add: function(s) {
this.entries.push(s);
}
};
buffer.add(100); // 100 추가
console.log(buffer.entries); // [100]
(function () {
this.entries = [];
let x = buffer.add;
x(300); // ?????
})();
console.log(buffer.entries); // [100]
두번째 익명 함수 영역에서 새로운 배열 entries를 선언하고 buffer의 add 함수를 x에 할당했다. 이 시점에서 buffer.add 함수의 Scope는 buffer가 아닌 익명 함수가 되기 때문에 x 함수를 실행해도 buffer의 entries에는 값이 추가되지 않는다.
그렇다면 함수를 파라미터로 받는 고차 함수는 어떨까?
var arr = [1, 2, 3];
arr.forEach(buffer.add);
console.log(buffer.entries); // [100]
고차 함수에서도 위의 익명 함수와 마찬가지로 전달된 함수는 새로운 Scope에서 실행된다. 그렇기 때문에 buffer 객체의 entires 프로퍼티에 값이 추가되지 않는다.
이 때 bind 함수를 이용해 명시적으로 수신자 객체(this)를 지정한 새로운 함수를 만들 수 있다.
var arr = [1, 2, 3];
buffer.entries = [];
let bindAdd = buffer.add.bind(buffer); // 이 함수의 `this`는 buffer 객체를 가리킨다.
arr.forEach(bindAdd);
console.log(buffer.entries); // [1, 2, 3]
이렇게 만든 함수는 this가 명시적으로 선언되었기 때문에 더 안전하고, 의도한 결과를 얻어낼 수 있다.
2) 함수의 커링 (이펙티브 자바스크립트 아이템 26)
함수형 언어에 필수적으로 구현되어 있는 커링이 자바스크립트에서는 조금 색다르게 지원된다. 위에서 수신자 객체(this)를 지정할 때 사용한 bind 함수를 이용하는 것이다.
bind 함수를 살펴보면 bind 함수는 수신자 객체뿐만 아니라 추가적인 파라미터 배열을 입력받는데, 입력받는 파라미터 배열은 함수의 파라미터로 전달된다.
코드로 보면 훨씬 이해하기 쉽다.
let addXYZ = function (x, y, z) {
return x + y + z;
};
let add100YZ = addXYZ.bind(null, 100);
let add100200Z = add100YZ.bind(null, 200);
console.log(addXYZ(1, 2, 3)); // 6
console.log(add100YZ(10, 10)); // 120
console.log(add100200Z(100)); // 400
여기서 재미있는 점은 bind의 첫 번째 파라미터, 그러니까 수신자 객체(this)는 null로 입력된다. null로 입력된 this는 전역 변수로 선언되는데, 아래와 같은 코드로 확인해 볼 수 있다.
let thisName = function (name) {
this.name = name;
};
let bindThisName = thisName.bind(null, 'Jack');
bindThisName();
console.log(this.name); // Jack
3. bind된 함수의 toString()
bind로 커링된 함수는 toString()을 호출해도 커링된(혹은 수신자 객체가 지정된) 함수가 출력되지 않는다.
let blahblah = function (str) {
console.log(str);
};
let bindBlah = blahblah.bind(null, 'hello world!');
console.log(bindBlah.toString()); // function () { [native code] }
이펙티브 자바스크립트에서 그 답을 찾을 수 있다.
"많은 호스트 환경에서, bind 함수는 또 다른 프로그래밍 언어(일반적으로 C++)로 구현되었기 때문에, 실행 환경에 보여주기 위한 자바스크립트 코드를 전혀 가지지 않는 컴파일된 함수를 생성한다."
'ECMAScript | TypeScript' 카테고리의 다른 글
ECMAScript 5.1로 만든 조합(Combination) 함수 (0) | 2017.09.13 |
---|---|
ESCMAScript, Proxy와 Proxy Handler (0) | 2017.09.11 |
ECMAScript, 딕셔너리와 Map (0) | 2017.08.21 |
Typescript의 Decorator - 2. Property Decorator, 간단한 Dependency Injection (0) | 2017.08.15 |
Typescript의 Decorator - 1. Class Decorator (0) | 2017.08.13 |