कॉल और अप्लाई के बीच क्या अंतर है?


3101

किसी फ़ंक्शन का उपयोग करने callऔर applyउसे लागू करने के बीच क्या अंतर है?

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

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

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


726
aआर्ग्स के एरे के लिए आवेदन करने के लिए और आर्ग cके कॉलम के लिए कॉल करने के बारे में सोचें ।
लैरी बैटल

176
@LarryBattle मैं लगभग ऐसा ही करता हूं, लेकिन मुझे लगता है कि अल्पविराम (यानी अल्पविराम से अलग तर्क) के लिए कॉल में सरणी और सी के लिए आवेदन करना होगा।
समीह

3
मैं मानता हूं कि यह बेवकूफी है। कष्टप्रद यह है कि किसी तरह यह सवाल साक्षात्कार के दौरान पूछा जाता है क्योंकि कुछ प्रभावशाली चंपों ने इस प्रश्न को महत्वपूर्ण js प्रश्नों की सूची में जोड़ दिया।
रिंगो

6
आप लागू एक बार एक नौकरी (एक तर्क), तो आप [फोन] के लिए कॉल लोग कई बार (कई तर्क)। वैकल्पिक: कई कॉल ऑफ़ ड्यूटी गेम हैं [भी?] ।
ग्रास डबल

1
जब इरादा "यह" मान की परवाह किए बिना तर्क मानों की एक सूची के साथ एक वैरिएडिक फ़ंक्शन को लागू करना है, तो ES6 प्रसार ऑपरेटर का उपयोग करें, जैसे fn(...input)कि इनपुट एक सरणी है। developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
गजस

जवाबों:


3644

अंतर यह है कि applyआप argumentsएक सरणी के रूप में फ़ंक्शन को आमंत्रित करते हैं ; callमापदंडों को स्पष्ट रूप से सूचीबद्ध किया जाना चाहिए। एक उपयोगी mnemonic " ए के लिए एक rray और C के लिए c 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


24
जोड़ने के लिए एक बात यह है कि आर्ग का एक संख्यात्मक सरणी ([]) होना चाहिए। सहयोगी सरणियाँ ({}) काम नहीं करेंगी।
केविन श्रोएडर

325
@KevinSchroeder: जावास्क्रिप्ट भाषा में, []एक कहा जाता है सरणी , {}एक कहा जाता है वस्तु
मार्टिज़न

89
मैं अक्सर भूल जाता था कि कौन सी एक सरणी लेता है, और जो आपसे तर्कों को सूचीबद्ध करने की अपेक्षा करता है। एक तकनीक जो मुझे याद थी, वह यह है कि अगर विधि का पहला अक्षर तब से शुरू होता है , तो यह एक सरणी लेता है अर्थात एक पूर्ण सरणी
aziz punjani

16
@SAM का उपयोग करते हुए कॉल करता है, तो आप का मान बदलने की जरूरत है एक सामान्य समारोह कॉल के बजाय केवल समझ में आता है इस समारोह कॉल के लिए। एक उदाहरण (जो एक फ़ंक्शन के तर्क-ऑब्जेक्ट को किसी सरणी में परिवर्तित करता है): Array.prototype.slice.call(arguments)या [].slice.call(arguments)लागू करना समझ में आता है यदि आपके पास किसी सरणी में तर्क हैं, उदाहरण के लिए एक फ़ंक्शन में जो एक ही फ़ंक्शन को (लगभग) समान मापदंडों के साथ कॉल करता है। अनुशंसा एक सामान्य फ़ंक्शन कॉल का उपयोग करें funcname(arg1)यदि ऐसा होता है जो आपको चाहिए, और कॉल सहेजें और उन विशेष अवसरों के लिए आवेदन करें जब आपको वास्तव में उनकी आवश्यकता होती है।
कुछ

4
@KunalSingh दोनों callऔर applyदो पैरामीटर लेता है। apply' and कॉल `फ़ंक्शन का पहला तर्क स्वामी ऑब्जेक्ट होना चाहिए और दूसरा पैरामीटर क्रमशः सरणी या अल्पविराम से अलग पैरामीटर होगा। यदि आप पास nullया undefinedपहले तर्क के रूप में तो गैर-सख्त मोड में उन्हें वैश्विक वस्तु के साथ बदल दिया जाता हैwindow
एजे कुरैशी

229

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

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

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

इसलिए:

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

42
लागू करने का दूसरा पैरामीटर () और कॉल () वैकल्पिक है, आवश्यक नहीं है।
नाराज कीवी

34
पहले पैरामीटर की भी आवश्यकता नहीं है।
इक्रोम

@Ikrom, पहले पैरामीटर के लिए आवश्यक नहीं है, callलेकिन इसके लिए एक आवश्यकता है apply
iamcastelli

160

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


111

यहाँ एक अच्छा महामारी है। एक pply rrays का उपयोग करता है और A lways एक या दो तर्क लेता है। जब आप C का उपयोग करते हैं तो आपको तर्कों की संख्या C C करनी होगी ।


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

92

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

JsPerf, http://jsperf.com/test-call-vs-apply/3 देखें


[ UPDATE!]

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

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

.apply(this, [...])

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


यह इस बात पर निर्भर करता है कि फ़ंक्शन पैरामीटर / सरणी के साथ क्या करता है, अगर उसे सरणी को संसाधित करने की आवश्यकता नहीं है, तो क्या इसे कम समय लगता है?
एरिक होडोंस्की

12
दिलचस्प बात यह है कि सरणी के बिना भी, कॉल अभी भी बहुत तेज है। jsperf.com/applyvscallvsfn2
जोश मैक

@JoshMc यह बहुत विशिष्ट ब्राउज़र होगा। IE 11 में, मैं कॉल के रूप में दो बार तेजी से लागू हो रहा हूँ।
विंसेंट मैकनाब

1
1. एक नई सरणी बनाने का मतलब है कि कचरा संग्रहकर्ता को किसी बिंदु पर इसे साफ करने की आवश्यकता होगी। 2. डाइरेक्शन का उपयोग करके ऐरे में एक्सेस करने वाली चीजें सीधे वेरिएबल (पैरामीटर) तक पहुंचने से कम कुशल होती हैं। (मेरा मानना ​​है कि "पार्सिंग" से किमीथेनी का मतलब क्या है, जो वास्तव में कुछ अलग है।) लेकिन मेरे तर्कों में से किसी ने भी जेस्पर को नहीं समझाया। यह इंजन के दो कार्यों के कार्यान्वयन से संबंधित होना चाहिए, उदाहरण के लिए शायद वे वैसे भी एक खाली सरणी बनाते हैं, अगर कोई भी पारित नहीं हुआ था।
joeytwield

परीक्षण और वीडियो साझा करने के लिए धन्यवाद
गैरी

76

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


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);

यदि किसी फ़ंक्शन को कॉल करने पर कोई स्पष्ट रिसीवर नहीं है, तो वैश्विक ऑब्जेक्ट रिसीवर बन जाता है। जैसा कि पृष्ठ ४ window में "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वैश्विक वस्तु नाम की संपत्ति को जोड़ने का एक ही अवांछनीय दुष्प्रभाव है ।

किसी फ़ंक्शन के बारे में सोचना उपयोगी हो सकता है क्योंकि उस चर का कोई ज्ञान नहीं है जिसे उसे सौंपा गया है। यह इस विचार को सुदृढ़ करने में मदद करता है कि इस का मान तब होगा जब फ़ंक्शन को परिभाषित करने के बजाए कॉल किया जाता है।


अर्क का अंत।


बस इस तथ्य पर ध्यान दें, कि शरीर के additionalValuesअंदर संदर्भित नहीं obj.addValuesहै
विक्टर स्टोलिन

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

मुझे पता है कि आपने इसे नहीं लिखा था, लेकिन आपने पुस्तक से पाठ और उदाहरणों को प्रासंगिक के रूप में उजागर किया, और मैं बहुत आभारी हूं। वे बहुत मददगार थे।
फ्रलकन

34

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

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

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

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


1
उन लोगों के लिए जो यह जानना चाहते हैं कि console.logचेक आउट कैसे करना है
मिशेल एरीज

25

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

  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

मैं एक उदाहरण दिखाना चाहता हूं, जहां 'valueForThis' तर्क का उपयोग किया जाता है:

Array.prototype.push = function(element) {
   /*
   Native code*, that uses 'this'       
   this.put(element);
   */
}
var array = [];
array.push(1);
array.push.apply(array,[2,3]);
Array.prototype.push.apply(array,[4,5]);
array.push.call(array,6,7);
Array.prototype.push.call(array,8,9);
//[1, 2, 3, 4, 5, 6, 7, 8, 9] 

** विवरण: http://es5.github.io/#x15.4.4.7 *


20

कॉल () अल्पविराम से अलग किए गए तर्क, पूर्व:

.call(scope, arg1, arg2, arg3)

और लागू () तर्कों की एक सरणी लेता है, उदा:

.apply(scope, [arg1, arg2, arg3])

यहाँ कुछ और उपयोग उदाहरण हैं: http://blog.i-evaluation.com/2012/08/15/javascript-call-and-apply/


`// कॉल () === अल्पविराम से अलग तर्क (तर्क-सूची) .call (यह, args1, args2, args3, ...) // लागू करें () === सरणी के तर्क (सरणी-आइटम)। लागू करें (यह, [arr0, arr1, arr2, ...]) `
xgqfrms

19

से Function.prototype.apply () पर MDN डॉक्स :

लागू () विधि किसी दिए गए thisमान और एक सरणी (या एक सरणी जैसी वस्तु) के रूप में दिए गए तर्कों के साथ एक फ़ंक्शन को कॉल करती है ।

वाक्य - विन्यास

fun.apply(thisArg, [argsArray])

से Function.prototype.call () पर MDN डॉक्स :

कॉल () विधि किसी दिए गए thisमान और व्यक्तिगत रूप से प्रदान किए गए तर्कों के साथ एक फ़ंक्शन को कॉल करती है।

वाक्य - विन्यास

fun.call(thisArg[, arg1[, arg2[, ...]]])

से Function.apply और Function.call जावास्क्रिप्ट में :

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


कोड उदाहरण:

var doSomething = function() {
    var arr = [];
    for(i in arguments) {
        if(typeof this[arguments[i]] !== 'undefined') {
            arr.push(this[arguments[i]]);
        }
    }
    return arr;
}

var output = function(position, obj) {
    document.body.innerHTML += '<h3>output ' + position + '</h3>' + JSON.stringify(obj) + '\n<br>\n<br><hr>';
}

output(1, doSomething(
    'one',
    'two',
    'two',
    'one'
));

output(2, doSomething.apply({one : 'Steven', two : 'Jane'}, [
    'one',
    'two',
    'two',
    'one'
]));

output(3, doSomething.call({one : 'Steven', two : 'Jane'},
    'one',
    'two',
    'two',
    'one'
));

इस फिडल को भी देखें ।



10

यहाँ एक छोटी ईश पोस्ट है, मैंने इस पर लिखा है:

http://sizeableidea.com/call-versus-apply-javascript/

var obj1 = { which : "obj1" },
obj2 = { which : "obj2" };

function execute(arg1, arg2){
    console.log(this.which, arg1, arg2);
}

//using call
execute.call(obj1, "dan", "stanhope");
//output: obj1 dan stanhope

//using apply
execute.apply(obj2, ["dan", "stanhope"]);
//output: obj2 dan stanhope

//using old school
execute("dan", "stanhope");
//output: undefined "dan" "stanhope"

यहाँ एक और एक है: blog.i-evaluation.com/2012/08/15/javascript-call-and-apply, लेकिन मूल रूप से यह सही है: .call (गुंजाइश, arg1, arg2, arg3)
मार्क Karowsowski

7

अंतर यह है कि call()फ़ंक्शन तर्कों को अलग से apply()लेता है , और फ़ंक्शन तर्कों को एक सरणी में लेता है।


6

हम नीचे दिए गए तरीकों से कॉल को अलग और लागू कर सकते हैं

कॉल: तर्क के साथ एक समारोह व्यक्तिगत रूप से प्रदान करते हैं। यदि आप पास किए जाने वाले तर्कों को जानते हैं या पास करने के लिए कोई तर्क नहीं हैं तो आप कॉल का उपयोग कर सकते हैं।

आवेदन: सरणी के रूप में प्रदान किए गए तर्क के साथ एक फ़ंक्शन को कॉल करें। आप आवेदन का उपयोग कर सकते हैं यदि आपको पता नहीं है कि फ़ंक्शन को पास करने के लिए कितने तर्क हैं।

कॉल पर लागू होने का उपयोग करने का एक फायदा है, हमें तर्क की संख्या को बदलने की आवश्यकता नहीं है केवल हम पास किए गए सरणी को बदल सकते हैं।

प्रदर्शन में बड़ा अंतर नहीं है। लेकिन हम कह सकते हैं कि लागू करने की तुलना में कॉल थोड़ी तेज़ है क्योंकि एक सरणी को लागू पद्धति में मूल्यांकन करने की आवश्यकता है।


5

इन तरीकों के बीच अंतर यह है कि आप मापदंडों को कैसे पारित करना चाहते हैं।

"अल्पविराम के लिए सरणी और सी के लिए" एक आसान महामारी है।


11
यह उत्तर क्या प्रदान करता है जो पहले से ही अन्य उत्तरों में अच्छी तरह से उपलब्ध नहीं है?
Kyll

5

thisकिसी फ़ंक्शन के निष्पादित होने पर मान को बाध्य करने के लिए कॉल और लागू दोनों का उपयोग किया जाता है। अंतर केवल इतना है कि तर्क जहां 1 है और callलेता n+1है । केवल दो तर्क लेता है, एक है अन्य तर्क सरणी।this'n' argumentsapplythis

लाभ मैं में देखना applyअधिक callहै कि हम आसानी से बहुत प्रयास के बिना अन्य कार्य करने के लिए एक समारोह कॉल प्रतिनिधि सकता है;

function sayHello() {
  console.log(this, arguments);
}

function hello() {
  sayHello.apply(this, arguments);
}

var obj = {name: 'my name'}
hello.call(obj, 'some', 'arguments');

निरीक्षण करें कि हमने कितनी आसानी helloसे sayHelloउपयोग करने के लिए प्रतिनिधि दिया है apply, लेकिन इसके साथ callइसे प्राप्त करना बहुत मुश्किल है।


4

हालांकि एक ही चीज़ को प्राप्त करने callऔर applyप्राप्त करने के बाद, मुझे लगता है कि कम से कम एक जगह है जहां आप उपयोग नहीं कर सकते हैं callलेकिन केवल उपयोग कर सकते हैं apply। यही कारण है कि जब आप विरासत का समर्थन करना चाहते हैं और निर्माणकर्ता को कॉल करना चाहते हैं।

यहां एक फ़ंक्शन आपको कक्षाएं बनाने की अनुमति देता है जो अन्य कक्षाओं को विस्तारित करके कक्षाएं बनाने का समर्थन करता है।

function makeClass( properties ) {
    var ctor = properties['constructor'] || function(){}
    var Super = properties['extends'];
    var Class = function () {
                 // Here 'call' cannot work, only 'apply' can!!!
                 if(Super)
                    Super.apply(this,arguments);  
                 ctor.apply(this,arguments);
                }
     if(Super){
        Class.prototype = Object.create( Super.prototype );
        Class.prototype.constructor = Class;
     }
     Object.keys(properties).forEach( function(prop) {
           if(prop!=='constructor' && prop!=='extends')
            Class.prototype[prop] = properties[prop];
     });
   return Class; 
}

//Usage
var Car = makeClass({
             constructor: function(name){
                         this.name=name;
                        },
             yourName: function() {
                     return this.name;
                   }
          });
//We have a Car class now
 var carInstance=new Car('Fiat');
carInstance.youName();// ReturnsFiat

var SuperCar = makeClass({
               constructor: function(ignore,power){
                     this.power=power;
                  },
               extends:Car,
               yourPower: function() {
                    return this.power;
                  }
              });
//We have a SuperCar class now, which is subclass of Car
var superCar=new SuperCar('BMW xy',2.6);
superCar.yourName();//Returns BMW xy
superCar.yourPower();// Returns 2.6

मेरा मानना ​​है कि चयनित उत्तर में वर्णित प्रसार के साथ कॉल वहां काम करेगा। जब तक मैं कुछ याद कर रहा हूँ।
झूलबर्टी

4

सारांश:

दोनों call()और apply()विधियां हैं, जो पर स्थित हैं Function.prototype। इसलिए वे प्रोटोटाइप चेन के माध्यम से प्रत्येक फ़ंक्शन ऑब्जेक्ट पर उपलब्ध हैं। दोनों call()और apply()के एक निर्धारित मूल्य के साथ एक समारोह निष्पादित कर सकते हैं this

के बीच मुख्य अंतर call()और apply()जिस तरह से आप इसे में बहस में पारित करने के लिए है। दोनों में call()और apply()आप पहले तर्क के रूप में पास करते हैं जिस वस्तु को आप चाहते हैं वह मूल्य है this। अन्य तर्क निम्न तरीके से भिन्न हैं:

  • साथ में call() आप सामान्य रूप से बहस में डाल करने के लिए है (दूसरा तर्क से शुरू)
  • apply()आप के साथ तर्कों के सरणी में पारित करना होगा।

उदाहरण:

let obj = {
  val1: 5,
  val2: 10
}

const summation = function (val3, val4) {
  return  this.val1 + this.val2 + val3 + val4;
}

console.log(summation.apply(obj, [2 ,3]));
// first we assign we value of this in the first arg
// with apply we have to pass in an array


console.log(summation.call(obj, 2, 3));
// with call we can pass in each arg individually

मुझे इन कार्यों का उपयोग करने की आवश्यकता क्यों होगी?

thisमूल्य जावास्क्रिप्ट में मुश्किल कभी कभी हो सकता है। जब फ़ंक्शन को परिभाषित किया जाता है तो फ़ंक्शन का निष्पादन नहीं होने पर thisनिर्धारित मूल्य यदि हमारा कार्य एक सही thisबंधन पर निर्भर है तो हम इसका उपयोग कर सकते हैं call()और apply()इस व्यवहार को लागू कर सकते हैं । उदाहरण के लिए:

var name = 'unwantedGlobalName';

const obj =  {
  name: 'Willem',
  sayName () { console.log(this.name);}
}


let copiedMethod = obj.sayName;
// we store the function in the copiedmethod variable



copiedMethod();
// this is now window, unwantedGlobalName gets logged

copiedMethod.call(obj);
// we enforce this to be obj, Willem gets logged


4

मुख्य अंतर यह है कि कॉल का उपयोग करते हुए, हम स्कोप को बदल सकते हैं और तर्कों को सामान्य रूप से पारित कर सकते हैं, लेकिन लागू करें आप एरे के रूप में तर्कों का उपयोग करके इसे कॉल कर सकते हैं (उन्हें एक सरणी के रूप में पास करें)। लेकिन आपके कोड में उन्हें क्या करना है, इसके संदर्भ में, वे बहुत समान हैं।

हालांकि इस फ़ंक्शन का सिंटैक्स लागू होने के लगभग समान है (), मूलभूत अंतर यह है कि कॉल () एक तर्क सूची को स्वीकार करता है, जबकि लागू () तर्क के एक एकल सरणी को स्वीकार करता है।

तो जैसा कि आप देखते हैं, कोई बड़ा अंतर नहीं है, लेकिन फिर भी, ऐसे मामले हैं जिन्हें हम कॉल () या लागू () का उपयोग करना पसंद करते हैं। उदाहरण के लिए, नीचे दिए गए कोड को देखें, जो एमडीएन से एक सरणी में सबसे छोटी और सबसे बड़ी संख्या का पता लगाते हैं, आवेदन पद्धति का उपयोग करते हुए:

// min/max number in an array
var numbers = [5, 6, 2, 3, 7];

// using Math.min/Math.max apply
var max = Math.max.apply(null, numbers); 
// This about equal to Math.max(numbers[0], ...)
// or Math.max(5, 6, ...)

var min = Math.min.apply(null, numbers)

इसलिए मुख्य अंतर सिर्फ तरीका है जिससे हम तर्क पारित कर रहे हैं:

कॉल:

function.call(thisArg, arg1, arg2, ...);

लागू:

function.apply(thisArg, [argsArray]);

2

मैं इसमें थोड़ा विस्तार जोड़ दूं।

ये दोनों कॉल लगभग बराबर हैं:

func.call(context, ...args); // pass an array as list with spread operator

func.apply(context, args);   // is same as using apply

केवल एक मामूली अंतर है:

  • spreadऑपरेटर ... गुजर अनुमति देता है iterable args सूची कॉल करने के लिए के रूप में।
  • applyकेवल स्वीकार करता सरणी की तरह आर्ग।

तो, ये कॉल एक दूसरे के पूरक हैं। जहां हम एक पुनरावृत्ति की उम्मीद करते हैं , callकाम करते हैं, जहां हम एक सरणी की तरह उम्मीद करते हैं ,apply काम करते ।

और वस्तुओं है कि दोनों कर रहे हैं के लिए iterable और सरणी की तरह , एक वास्तविक सरणी की तरह, हम तकनीकी रूप से उनमें से किसी को इस्तेमाल कर सकते हैं, लेकिन लागू शायद हो जाएगा तेज होगा क्योंकि अधिकांश जावास्क्रिप्ट इंजन आंतरिक रूप से इसे बेहतर रूप से अनुकूलित करते हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.