이전 this의 블로깅에 이어서, call, apply, bind를 이야기 해보겠다.
This가 함수가 호출됨에 따라 객체를 가르켰다면, 이번에는 call, apply, bind는 this의 범위를 특정할 수 있다. 오늘의 블로깅은 여기를 참고했음.
Every JavaScript function is actually a Function object. This can be seen with the code (function(){}).constructor === Function, which returns true.
MDN에서 가져온 함수의 정의(?)다. 해석해보자면,
자바스크립트의 모든 함수는 사실 함수 객체다. 코드로 볼 수 있는데 function(){}).constructor === Function라고 하면 true를 리턴한다.
그러니까 함수 객체이기 때문에, 변수 프로퍼티와 함수 프로퍼티를 갖는다. 그리고 이 함수 프로퍼티를 우리는 메소드라고 부른다.
함수객체는 아래와 같은 메소드를 갖는다. 대표적으로 apply, call, bind, toString이 있다. (그래서 우리가 OOP를 볼때 그렇게도 toString을 찾았던가....?)
그러니까 우리는 함수이름.call(), 함수이름.apply(), 함수이름.bind(), 이렇게 사용할 수 있다.
call, apply, bind는 기본적으로 함수의 실행영역을 지정하는 메소드다. 위 세 개의 함수는 .call/apply/bind()안에 할당되는 첫번째 인자를 this로 간주한다. 함수 자신의 실행"환경"을 외부 this로 설정할 수 있는 것이 주요한 특징이라고 생각하며 된다.
MDN에서 말하길, 두 메소드의 차이점은 아래와 같다.
공통점은 함수를 호출해 실행시킨다는 것이다. 따라서 Call만 기술하겠다.
call()은 이미 할당되어있는 다른 객체의 함수/메소드를 호출하는 해당 객체에 재할당할때 사용됩니다. this는 현재 객체(호출하는 객체)를 참조합니다. 메소드를 한번 작성하면 새 객체를 위한 메소드를 재작성할 필요 없이 call()을 이용해 다른 객체에 상속할 수 있습니다.
MDN에서 말하는 Call()의 역할은 위와 같다.
이에 따른 예시를 살펴 보자.
객체의 생성자 연결(chain)에 call을 사용할 수 있다. 위 예에서, Product 객체의 생성자는 name 및 price 를 매개변수로 정의된다. 다른 두 함수 Food는 this 및 name과 price를 전달하는 Product를 호출합니다. Product는 name 및 price 속성을 초기화한다.
여기서는 this가 Product의 속성을 상속받아오는 역할을 함.
이 부분은 이해를 제대로 하지 못했지만, 요점은 익명함수를 적용할 배열을 지정했다는 것. 따라서 this의 범위를 특정했다는 것만 이해하고 넘어가쟈...
이것도 마찬가지로, greet()라는 함수를 호출하면, this의 범위는 obj로 특정된다.
그러나 .call() 사용하면 This는 전역객체 window에 바인딩되고, strict-mode에서는 undefined가 나온다.
call(apply)과 유사하게 this 및 인자를 바인딩하나 두 메소드의 차이점은 실행시점이다. call(apply)는 엔터를 내려치는 것(??????)과 동시에 함수실행이 되지만, bind는 당장 실행하는 것이 아닌 바인딩된 함수를 리턴하는 메소드다.
보통 setTimeout()에서 많이 쓰는데, 아래와 예제를 보자.
위 예제에서는 box.printAsync()에서 에러가 난다. 왜냐하면 setTimeout에서 this의 디폴트값은 window이기 때문이다. 그렇기 때문에 이 this의 범위를 바꿔줘야한다. 그러나 call/apply는 즉시 실행되기 때문에 setTimeout가 의미가 없다. 따라서 bind를 써서 활용한다.
제대로 작성하면 아래와 같다.
사실 바인드의 예시에는 이벤트 핸들러도 있는데, 아직 확실하게 이해를 못해서 설명을 할 수 없었ㄷ.......
그렇지만 이 포스팅의 이점은 함수는 객체라는 것을 좀 확실하게 정리했다는 것. 이전에 티스토리 포스팅에서 마무리짓지 못하고 임시글로 남겨둔게 마음에 걸렸는데, 이제 하나는 이해하게 돼서 기쁘다.