본문 바로가기
관리자

Programming-[Frontend]/Javascript

Javascript / 함수 / call, apply, bind

728x90
반응형

 

1. call과 apply method

지난 this에 관한 글에서 일반적으로 this는 전역객체나 부모객체를 가리키는 반면,

call, apply는 사용자가 정해주는 객체를 this로 취급한다는 것을 배웠다.

(Javascript / Execution context, this)

 

call, apply, bind는 함수를 호출하는 또 다른 방법으로,

 

함수이름.call/.apply/.bind(thisArg, 인자)

 

로 표현된다.

 

만약 첫번째 인자인 객체를 입력하지 않으면, 이 메소드들은 자동으로 전역객체인 window를 가리키게 된다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
let a = {
    food: 'Cheese Burger' 
};
 
let b = {
    food: 'Chicken',
    eat: function() {
        console.log(this.food + ' 를 선택하셨습니다.');
    }
};
 
b.eat(); // 결과 : 'Chicken 를 선택하셨습니다.'
 
 
b.eat.call(a); // 결과 : 'Cheese Burger 를 선택하셨습니다.'
cs

b.eat()는 'b'라는 객체에서 'eat'라는 속성값을 조회하고, 그것이 함수라면 실행한다.

여기서 this.food를 만나게 되는데, method 조회로 호출(b.eat) 되었으므로

직계 부모요소인 b를 this로 인식한다.

따라서 this.food  === b.food는 'Chicken'이기 때문에 'Chicken' 를 선택하셨습니다.' 가 출력된다.

 

b.eat.call(a) 에서는 b.eat의 'this에 대한 대상 (thisArg)'을 a로 지정한다.

따라서 b.eat의 this.food === a.food가 되어, 'Cheese Burger'를 선택하셨습니다.'가 출력된다.

 

 


 

 

1
2
3
4
5
6
7
8
9
10
function add(x, y) {
  this.val = x + y;
  console.log(this.val);
}
 
let obj = { val: 0 };
 
add.call(obj, 28);  // 결과 : 10
obj  // 결과 : {val : 10 } // val에 10의 결과값이 담김.
 
cs

 

>> add 라는 함수를 호출하는데, this는 obj로 하겠다.

그리고 함수에 들어가는 인자는 2, 8로 하겠다.

 

add.call 에서 add 함수가 호출되는 시점의 this는 obj 그 자체가 된다.

즉, this.val === obj.val = x +y 가 되고, x = 2, y = 8로 인자를 넣어줬으므로,

결과는 obj = {val : 10}이 된다.

 

>>obj = { val : 0 } 이였는데, add.call(obj, 2, 8); 이후 obj = { val : 10 } 이 됨.

 

 


 

2. call과 apply method의 차이점

 

call과 apply는 두번째 파라미터로 받는 '인자' 부분이,

call은 인수들의 나열 형태로, apply는 배열 형태로 주어져야 한다는 차이가 있을 뿐이다.

 

1
2
3
4
5
6
7
8
9
function sum(a, b, c) {
  return a + b + c
}
 
sum.call(null123)
//결과 : 6
 
sum.apply(null[123])
//결과 : 6
cs

- null : sum이라는 함수를 호출하는 과정에 call 이나 apply를 적용하는데, sum 함수에는 this가 없으므로

call과 apply에 this를 적을 필요가 없다. 그래서 null을 사용하였다.

null 이 아니라 그 무엇이 되더라도, 상관없이 sum 함수는 작동한다.

(number, Boolean, NaN, undefined, null 등. 그래도 그냥 아무렇게나 변수처럼 문자를 쓰면 'not defined' 에러가 나긴 함)

 

 

 

1
2
3
4
5
6
7
8
let sum = function add(x, y) {
  sum = x + y;
  console.log(`Is ${sum} same with ${this.result}?`);
}
let obj = {result : 10};
 
sum.apply(obj, [40,60])
// 결과 : Is 100 same with 10?
cs

sum = 40 + 60 이고,

sum.apply 호출 시점에 this.result === obj.result = 10이 된다.

 

 

 


 

3. Bind method

 

bind 함수는 특정 함수의 객체의 this를 특정 객체의 값으로 묶고(binding), 하나의 고정된 변수(함수)로 만들어 버린다.

함수에 call 이나 apply를 적용한 결과 자체를 변수로 지정할 수 없지만,

bind를 사용하면 함수에 특정 this값을 적용한 결과를 변수에 지정할 수 있게 된다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
let burger = {
    food : 'Cheese Burger',
    drink : 'Sprite'
    };
 
let chicken = {
    food : 'Fried Chicken',
    drink : 'Coke'
    }
 
function eat() {
        console.log(this.food + ' 를 선택하셨습니다.');
    }
 
// Case 1) bind
let burgerMania1 = eat.bind(burger)  // eat 함수의 this.food를 burger.food로 고정시켜서 하나의 변수(함수)로 만들어버림
burgerMania1() // 결과 : Cheese Burger 를 선택하셨습니다.
burgerMania1.call(chicken)  // 결과 : Cheese Burger 를 선택하셨습니다. 
// bind에서 this가 고정되어 변경되지 않음. burgerMania1은 Cheese Burger만 먹게 됨...
>> 물론, burgerMania1 = eat.bind(chicken) 으로 재지정해주면 변경 가능하다.
 
// Case 2) call
let burgerMania2 = eat.call(burger)  //결과 : Cheese Burger 를 선택하셨습니다.
//지정된 것이 아니라 단순히 eat.call(burger)의 결과가 실행된 것
burgerMania2()  // 결과 : 변수(함수)로 지정이 안됨 // burgerMania2의 결과 : undefined.
burgerMania2.call(chicken) // 결과 Uncaught TypeError: Cannot read property 'call' of undefined
cs

 


 

4. Bind method 사용 사례

this의 값이 어떤 과정을 거치면 바뀌어버리는 경우 bind를 사용할 수 있다.

대표적 사례로, setTimeout()의 경우 실행 시에 this를 window로 변경하므로, bind를 통해서 명시적으로 this를 다시 지정해줄 필요가 있다.

( setTimeout(callback, args))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
let burger = {
    food : 'Cheese Burger',
    drink : 'Sprite'
    };
 
let chicken = {
    food : 'Fried Chicken',
    drink : 'Coke'
    }
 
function eat() {
        console.log(this.food + ' 를 선택하셨습니다.');
    }
 
// Case 1. bind 없이 실행
setTimeout(eat, 1000)
// 결과 : 1초 후 'undefined 를 선택하셨습니다.' 라고 출력됨
 
 
// Case 2, bind와 함께 실행
setTimeout(eat.bind(chicken), 1000)
// 결과 : 1초 후 'Fried Chicken' 를 선택하셨습니다.'
cs

 

 

다음 글에서는 call, apply의 좀 더 다양한 활용 사례에 대해서 공부해본다.

Javascript / 함수 / call, apply의 활용 ( .call.filter, Math-apply)

728x90
반응형