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




performance function (14)

सारांश:

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

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

  • call() आपको तर्कों को सामान्य रूप से रखना होगा (दूसरे तर्क से शुरू करना)
  • apply() साथ 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 बाध्यकारी के दाहिने ओर निर्भर करता है तो हम इस व्यवहार को लागू करने के लिए 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

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

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

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

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


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

apply और call पर एमडीएन के दस्तावेज देखें।

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

theFunction.apply(valueForThis, arrayOfArgs)

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

ईएस 6 के रूप में, call फ़ंक्शन के उपयोग के लिए सरणी spread की संभावना भी है, आप यहां संगतताएं देख सकते हैं।

नमूना कोड:

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


इन तरीकों के बीच अंतर हैं, आप पैरामीटर को कैसे पास करना चाहते हैं।

"ए के लिए सरणी और सी के लिए सी" एक आसान निमोनिक है।


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

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

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

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


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

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

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

इसलिए:

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

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

.call(scope, arg1, arg2, arg3)

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

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

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


प्रत्येक फ़ंक्शन का उपयोग करने के बारे में इस बात का उत्तर देने के लिए, यदि आप उन तर्कों की संख्या नहीं जानते हैं जिन्हें आप पास करेंगे, या यदि वे पहले से ही सरणी या सरणी जैसी वस्तु में हैं (जैसे arguments स्वयं को आगे बढ़ाने के लिए ऑब्जेक्ट्स तर्क। अन्यथा call उपयोग 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 प्राथमिकता देता हूं क्योंकि मैं फ़ंक्शन को call कर रहा हूं। apply होगा कि आप फ़ंक्शन को लागू नहीं कर रहे हैं (अस्तित्वहीन) तर्क।

कोई प्रदर्शन अंतर नहीं होना चाहिए, सिवाय इसके कि यदि आप apply और किसी सरणी में तर्कों को f.apply(thisObject, [a, b, c]) उदाहरण के लिए f.apply(thisObject, [a, b, c]) f.call(thisObject, a, b, c) )। मैंने इसका परीक्षण नहीं किया है, इसलिए मतभेद हो सकते हैं, लेकिन यह बहुत ब्राउज़र विशिष्ट होगा। यह संभावना है कि call तेज है यदि आपके पास पहले से ही किसी सरणी में तर्क नहीं हैं और यदि आप ऐसा करते हैं तो apply तेज apply है।


भले ही call और एक ही चीज़ को apply call , मुझे लगता है कि कम से कम एक जगह है जहां आप call उपयोग नहीं कर सकते हैं, लेकिन केवल apply उपयोग कर 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

मैं एक उदाहरण दिखाना चाहता हूं, जहां '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 *


मौलिक अंतर यह है कि call() एक तर्क सूची स्वीकार करता है, जबकि apply() तर्कों की एक एकल सरणी स्वीकार करता है।


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

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"

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

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

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

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

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


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

जब यह एक समारोह कहा जाता है तो this क्या दर्शाता है

फॉर्म foo.bar.baz() फ़ंक्शन को कॉल करते समय, ऑब्जेक्ट foo.bar को रिसीवर के रूप में जाना जाता है। जब फ़ंक्शन कहा जाता है, तो वह रिसीवर होता है जिसका उपयोग इसके लिए मूल्य के रूप में किया जाता है:

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 फ़ंक्शन बॉडी में संदर्भित नहीं किया गया था, तो f(20) और obj.addValues(20) का व्यवहार समान होगा।

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

/**
* @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() , जबकि 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 हैं:

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

फ़ंक्शन कहलाते समय इसका मान null या undefined नहीं हो सकता है। जब call() या apply() करने के लिए रिसीवर के रूप में null या undefined जाता है, तो वैश्विक वस्तु को इसके बजाय रिसीवर के मान के रूप में उपयोग किया जाता है। इसलिए, पिछले कोड में वैश्विक वस्तु के लिए value नामक संपत्ति जोड़ने का एक ही अवांछनीय दुष्प्रभाव होता है।

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

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


Function.prototype.apply () पर एमडीएन दस्तावेज़ों से:

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

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

fun.apply(thisArg, [argsArray])

Function.prototype.call () पर एमडीएन दस्तावेज़ों से:

कॉल () विधि किसी फ़ंक्शन को 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'
));

यह पहेली भी देखें।





dynamic