배경
Storybook 학습 → bind 메소드 → call & apply 먼저 .. → this 개념 부실 ....
this
전역 스크립트가 실행되거나 함수가 호출될 때,
JS 내부 규칙에 따라 동적으로 결정된다
- new 키워드
→ this는 새로 생긴 객체에 묶임 - obj.function() 형태로 메소드로 호출하는 경우
→ this는 function을 프로퍼티로 가지는 객체 - call / apply / bind 사용하는 경우
→ this는 인수로 전달된 객체 - ES6 화살표 함수인 경우
→ this는 상위 스코프의 this - addEventListener 안에서 호출하는 경우
→ this는 event.currentTarget 의 (이벤트 리스너가 부착된) HTML 요소 - 나머지의 경우
→ this는 window 객체 / 엄격 모드일 경우 undefined - ... 이 외의 경우 ...
예외 경우가 많기 때문에, 헷갈릴 가능성이 크다
이노믜 this를 특정시키기 위한 메소드에는 3번 경우의 call & apply 메소드가 있다
1. call
call 메소드는 모든 함수에서 사용할 수 있으며,
this 값 및 인수를 전달해 특정 값으로 지정하여 함수를 호출한다
const jh = {
name: "주함",
};
const dh = {
name: "다헤",
};
function showThisName() {
console.log(this.name);
// 여기서 this는 window
}
showThisName(); // 아무것도 안 나옴
showThisName.call(jh); // 주함
showThisName.call(dh); // 다헤
함수를 호출하면서 call을 사용하고, this로 사용할 객체를 넘기면
해당 함수가 괄호 안에 있는 객체의 method인 것처럼 사용할 수 있다
즉, 새 객체를 위한 메소드를 재작성할 필요 없이 call()을 이용해 다른 객체에 상속할 수 있다
아래는 공식문서의 대표 예시이다
function Product(name, price) {
this.name = name;
this.price = price;
if (price < 0) {
throw RangeError('Cannot create product ' +
this.name + ' with a negative price');
}
}
function Food(name, price) {
Product.call(this, name, price);
this.category = 'food';
}
function Toy(name, price) {
Product.call(this, name, price);
this.category = 'toy';
}
const cheese = new Food('feta', 5);
const fun = new Toy('robot', 40);
func.call( thisArg [, arg1 [, arg2 [, …] ] ] )
call의 첫 번째 매개변수는 this로 사용할 값이고,
매개변수가 더 있으면 호출하는 함수의 인자(argument)로 전달된다.
즉, 두 번째 매개변수부터는 함수가 사용할 매개변수(parameter)를 순서대로 적은 것이다
// update 함수는 생일과 직업을 받아서 객체의 정보를 업데이트 한다
function update(birthday, job) {
this.birthday = birthday;
this.job = job;
};
update.call(jh, 0226, 'student');
console.log(jh); // {name: 'jh', birthday: 0226, job: 'student'}
update.call(dh, 1234, 'teacher');
console.log(dh); // {name: 'dh', birthday: 1234, job: 'sister'}
2. apply
매개변수를 처리하는 방법을 제외하면 call과 완전히 똑같다!!
func.apply(thisArg, [argsArray])
call은 일반적인 함수와 마찬가지로 매개변수를 직접 받지만, apply는 매개변수를 배열로 받는다
function update(birthday, job) {
this.birthday = birthday;
this.job = job;
};
update.apply(jh, [990101, 'student']);
console.log(jh); // {name: '주함', birthday: 0226, job: 'student'}
update.apply(dh, [890202, 'teacher']);
console.log(dh); // {name: '다헤', birthday: 1234, job: 'sister'}
apply는 배열 요소를 함수 매개변수로 사용할 때 유용하다
apply는 두 번째 매개변수로 배열을 전달하면, 그 요소들을 차례대로 인수로 사용한다
const nums = [3, 10, 1, 6, 4];
// 1. spread 연산자
const minNum = Math.min(...nums);
const maxNum = Math.max(...nums);
// 2. apply
// null은 this로 사용될 값인데, min과 max는 this가 필요하지 않아서 아무 값이나 넣은 것
const minNum = Math.min.apply(null, nums);
const maxNum = Math.max.apply(null, nums);
// = Math.max.apply(null, [3, 10, 1, 6, 4]);
// = Math.max.call(null, ...nums);
console.log(minNum);
console.log(maxNum);
활용
배열에 배열을 붙이는 기능도 가능하다!
const array = ['a', 'b'];
const elements = [0, 1, 2];
array.push.apply(array, elements);
console.info(array); // ["a", "b", 0, 1, 2]
push 는 배열에 단일 요소만 추가하고,
concat 은 새 배열을 만들어 반환한다
기존 배열에 배열을추가하고 싶다면? push.apply !
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Function/call
Function.prototype.apply() - JavaScript | MDN
The Simple Rules to 'this' in Javascript
this를 변경하는 call(), apply(), bind()
다음은 bind 박살~.~
'JS, TS' 카테고리의 다른 글
[JavaScript] How to implement Image Compression (5) | 2023.02.21 |
---|---|
[Javascript] Map & Set 객체 살펴보기 (2) | 2022.05.30 |
[Typescript] Enum, Union & intersection Type (3) | 2022.04.14 |
[Javascript] Event Delegation / 이벤트 위임 (0) | 2021.10.10 |
[Javascript] Promise와 Async / Await (0) | 2021.09.05 |