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, 2, 8); // 결과 : 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(null, 1, 2, 3)
//결과 : 6
sum.apply(null, [1, 2, 3])
//결과 : 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)
'Programming-[Frontend] > Javascript' 카테고리의 다른 글
Javascript / 함수 / call, apply의 활용 ( .map.call(.filter.call), Math-apply) (0) | 2020.08.30 |
---|---|
Javascript / 기초 / 삼항연산자 (0) | 2020.08.27 |
Javascript / Array / sort (0) | 2020.08.25 |
Javascript / Execution context, this (0) | 2020.08.24 |
Javascript / API, Server 기초 개념 (0) | 2020.08.24 |