함수 사용 call
과 apply
호출 의 차이점은 무엇입니까 ?
var func = function() {
alert('hello!');
};
func.apply();
vs func.call();
위에서 언급 한 두 가지 방법간에 성능 차이가 있습니까? 언제 call
이상 을 사용 하는 것이 가장 apply
좋습니까?
답변
차이점은 배열로 apply
함수를 호출 할 수 있다는 것입니다 arguments
. call
매개 변수를 명시 적으로 나열해야합니다. 유용한 니모닉은 ” 에 대한 rray와 C 에 대한 C OMMA.”
apply and call 에 대한 MDN 설명서를 참조하십시오 .
의사 구문 :
theFunction.apply(valueForThis, arrayOfArgs)
theFunction.call(valueForThis, arg1, arg2, ...)
또한 ES6부터 함수 spread
와 함께 사용할 수 있는 배열 가능성이 있습니다 . 여기서call
호환성을 확인할 수 있습니다 .
샘플 코드 :
function theFunction(name, profession) {
console.log("My name is " + name + " and I am a " + profession +".");
}
theFunction("John", "fireman");
theFunction.apply(undefined, ["Susan", "school teacher"]);
theFunction.call(undefined, "Claude", "mathematician");
theFunction.call(undefined, ...["Matthew", "physicist"]); // used with the spread operator
답변
K. Scott Allen 은이 문제에 대해 좋은 글 을 남겼 습니다.
기본적으로 함수 인수를 처리하는 방법이 다릅니다.
apply () 메서드는 call ()과 동일하지만 apply ()에는 두 번째 매개 변수로 배열이 필요합니다. 배열은 대상 메소드의 인수를 나타냅니다. “
그래서:
// assuming you have f
function f(message) { ... }
f.call(receiver, "test");
f.apply(receiver, ["test"]);
답변
각 함수의 사용시기에 대한 부분에 대답하려면 apply
전달할 인수의 수를 모르거나 인수가 이미 배열 또는 배열과 같은 오브젝트 ( arguments
자신의 인수를 전달 하는 오브젝트)에있는 경우 사용하십시오. call
인수를 배열로 랩핑 할 필요가 없으므로 그렇지 않으면 사용하십시오 .
f.call(thisObject, a, b, c); // Fixed number of arguments
f.apply(thisObject, arguments); // Forward this function's arguments
var args = [];
while (...) {
args.push(some_value());
}
f.apply(thisObject, args); // Unknown number of arguments
예를 들어 인수를 전달하지 않으면 함수를 호출 하기 call
때문에 선호 합니다. 존재하지 않는 인수에 함수를 적용 하고 있음을 의미합니다 .apply
apply
인수를 사용하여 배열에서 래핑하는 경우 (예 : f.apply(thisObject, [a, b, c])
대신 f.call(thisObject, a, b, c)
)를 제외하고는 성능 차이가 없어야합니다 . 나는 그것을 테스트하지 않았으므로 차이점이있을 수 있지만 브라우저마다 매우 다를 수 있습니다. 그것은 가능성이 높습니다 call
이미 배열의 인수를하지 않는 경우입니다 빠른 apply
입니다 빨리 당신이 할 경우.
답변
좋은 니모닉이 있습니다. pply는 사용 rrays 및 의 법이지는 하나 개 또는 두 개의 인수를 사용합니다. 당신이 사용하는 경우 C를 당신이 가지고있는 모든 C는 인수의 수를 ount.
답변
이것은 오래된 주제이지만 .call이 .apply보다 약간 빠르다는 것을 지적하고 싶었습니다. 왜 그런지 정확히 말할 수 없습니다.
jsPerf, http://jsperf.com/test-call-vs-apply/3 참조
[ UPDATE!
]
Douglas Crockford는 성능 차이를 설명하는 데 도움이되는 두 가지 차이점을 간략하게 언급합니다 … http://youtu.be/ya4UHuXNygM?t=15m52s
Apply는 인수의 배열을 취하지 만 Call은 0 개 이상의 개별 매개 변수를 사용합니다! 아하!
.apply(this, [...])
.call(this, param1, param2, param3, param4...)
답변
Michael Bolin의 Closure : The Definitive Guide 에서 발췌 한 내용 입니다. 약간 길어 보일 수 있지만 통찰력이 풍부합니다. “부록 B. 자주 JavaScript 개념을 오해”:
어떤 this
함수가 호출되는 경우를 말합니다
형식의 함수를 호출 할 때 foo.bar.baz()
객체를 foo.bar
수신자라고합니다. 함수가 호출되면 다음 값으로 사용되는 수신자입니다 this
.
var obj = {};
obj.value = 10;
/** @param {...number} additionalValues */
obj.addValues = function(additionalValues) {
for (var i = 0; i < arguments.length; i++) {
this.value += arguments[i];
}
return this.value;
};
// Evaluates to 30 because obj is used as the value for 'this' when
// obj.addValues() is called, so obj.value becomes 10 + 20.
obj.addValues(20);
함수가 호출 될 때 명시적인 수신자가 없으면 전역 오브젝트가 수신자가됩니다. 47 페이지의 “goog.global”에서 설명한대로 window는 웹 브라우저에서 JavaScript가 실행될 때 전역 객체입니다. 이것은 놀라운 행동으로 이어진다 :
var f = obj.addValues;
// Evaluates to NaN because window is used as the value for 'this' when
// f() is called. Because and window.value is undefined, adding a number to
// it results in NaN.
f(20);
// This also has the unintentional side effect of adding a value to window:
alert(window.value); // Alerts NaN
비록 obj.addValues
와 f
동일한 기능을 참조하십시오, 그들은 수신기의 값이 각 통화에서 다르기 때문에 전화했을 때 다르게 동작합니다. 따라서을 참조하는 함수를 호출 할 때 호출 될 때 올바른 값 this
을 갖도록하는 것이 중요합니다 this
. 명확하게 말하면 this
함수 본문에서 참조되지 않은 경우 동작 f(20)
과 obj.addValues(20)
동일합니다.
함수는 JavaScript에서 일류 객체이므로 자체 메서드를 가질 수 있습니다. 모든 함수에는 메소드가 call()
있으며 함수를 호출 할 때 apply()
수신자 (즉, 참조하는 오브젝트)를 재정의 할 수 this
있습니다. 메소드 서명은 다음과 같습니다.
/**
* @param {*=} receiver to substitute for 'this'
* @param {...} parameters to use as arguments to the function
*/
Function.prototype.call;
/**
* @param {*=} receiver to substitute for 'this'
* @param {Array} parameters to use as arguments to the function
*/
Function.prototype.apply;
참고 유일한 차이 call()
및 apply()
그 인 call()
반면, 각각의 인자로서의 기능 파라미터를 수신하는 apply()
단일 어레이로 수신 :
// When f is called with obj as its receiver, it behaves the same as calling
// obj.addValues(). Both of the following increase obj.value by 60:
f.call(obj, 10, 20, 30);
f.apply(obj, [10, 20, 30]);
로 다음의 호출은, 동등 f
하고 obj.addValues
동일한 기능을 참조하십시오
obj.addValues.call(obj, 10, 20, 30);
obj.addValues.apply(obj, [10, 20, 30]);
그러나 수신자 인수가 지정되지 않은 경우 수신자 인수를 대체하기 위해 자체 수신자의 값을 사용 call()
하거나 apply()
사용 하지 않기 때문에 다음이 작동하지 않습니다.
// Both statements evaluate to NaN
obj.addValues.call(undefined, 10, 20, 30);
obj.addValues.apply(undefined, [10, 20, 30]);
의 값은 this
절대 null
또는 undefined
함수가 호출 될 수 없습니다 . 경우 null
또는 undefined
받는 수신기로 공급된다 call()
또는 apply()
전역 객체 대신에 수신기에 대한 값으로서 사용된다. 따라서 앞의 코드는 value
전역 개체에 이름이 지정된 속성을 추가 할 때와 동일한 바람직하지 않은 부작용이 있습니다.
함수가 할당 된 변수에 대한 지식이없는 것으로 생각하면 도움이 될 수 있습니다. 이는 함수가 정의 될 때가 아니라 함수가 호출 될 때이 값이 바인드 될 것이라는 아이디어를 강화하는 데 도움이됩니다.
추출물의 끝.
답변
때로는 한 객체가 다른 객체의 기능을 빌리는 것이 유용합니다. 즉, 빌린 객체는 빌려 진 함수를 마치 마치 마치 마치 마치 마치 마치 마치 자신의 함수처럼 실행합니다.
작은 코드 예 :
var friend = {
car: false,
lendCar: function ( canLend ){
this.car = canLend;
}
};
var me = {
car: false,
gotCar: function(){
return this.car === true;
}
};
console.log(me.gotCar()); // false
friend.lendCar.call(me, true);
console.log(me.gotCar()); // true
friend.lendCar.apply(me, [false]);
console.log(me.gotCar()); // false
이 메소드는 객체에 임시 기능을 제공하는 데 매우 유용합니다.