सवाल कॉल और आवेदन के बीच क्या अंतर है?


उपयोग के बीच क्या अंतर है call तथा apply एक समारोह का आह्वान करने के लिए?

var func = function() {
  alert('hello!');
};

func.apply(); बनाम func.call();

क्या दो उपरोक्त तरीकों के बीच प्रदर्शन अंतर है? उपयोग करने के लिए सबसे अच्छा कब है call ऊपर apply और इसके विपरीत?


2741
2017-12-31 19:56


मूल


सोच a तर्कों की सरणी के लिए आवेदन में और cतर्क के कॉलम के लिए कॉल में। - Larry Battle
@LarryBattle पूरी तरह से मुझे 70-480 प्रमाणीकरण के लिए अंतर याद रखने में मदद की :) - Shouvik
@LarryBattle मैं लगभग वही करता हूं, लेकिन मुझे लगता है कि एएमए और सी के लिए कॉल में कॉमा के लिए आवेदन किया जाता है (यानी अल्पविराम से अलग तर्क)। - Samih
@LarryBattle अच्छा निमोनिक लैरी, अंत में नामों के साथ सहसंबंध याद किया - Tomo
आप लागू करें एक बार नौकरी के लिए (एक तर्क), आप [फोन] कॉल लोग कई बार (कई तर्क)। वैकल्पिक: [भी?] कई हैं कॉल ड्यूटी गेम्स का। - Gras Double


जवाब:


अंतर यह है कि apply आपको फ़ंक्शन के साथ आविष्कार करने देता है arguments एक सरणी के रूप में; call पैरामीटर को स्पष्ट रूप से सूचीबद्ध करने की आवश्यकता है। एक उपयोगी निमोनिक है " के लिये रे और सी के लिये सीOMMA। "

एमडीएन के दस्तावेज देखें लागू करें तथा कॉल

छद्म वाक्यविन्यास:

theFunction.apply(valueForThis, arrayOfArgs)

theFunction.call(valueForThis, arg1, arg2, ...)

ईएस 6 के रूप में भी संभावना है 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


3308
2017-12-31 20:00



जोड़ने के लिए एक बात यह है कि तर्क एक संख्यात्मक सरणी ([]) होना चाहिए। सहयोगी सरणी ({}) काम नहीं करेगी। - Kevin Schroeder
@ केविन स्क्रोडर: जावास्क्रिप्ट पार्लान्स में, [] एक कहा जाता है सरणी, {} एक कहा जाता है वस्तु। - Martijn
मैं अक्सर भूल जाता था जो एक सरणी लेता है, और जो आपको तर्कों को सूचीबद्ध करने की अपेक्षा करता है। एक तकनीक जिसे मैं याद रखता था वह यह है कि विधि का पहला अक्षर शुरू होता है ए तो यह एक सरणी लेता है i.e ए प्लीज सरणी - aziz punjani
@ एसएएम का उपयोग करना कॉल सामान्य फ़ंक्शन कॉल की बजाय केवल तभी समझदारी होती है जब आपको मूल्य बदलने की आवश्यकता होती है इस फ़ंक्शन कॉल के लिए। एक उदाहरण (जो फ़ंक्शन तर्क-वस्तु को सरणी में परिवर्तित करता है): Array.prototype.slice.call(arguments) या [].slice.call(arguments)। लागू करें अगर आपके पास किसी सरणी में तर्क हैं, तो यह समझ में आता है, उदाहरण के लिए एक फ़ंक्शन में जो एक ही पैरामीटर (लगभग) के साथ एक ही पैरामीटर को कॉल करता है। सिफ़ारिश करना एक सामान्य फंक्शन कॉल का प्रयोग करें funcname(arg1) यदि वह वही करता है जो आपको चाहिए, और सहेजें कॉल तथा लागू करें उन विशेष अवसरों के लिए जब आपको वास्तव में उनकी आवश्यकता होती है। - some
@ कुनलसिंह दोनों call तथा apply दो पैरामीटर लेता है। का पहला तर्क apply' and कॉल 'फ़ंक्शन स्वामी ऑब्जेक्ट होना चाहिए और दूसरा पैरामीटर क्रमशः सरणी या अल्पविराम से अलग पैरामीटर होगा। यदि आप पास करते हैं null या undefined पहले तर्क के रूप में फिर गैर-सख्त मोड में उन्हें वैश्विक वस्तु के साथ प्रतिस्थापित किया जाता है यानी। window - A J Qarshi


के स्कॉट एलन है एक अच्छा लेखन इस विषय पर।

असल में, वे इस बात पर भिन्न होते हैं कि वे फ़ंक्शन तर्कों को कैसे संभालते हैं।

लागू () विधि कॉल () के समान है, लागू करने के अलावा () को दूसरे पैरामीटर के रूप में एक सरणी की आवश्यकता होती है। सरणी लक्ष्य विधि के लिए तर्कों का प्रतिनिधित्व करती है। "

इसलिए:

// assuming you have f
function f(message) { ... }
f.call(receiver, "test");
f.apply(receiver, ["test"]);

209
2017-12-31 19:59



लागू () और कॉल () का दूसरा पैरामीटर वैकल्पिक है, आवश्यक नहीं है। - angry kiwi
पहले पैरामीटर की भी आवश्यकता नहीं है। - Ikrom


प्रत्येक फ़ंक्शन का उपयोग करने के बारे में इस बात का उत्तर देने के लिए, उपयोग करें 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 यदि आप करते हैं तो तेज़ है।


150
2017-12-31 21:50





यहाँ एक अच्छा निमोनिक है। कृपया उपयोग करता है रे और लावे एक या दो तर्क लेता है। जब आप उपयोग करते हैं सीआपको बस इतना करना है सीतर्कों की संख्या काउंट करें।


102
2017-09-04 13:36



वहाँ उपयोगी निमोनिक सही! मैं 'दो या दो तर्क' को 'अधिकतम दो तर्क' कहने के लिए बदल दूंगा क्योंकि न तो पहले या दूसरे पैरामीटर apply आवश्यक है। मुझे यकीन नहीं है कि क्यों कोई कॉल करेगा apply या call एक पैरामीटर के बिना। ऐसा लगता है कि कोई यहां क्यों पता लगाने की कोशिश कर रहा है stackoverflow.com/questions/15903782/... - dantheta
तो, कॉल () का उपयोग कब करें और कब उपयोग करें () .... - Krish


हालांकि यह एक पुराना विषय है, मैं बस यह इंगित करना चाहता था। कैल .apply से थोड़ा तेज है। मैं आपको बिल्कुल क्यों नहीं बता सकता।

जेएसपीरफ़ देखें, http://jsperf.com/test-call-vs-apply/3


[UPDATE!]

डगलस क्रॉकफोर्ड ने संक्षेप में दोनों के बीच अंतर का उल्लेख किया है, जो प्रदर्शन अंतर को समझाने में मदद कर सकता है ... http://youtu.be/ya4UHuXNygM?t=15m52s

आवेदन तर्कों की एक सरणी लेता है, जबकि कॉल शून्य या अधिक व्यक्तिगत पैरामीटर लेता है! आह हा!

.apply(this, [...])

.call(this, param1, param2, param3, param4...)


91
2017-11-07 17:36



यह पैरामीटर / सरणी के साथ फ़ंक्शन के साथ क्या करता है, यदि इसे सरणी को संसाधित करने की आवश्यकता नहीं है, तो इसमें कम समय लगता है? - Relic
दिलचस्प रूप से सरणी के बिना भी, कॉल अभी भी बहुत तेज है। jsperf.com/applyvscallvsfn2 - Josh Mc
@ जोशएमसी यह बहुत ब्राउज़र विशिष्ट होगा। आईई 11 में, मैं कॉल के रूप में तेजी से दो बार आवेदन कर रहा हूं। - Vincent McNabb
1. एक नई सरणी बनाना मतलब है कि कचरा कलेक्टर को इसे किसी बिंदु पर साफ करने की आवश्यकता होगी। 2. dereference का उपयोग कर सरणी में आइटम एक्सेस करना एक चर (पैरामीटर) को सीधे एक्सेस करने से कम कुशल है। (मेरा मानना ​​है कि "पार्सिंग" का अर्थ है जो वास्तव में कुछ अलग है।) लेकिन मेरे तर्कों में से कोई भी jsperf की व्याख्या नहीं करता है। यह इंजन के दो कार्यों के कार्यान्वयन से संबंधित होना चाहिए, उदा। शायद वे एक खाली सरणी बनाते हैं, अगर कोई भी पास नहीं हुआ है। - joeytwiddle
परीक्षण और वीडियो साझा करने के लिए धन्यवाद - Gary


से एक निकास फॉलो करता है क्लोजर: माइकल बोलिन द्वारा परिभाषित गाइड। यह थोड़ा लंबा लग सकता है, लेकिन यह बहुत अंतर्दृष्टि के साथ संतृप्त है। "परिशिष्ट बी से अक्सर जावास्क्रिप्ट अवधारणाओं को गलत समझा":


क्या 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" में समझाया गया है, जब जावास्क्रिप्ट को वेब ब्राउज़र में निष्पादित किया जाता है तो विंडो वैश्विक वस्तु होती है। यह कुछ आश्चर्यजनक व्यवहार की ओर जाता है:

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) वही होगा।

चूंकि फ़ंक्शंस जावास्क्रिप्ट में प्रथम श्रेणी की वस्तुएं हैं, इसलिए उनके पास अपनी विधियां हो सकती हैं। सभी कार्यों में विधियां हैं 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 वैश्विक वस्तु के लिए।

किसी फ़ंक्शन के बारे में सोचने में मददगार हो सकता है क्योंकि चर के बारे में कोई जानकारी नहीं है जिसे इसे असाइन किया गया है। यह इस विचार को मजबूत करने में मदद करता है कि जब यह परिभाषित किया जाता है तो फ़ंक्शन को बुलाए जाने पर इसका मूल्य बाध्य होगा।


निकालने का अंत


71
2017-12-04 12:41



इस तथ्य को ध्यान में रखते हुए, वह additionalValues अंदर संदर्भित नहीं है obj.addValues तन - Viktor Stolbin
मुझे पता है कि आप इस सवाल का जवाब दे रहे थे लेकिन जोड़ना चाहते हैं: एफ को परिभाषित करते समय आप बाइंड का इस्तेमाल कर सकते थे। var f = obj.addValues; हो जाता है var f = obj.addValues.bind(obj)   और अब एफ (20) कॉल का उपयोग किए बिना काम करेगा या हर बार आवेदन करेगा। - jhliberty


कभी-कभी किसी ऑब्जेक्ट के किसी ऑब्जेक्ट के फ़ंक्शन को उधार लेने में उपयोगी होता है, जिसका अर्थ है कि उधार लेने वाली वस्तु बस लेंट फ़ंक्शन निष्पादित करती है जैसे कि यह स्वयं थी।

एक छोटा कोड उदाहरण:

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

ऑब्जेक्ट अस्थायी कार्यक्षमता देने के लिए ये विधियां बहुत उपयोगी हैं।


33
2018-02-25 19:31



उन लोगों के लिए जो जानना चाहते हैं कि कैसे देखना है console.log चेक आउट: Console.log क्या है और मैं इसका उपयोग कैसे करूं? - Michel Ayres


कॉल, एप्लिकेशन और बाइंड के साथ एक और उदाहरण। कॉल और आवेदन के बीच का अंतर स्पष्ट है, लेकिन बाइंड इस तरह काम करता है:

  1. बाइंड एक फ़ंक्शन का एक उदाहरण देता है जिसे निष्पादित किया जा सकता है
  2. पहला पैरामीटर 'इस'
  3. दूसरा पैरामीटर ए है अल्पविराम से अलग तर्कों की सूची (जैसे कॉल)

}

function Person(name) {
    this.name = name; 
}
Person.prototype.getName = function(a,b) { 
     return this.name + " " + a + " " + b; 
}

var reader = new Person('John Smith');

reader.getName = function() {
   // Apply and Call executes the function and returns value

   // Also notice the different ways of extracting 'getName' prototype
   var baseName = Object.getPrototypeOf(this).getName.apply(this,["is a", "boy"]);
   console.log("Apply: " + baseName);

   var baseName = Object.getPrototypeOf(reader).getName.call(this, "is a", "boy"); 
   console.log("Call: " + baseName);

   // Bind returns function which can be invoked
   var baseName = Person.prototype.getName.bind(this, "is a", "boy"); 
   console.log("Bind: " + baseName());
}

reader.getName();
/* Output
Apply: John Smith is a boy
Call: John Smith is a boy
Bind: John Smith is a boy
*/

23
2018-03-31 07:32