Javascript Function Method
appy, call, bind 메소드는 Function.prototype의 메소드다. 모든 함수는 prototype의 이 메소드들을 상속받는다. apply와 call 메소드는 기본적으로 this로 활용되는 객체와 인수 리스트를 전달받아 함수를 호출하는 본질적인 기능을 가지고 있다.
함수를 생성하고 [[Prototype]] 내부 슬롯을 확인해보면 이미 call, appy, bind 함수가 상속되어 있다.
첫번째 인자로는 해당 함수에 전달할 this 객체를 받는다.
두번째 인자로는 인수 리스트를 받는데, apply는 1개의 인수리스트를 받아 배열로 처리하고, call은 2개 이상의 인수리스트를 받아 쉼표로 구분된 배열을 처리한다.
function getThisBindings(){
return this;
}
const thisArg = { temp : 1};
const args = [1,2,3,4,5]
const args1 = [1,2,3,4,5,6,7,8]
console.log(getThisBindings());
console.log(getThisBindings.apply(thisArg, args))
console.log(getThisBindings.call(thisArg, args, args1))
// apply 메소드
[Arguments] { '0': 1, '1': 2, '2': 3, '3': 4, '4': 5 }
{ temp: 1 }
// call 메소드
[Arguments] {
'0': [ 1, 2, 3, 4, 5 ],
'1': [
1, 2, 3, 4,
5, 6, 7, 8
]
}
{ temp: 1 }
call, apply 용도?
위에서 살펴본 것 처럼 apply와 call 메소드의 본질적인 용도는 함수 자체를 호출하는 것이다. 여기에 this로 연결될 객체를 임의로 연결해줄 수 있다. apply와 call을 대표적으로 사용하는 곳은 유사배열 객체에서 배열 메소드를 사용하는 경우다.
arrayLikeobj() 함수에 인수들을 전달해준다. 전달된 매개변수들은 객체 형태로 전달된다. 매개변수를 Array.prototype.slice() 메소드를 사용하면 TypeError를 반환한다.
function arrayLikeObj(){
console.log(arguments);
const arr = arguments.slice();
console.log(arr);
return arr;
}
arrayLikeObj("a","b","c");
TypeError: arguments.slice is not a function
유사 배열 객체(array like object)에서 배열 메소드를 사용하기 위해서 call 혹은 apply를 사용한다.
function arrayLikeObj(){
console.log(arguments);
const arrCall = Array.prototype.slice.call(arguments);
const arrApply = Array.prototype.slice.apply(arguments);
console.log(arrCall);
console.log(arrApply);
}
arrayLikeObj("a","b","c");
Function.prototype.bind()
bind 메소드는 apply와 call 처럼 함수를 호출하지 않는다. this로 사용할 객체만 전달하는 역할을 한다. bind 메소드를 사용하는 이유는 this와 메소드 내부의 중첩 함수 혹은 콜백 함수 사용시 this 객체가 의도한 대로 연결되지 않는 경우 임의로 this 객체를 연결하기 위해 사용한다.
아래 경우는 함수가 호출되는 시점에 따라 this 객체가 변경되는 것을 확인할 수 있다. 최종적으로 일반 함수로 호출되는 foo의 콜백함수로 전달된 익명함수의 this는 window 전역 객체를 가리키게 된다.
const obj = {
name : "About-Tech",
foo(callback){
// this는 foo 메소드를 호출한 obj 객체를 가리킨다.
setTimeout(callback, 3000);
}
}
obj.foo(function(){
// 일반 함수로 호출되는 현재 시점에서 this는 전역 객체 window를 가리킨다.
// Node.js에서 전역객체 window의 name은 undefined다.
console.log(`[this] : ${this.name}`);
});
[this] : undefined
외부 함수 foo의 this객체와 콜백함수인 익명함수의 this객체를 일치시키기 위해서 bind() 메소드를 사용해서 this객체를 일치시켜준다.
const obj = {
name : "About-Tech",
foo(callback){
setTimeout(callback.bind(this), 300);
}
}
obj.foo(function(){
console.log(`[this] : ${this.name}`);
});
[this] : About-Tech
this 바인딩
Javascript에서 this는 함수가 호출되는 방식에 따라 다르게 바인딩 된다. 따라서 this 객체 바인딩이 상이해지는 시점에서는 Function.prototype.call/apply/bind 메소드를 사용해서 매뉴얼하게 바인딩 작업을 해줘야 의도한 프로그래밍이 가능하다.
함수 호출 방식 | this 바인딩 |
일반 함수 호출 | this = 전역 객체 |
메소드 호출 | this = 메소드를 호출한 객체 |
생성자 함수 호출 | this = 생성자 함수가 생성할 예정인 인스턴스 |
Function.prototype.call/apply/bind에 의한 간접호출 | this = Function.prototype.call/apply/bind에 첫번째 인수로 전달된 this 객체 |
Reference
'Programming' 카테고리의 다른 글
[React] Effect HOOK API useEffect 사용하는 방법 (0) | 2022.05.25 |
---|---|
[Javascript] setTimeout vs setInterval 차이 (debounce, throttle ?) (0) | 2022.05.22 |
[Javascript] AJAX란? (feat. Fetch, XHR, 장점 단점) (0) | 2022.05.20 |
[Network] HTTP Message Request Response 동작 이해하기 (0) | 2022.05.20 |
[Network] URI vs URL ? (0) | 2022.05.20 |
댓글