Call ve camera arasındaki fark nedir?


3104

Bir işlevi kullanmak callve applyçağırmak arasındaki fark nedir ?

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

func.apply(); vs func.call();

Yukarıda bahsedilen iki yöntem arasında performans farklılıkları var mı? Ne zaman kullanmak en iyisidir callüzerinde applytersi ve yardımcısı?


727
aBağımsız değişken dizisi için geçerli ve bağımsız değişken csütunları için çağrıda düşünün .
Larry Savaşı

176
@LarryBattle Ben hemen hemen aynı yapmak, ama bir dizi ve virgül çağrısında c (yani virgülle ayrılmış bağımsız değişkenler) için geçerli olduğunu düşünüyorum.
Samih

3
Kabul ediyorum aptalca. Rahatsız edici olan şey, bazı etkili görüşmeler soruyu önemli js soruları listesine eklediğinden, görüşmeler sırasında bir şekilde bu sorunun sorulmasıdır.
Ringo

6
Sen uygulamak kez bir iş (bir argüman), sen [telefon] için çağrı insanlar birçok kez (çeşitli argümanlar). Alternatif: Call of Duty oyunları da var mı?
Gras Double

1
Amaç, "bu" değerden bağımsız olarak bir değişken değerleri listesi içeren değişken bir işlevi çağırmak olduğunda, ES6 yayma işlecini kullanın; örneğin fn(...input), girdi bir dizi olduğunda. developer.mozilla.org/tr-TR/docs/Web/JavaScript/Reference/…
Gajus

Yanıtlar:


3648

Fark, applyfonksiyonu argumentsbir dizi olarak çağırmanıza izin vermesidir ; callparametrelerin açıkça listelenmesini gerektirir. Yararlı bir anımsatıcı " bir rray için A ve c omma için C " dir.

MDN dokümanlarına bakın uygulamak ve çağrı .

Sözde sözdizimi:

theFunction.apply(valueForThis, arrayOfArgs)

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

Ayrıca, ES6'dan itibaren, işlevle spreadbirlikte kullanım için dizi olasılığı vardır call, burada uyumlulukları görebilirsiniz .

Basit kod:

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


25
Eklenecek bir şey, bağımsız değişkenlerin sayısal bir dizi ([]) olması gerektiğidir. İlişkilendirilebilir diziler ({}) çalışmaz.
Kevin Schroeder

326
@KevinSchroeder: Javascript bölümünde, []bir dizi , nesne{} olarak adlandırılır .
Martijn

89
Sık sık hangisinin bir dizi aldığını ve hangi argümanları listelemenizi beklediğini unuturdum. İle yöntem başlar ilk harfi eğer bunu hatırlamak için kullanılan bir tekniktir bir o yani bir dizi alır bir pply dizisi
aziz Punjani

16
Kullanılması @SAM çağrıyı size değerini değiştirmek gerekiyorsa normal işlev çağrısı yerine sadece mantıklı bu işlev çağrısı için. Bir örnek (işlevler argüman-nesnesini bir diziye dönüştüren): Array.prototype.slice.call(arguments)veya [].slice.call(arguments). bir dizide, örneğin (neredeyse) aynı parametrelerle başka bir işlevi çağıran bir işlevde argümanlarınız varsa, uygulama mantıklıdır. Öneri kullanın normal işlev çağrısı funcname(arg1)neye ihtiyacınız yapar ve tasarrufu ise çağrı ve uygulamak gerçekten ihtiyaç olduğunda bu özel günler için.
bazı

4
@KunalSingh Hem callve applyiki parametre alır. apply' and Call` işlevinin ilk argümanı sahip nesnesi olmalı ve ikinci parametre sırasıyla dizi veya virgülle ayrılmış parametreler olacaktır. Eğer nullya undefinedda ilk argüman olarak geçerseniz, o zaman katı olmayan modda bunlar küresel nesne ile değiştirilirwindow
AJ Qarshi

229

K. Scott Allen bu konuda güzel bir yazışmaya sahip .

Temel olarak, işlev argümanlarını nasıl ele aldıklarına göre farklılık gösterirler.

Apply () yöntemi, call () işleviyle aynıdır, ancak Apply () yöntemi, ikinci parametre olarak bir dizi gerektirir. Dizi, hedef yöntem için bağımsız değişkenleri temsil eder. "

Yani:

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

42
Apply () ve call () öğelerinin ikinci parametresi isteğe bağlıdır, zorunlu değildir.
kızgın kivi

34
İlk parametre de gerekli değildir.
Ikrom

@Ikrom, ilk parametre için gerekli değil callama için bir gereklilik apply
iamcastelli

160

Her bir işlevin ne zaman kullanılacağıyla ilgili bölümü yanıtlamak için, applygeçeceğiniz bağımsız değişken sayısını bilmiyorsanız veya zaten bir dizi veya dizi benzeri bir nesnede ( argumentskendi bağımsız değişkenlerinizi iletecek nesne gibi) kullanın. callBir dizideki bağımsız değişkenleri sarmaya gerek olmadığından, aksi takdirde kullanın .

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

Ben (senin örnekte olduğu gibi) herhangi bir parametre göndermeden değilim, ben tercih callben değilim beri çağıran işlevi. işlevi (var olmayan) argümanlara uyguladığınızapply anlamına gelir .

Herhangi bir performans farkı olmamalıdır, ancak applybağımsız değişkenleri bir dizide (örneğin f.apply(thisObject, [a, b, c])yerine f.call(thisObject, a, b, c)) kullanır ve sararsanız . Test etmedim, bu yüzden farklılıklar olabilir, ancak tarayıcıya özel olurdu. Bu büyük olasılıkla callZaten bir dizide argümanları var ve yoksa daha hızlı applydaha hızlı bunu yaparsanız.


111

İşte iyi bir anımsatıcı. Bir pply A ışınları kullanır ve A lways bir veya iki Argüman alır. Kullandığınızda C Eğer gereken tek şey C argümanların sayısını ount.


2
Orada yararlı anımsatıcı !. 'Bir veya iki applybağımsız değişkeni', 'birinci veya ikinci parametrelere gerek olmadığından' en fazla iki bağımsız değişken 'diyecek şekilde değiştireceğim . Neden bir parametre arayacak applyveya callparametre olmadan emin değilim . Birisi neden burada bulmaya çalışıyor gibi görünüyor stackoverflow.com/questions/15903782/…
dantheta

92

Bu eski bir konu olsa da, .call'un .apply'den biraz daha hızlı olduğunu belirtmek istedim. Size tam olarak nedenini söyleyemem.

Bkz. JsPerf, http://jsperf.com/test-call-vs-apply/3


[ UPDATE!]

Douglas Crockford, ikisi arasındaki farktan kısaca bahsediyor, bu da performans farkını açıklamaya yardımcı olabilir ... http://youtu.be/ya4UHuXNygM?t=15m52s

Uygula, bir dizi bağımsız değişken alırken, Çağrı sıfır veya daha fazla bağımsız parametre alır! Ah hah!

.apply(this, [...])

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


Bu, işlevin parametreleri / dizisi ile ne yaptığına bağlıdır, diziyi işlemesi gerekmiyorsa, daha az zaman alır mı?
Eric Hodonsky

12
İlginç bir şekilde dizi olmadan bile, çağrı hala çok daha hızlı. jsperf.com/applyvscallvsfn2
Josh Mc

@JoshMc Çok tarayıcıya özgü olurdu. IE 11'de iki kat daha hızlı çağrı yapıyorum.
Vincent McNabb

1
1. Yeni bir dizi oluşturmak, çöp toplayıcının bir noktada onu temizlemesi gerekeceği anlamına gelir. 2. Dizideki dereference kullanarak öğelere erişmek, doğrudan bir değişkene (parametreye) erişimden daha az etkilidir. (Sanırım kmatheny'nin "ayrıştırma" ile kastettiği şey bu, aslında oldukça farklı bir şey.) Ama argümanlarımın hiçbiri jsperf'i açıklamıyor. Bu, motorun iki işlevi yerine getirmesiyle ilgili olmalıdır, örneğin, hiç geçmediyse, belki de boş bir dizi oluştururlar.
joeytwiddle

Testi ve videoyu paylaştığınız için teşekkür ederiz
Gary

76

Closure: The Definitive Guide'dan Michael Bolin'den bir alıntı izliyor . Biraz uzun görünebilir, ancak çok fazla içgörü ile doyurulur. "Ek B. Sık Yanlış Anlaşılan JavaScript Kavramları" ndan:


thisBir İşlev Çağrıldığında Neler İfade Edilir

Formun bir işlevini çağırırken foo.bar.baz(), nesneye foo.baralıcı denir. İşlev çağrıldığında, aşağıdakiler için değer olarak kullanılan alıcıdır 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);

Bir işlev çağrıldığında açık alıcı yoksa, global nesne alıcı olur. "Goog.global" sayfa 47 bölümünde açıklandığı gibi, bir web tarayıcısında JavaScript yürütüldüğünde pencere genel nesnedir. Bu bazı şaşırtıcı davranışlara yol açar:

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

Olsa obj.addValuesve faynı işleve bakın onlar alıcısının değeri her çağrısında farklı olduğu için çağrıldığında farklı davranır. Bu nedenle, atıfta bulunan bir işlevi çağırırken , çağrıldığında doğru değere sahip thisolmasını sağlamak önemlidir this. Açıkça söylemek gerekirse this, işlev gövdesinde referans verilmemişse, davranışı f(20)ve obj.addValues(20)aynı olacaktır.

İşlevler JavaScript'te birinci sınıf nesneler olduğu için kendi yöntemlerine sahip olabilirler. Tüm fonksiyonlar yöntemler vardır call()ve apply()bu mümkün (yani, nesne alıcı yeniden tanımlama için yapmak thisbelirtir) işlevini çağıran zaman. Yöntem imzaları aşağıdaki gibidir:

/**
* @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;

Not arasındaki tek fark, call()ve apply()ki call(), oysa tek tek, bağımsız değişken olarak işlev parametreleri alır apply()tek bir dizi olarak alır:

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

Aşağıdaki çağrılar eşdeğerdir fve obj.addValuesaynı işleve başvurur:

obj.addValues.call(obj, 10, 20, 30);
obj.addValues.apply(obj, [10, 20, 30]);

Bununla birlikte, belirtilmediğinde alıcı argümanının yerini almak için kendi alıcısının değerini ne call()de ne de apply()kullandığından, aşağıdakiler çalışmaz:

// Both statements evaluate to NaN
obj.addValues.call(undefined, 10, 20, 30);
obj.addValues.apply(undefined, [10, 20, 30]);

Değeri thishiçbir zaman olamaz nullveya undefinedbir işlev çağrıldığında. Tüm nullveya undefinedalıcıdan olarak temin edilir call()ya da apply()küresel bir amacı yerine alıcı değeri olarak kullanılır. Bu nedenle, önceki kod, valuegenel nesneye adlı bir özellik eklemek için aynı istenmeyen yan etkiye sahiptir .

Bir fonksiyonun, kendisine atanan değişken hakkında hiçbir bilgiye sahip olmadığını düşünmek yararlı olabilir. Bu, işlev tanımlandığından ziyade işlev çağrıldığında bunun değerinin bağlanacağı fikrinin güçlendirilmesine yardımcı olur.


Ekstraktın sonu.


Sadece gerçeği not etmek için, bu beden additionalValuesiçinde referans verilmezobj.addValues
Viktor Stolbin

Soruyu cevapladığınızı biliyorum ama eklemek istiyorsunuz: f'yi tanımlarken bağlama kullanabilirsiniz. var f = obj.addValues;olur var f = obj.addValues.bind(obj) ve şimdi f (20) her seferinde çağrı kullanmak veya uygulamak zorunda kalmadan çalışacaktır.
jhliberty

Bunu yazmadığınızı biliyorum, ancak kitaptaki metni ve örnekleri alakalı olarak vurguladınız ve çok minnettarım. Onlar çok yardımcı oldular.
Fralcon

34

Bazen bir nesnenin başka bir nesnenin işlevini ödünç alması yararlıdır, yani ödünç alma nesnesi ödünç işlevi kendi sanki kendi işleviymiş gibi yürütür.

Küçük bir kod örneği:

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

Bu yöntemler, nesnelere geçici işlevsellik vermek için çok kullanışlıdır.


1
Nasıl görüneceğini öğrenmek isteyen kişilere console.loggöz atın
Michel Ayres

25

Arama, Uygula ve Bağla ile ilgili başka bir örnek. Çağrı ve Uygula arasındaki fark açıktır, ancak Bind şu şekilde çalışır:

  1. Bind, çalıştırılabilen bir işlevin örneğini döndürür
  2. İlk Parametre ' bu '
  3. İkinci parametre, Virgülle ayrılmış bağımsız değişken listesidir ( Çağrı gibi )

}

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' argümanının kullanıldığı bir örnek göstermek istiyorum:

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] 

** ayrıntılar: http://es5.github.io/#x15.4.4.7 *


20

Call (), virgülle ayrılmış bağımsız değişkenler alır, örn:

.call(scope, arg1, arg2, arg3)

ve Apply () yöntemi bir dizi bağımsız değişken alır, örn:

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

birkaç kullanım örneği daha var: http://blog.i-evaluation.com/2012/08/15/javascript-call-and-apply/


`// call () === virgülle ayrılmış bağımsız değişkenler (arguments-list) .call (this, args1, args2, args3, ...) // Apply () === bağımsız değişken dizisi (dizi öğeleri). uygulayın (bu, [arr0, arr1, arr2, ...]) ``
xgqfrms

19

Gönderen Function.prototype.apply () MDN docs :

Apply () yöntemi, belirli bir thisdeğere sahip bir işlevi ve dizi (veya dizi benzeri bir nesne) olarak sağlanan bağımsız değişkenleri çağırır .

Sözdizimi

fun.apply(thisArg, [argsArray])

Gönderen Function.prototype.call () MDN docs :

Call () yöntemi, belirli bir thisdeğere ve bağımsız olarak sağlanan bağımsız değişkenlere sahip bir işlevi çağırır .

Sözdizimi

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

Gönderen JavaScript Function.apply ve Function.call :

Apply () yöntemi, call () işleviyle aynıdır, ancak Apply () yöntemi, ikinci parametre olarak bir dizi gerektirir. Dizi, hedef yöntem için bağımsız değişkenleri temsil eder.


Kod örneği:

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

Ayrıca bkz bu Fiddle .



10

İşte ufak bir yazı, bunun üzerine yazdım:

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"

İşte başka bir tane: blog.i-evaluation.com/2012/08/15/javascript-call-and-apply ama temelde doğru: .call (kapsam, arg1, arg2, arg3)
Mark Karwowski

7

Fark, call()işlev bağımsız değişkenlerini ayrı ayrı ve apply()bir dizideki işlev bağımsız değişkenlerini almasıdır.


6

Çağrıyı farklılaştırabilir ve yöntemleri aşağıdaki gibi uygulayabiliriz

CALL: Bağımsız değişkenli bir işlev ayrı ayrı sağlanır. Geçilecek argümanları biliyorsanız veya geçecek argüman yoksa çağrıyı kullanabilirsiniz.

UYGULA: Dizi olarak sağlanan bağımsız değişkenli bir işlevi çağırın. Eğer işleve kaç argümanın geçeceğini bilmiyorsanız uygula komutunu kullanabilirsiniz.

Çağrı üzerine uygula özelliğini kullanmanın bir avantajı vardır, yalnızca geçirilen bir diziyi değiştirebileceğimiz argüman sayısını değiştirmemiz gerekmez.

Performansta büyük bir fark yok. Ancak, bir dizinin uygulama yönteminde değerlendirmesi gerektiğinden, aramanın karşılaştırmak için biraz daha hızlı olduğunu söyleyebiliriz.


5

Bunlar ile yöntemler arasındaki fark, parametreleri nasıl iletmek istediğinizdir.

“Dizi için A ve virgül için C” kullanışlı bir anımsatıcıdır.


11
Bu cevap, diğer cevaplarda halihazırda iyi sağlanamamıştır.
Kyll

5

Çağrı ve uygulama her ikisi de thisbir işlev yürütüldüğünde değeri zorlamak için kullanılır . Tek fark, 1'in ve olduğu argümanları callalmasıdır . sadece iki argüman alır, biri diğeri argüman dizisidir.n+1this'n' argumentsapplythis

Ben gördüğünüz avantaj applyüzerinde callkolayca zorluk çekmeden diğer işleve bir işlev çağrısı temsilci olmasıdır;

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

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

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

Biz delege nasıl kolayca gözlemleyin helloiçin sayHellokullanarak apply, fakat callbunu başarmak için çok zordur.


4

Olsa callve applyaynı şeyi başarmak, seni kullanamazsınız tek bir yerde en az olduğunu düşünüyorum callama sadece kullanabilirsiniz apply. İşte o zaman mirası desteklemek ve yapıcıyı çağırmak istersiniz.

Burada, diğer sınıfları genişleterek sınıf oluşturmayı destekleyen sınıflar oluşturmanıza olanak sağlayan bir işlev vardır.

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

Çağrı, seçilen cevapta açıklandığı gibi forma operatörü ile çalışacağına inanıyorum. Bir şey eksik olmadıkça.
jhliberty

4

Özet:

Her ikisi de call()ve apply()üzerinde bulunan yöntemlerdir Function.prototype. Bu nedenle, her işlev nesnesinde prototip zinciri aracılığıyla kullanılabilirler. Her ikisi de call()ve apply()belirtilen bir değere sahip bir işlevi çalıştırabilirsiniz this.

Arasındaki temel fark call()ve apply()bunu içine argümanlar geçmek zorunda yoludur. İkisinde de call()ve apply()bir ilk argüman olarak siz değer olmasını istediğiniz nesneyi geçmesi this. Diğer argümanlar şu şekilde farklılık gösterir:

  • İle call()normalde argümanlar koymak zorunda (ikinci argüman başlayarak)
  • İle apply()argüman dizisi geçmek zorunda.

Misal:

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

Neden bu işlevleri kullanmam gerekiyor?

thisDeğer javascript zor bazen olabilir. Bir işlev tanımlandığında değil, bir işlev yürütüldüğündethis belirlenen değerdir . Eğer fonksiyonumuz doğru bir thisbağlamaya bağlıysa, bu davranışı uygulamak call()ve apply()uygulamak için kullanabiliriz . Örneğin:

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

Temel fark, çağrıyı kullanarak kapsamı değiştirebilir ve bağımsız değişkenleri normal olarak geçirebiliriz, ancak uygula, Array olarak bağımsız değişkenleri kullanarak (bir dizi olarak geçirir) çağırmanıza izin verir. Ancak kodunuzda ne yapacakları açısından oldukça benzerler.

Bu işlevin sözdizimi neredeyse application () işleviyle neredeyse aynı olsa da, temel fark call () öğesinin bir bağımsız değişken listesini kabul ederken, application () tek bir bağımsız değişken dizisini kabul etmesidir.

Gördüğünüz gibi, büyük bir fark yok, ancak yine de call () veya Apply () kullanmayı tercih ettiğimiz durumlar var. Örneğin, uygula yöntemini kullanarak MDN'den bir dizideki en küçük ve en büyük sayıyı bulan aşağıdaki koda bakın:

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

Temel fark sadece argümanları aktarma şeklimizdir

:

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

Uygulamak:

function.apply(thisArg, [argsArray]);

2

Buna biraz ayrıntı ekleyeyim.

bu iki çağrı neredeyse eşdeğerdir:

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

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

Küçük bir fark var:

  • spreadOperatör ... geçen sağlar iterable args aramaya liste olarak.
  • applySadece kabul dizi benzeri bağımsız değişken.

Yani, bu çağrılar birbirini tamamlıyor. Biz bekliyoruz Nerede iterable , callbiz bekliyoruz işleri, dizi benzeri , applyeserlerini.

Ve her ikisi de nesneler için iterable ve dizi benzeri , gerçek dizi gibi, biz teknik olarak bunlardan herhangi verebilirdim ama uygulamak muhtemelen olacak daha hızlı en JavaScript motorları dahili olarak daha iyi optimize çünkü.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.