Function.prototype.call() 메서드
Function.prototype.call() 메서드
call()은 Function 인스턴스의 메서드로, 지정된 this 값과 개별적으로 제공된 인자들을 사용해 해당 함수를 호출합니다. 함수를 객체의 프로퍼티로 먼저 붙이지 않고도 기존 함수의 this를 임의의 값으로 지정해 호출할 수 있어, 한 객체의 메서드를 범용 유틸리티 함수처럼 재사용할 때 유용합니다.
본문
개요
call() 메서드는 주어진 this 값과 개별적으로 제공된 인자들을 사용해 이 함수를 호출합니다. 하나의 객체를 다른 객체의 생성자/메서드에 빌려쓰는 "메서드 빌려오기(method borrowing)" 패턴의 핵심입니다.
기본적인 사용 예는 다음과 같습니다.
function Product(name, price) {
this.name = name;
this.price = price;
}
function Food(name, price) {
Product.call(this, name, price);
this.category = "food";
}
console.log(new Food("cheese", 5).name);
// Expected output: "cheese"
구문(Syntax)
call(thisArg)
call(thisArg, arg1)
call(thisArg, arg1, arg2)
call(thisArg, arg1, arg2, /* …, */ argN)
매개변수
- thisArg —
func를 호출할 때this로 사용할 값입니다. 함수가 strict mode가 아니면null과undefined는 전역 객체로 치환되고, 원시 값은 객체로 변환됩니다. - arg1, …, argN (선택) — 함수에 전달할 인자들입니다.
반환값 — 지정된 this 값과 인자들로 함수를 호출한 결과입니다.
설명(Description)
참고: 이 함수는 함수 인자를 개별 리스트로
call()에 전달한다는 점을 제외하면apply()와 거의 동일합니다.apply()에서는 인자들이 배열 같은 하나의 객체로 묶여 전달됩니다. 예를 들어func.call(this, "eat", "bananas")는func.apply(this, ["eat", "bananas"])와 대응됩니다.
일반적으로 함수를 호출할 때 함수 내부의 this 값은 해당 함수가 접근된 객체입니다. call()을 사용하면 함수를 먼저 객체의 프로퍼티로 붙일 필요 없이, 기존 함수를 호출할 때 this로 임의의 값을 지정할 수 있습니다. 이로써 한 객체의 메서드를 범용 유틸리티 함수로 사용할 수 있게 됩니다.
경고: 생성자 체이닝(예: 상속 구현)에
call()을 사용하지 마십시오. 이는 생성자 함수를 일반 함수로 호출하게 되어new.target이undefined가 되고, 클래스는new없이는 호출할 수 없으므로 오류를 던집니다. 대신Reflect.construct()나extends를 사용하십시오.
예제
call()로 함수를 호출하면서 this 값 지정하기 — 아래 예에서 greet가 obj의 메서드가 아님에도 불구하고 greet를 호출하면 this의 값이 객체 obj에 바인딩됩니다.
function greet() {
console.log(this.animal, "typically sleep between", this.sleepDuration);
}
const obj = {
animal: "cats",
sleepDuration: "12 and 16 hours",
};
greet.call(obj); // cats typically sleep between 12 and 16 hours
첫 번째 인자 없이 call()로 함수 호출하기 — 첫 번째 thisArg 매개변수를 생략하면 기본값은 undefined입니다. 비-strict 모드에서는 this 값이 globalThis(전역 객체와 유사)로 치환됩니다.
globalThis.globProp = "foo";
function display() {
console.log(`globProp value is ${this.globProp}`);
}
display.call(); // Logs "globProp value is foo"
strict mode에서는 this 값이 치환되지 않으므로 undefined로 유지되어 예외를 던집니다.
"use strict";
globalThis.globProp = "foo";
function display() {
console.log(`globProp value is ${this.globProp}`);
}
display.call(); // throws TypeError: Cannot read the property of 'globProp' of undefined
메서드를 유틸리티 함수로 변환 — call()은 this가 함수가 접근된 값이 아니라 일반 매개변수로 전달된다는 점을 제외하면 일반 함수 호출과 거의 동등합니다. 이는 범용 유틸리티 함수의 방식과 유사합니다 — array.map(callback) 대신 map(array, callback)처럼 사용하여, 배열이 아닌 유사 배열 객체에도 map을 쓸 수 있게 합니다.
Array.prototype.slice()를 유사 배열 객체를 실제 배열로 변환하는 데 사용하고 싶다면:
const slice = Array.prototype.slice;
// …
slice.call(arguments);
slice.call을 저장해 일반 함수로 호출할 수는 없습니다. call() 메서드도 역시 자기 this 값을 읽기 때문입니다. 이때는 bind()를 써서 call()의 this 값을 바인딩할 수 있습니다.
// Same as "slice" in the previous example
const unboundSlice = Array.prototype.slice;
const slice = Function.prototype.call.bind(unboundSlice);
// …
slice(arguments);