Apa perbedaan antara panggilan dan melamar?

3105

Apa perbedaan antara menggunakan calldan applymenjalankan fungsi?

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

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

Apakah ada perbedaan kinerja antara kedua metode yang disebutkan di atas? Kapan sebaiknya menggunakan calllebih dari applydan sebaliknya?

John Duff
sumber
727
Pikirkan adi terapkan untuk array argumen dan cpanggilan untuk kolom argumen.
Larry Battle
176
@LarryBattle Saya melakukan hal yang hampir sama, tapi saya pikir a berlaku untuk array dan c dalam panggilan untuk koma (yaitu argumen yang dipisahkan koma).
Samih
3
Saya setuju itu bodoh. Yang menjengkelkan adalah bahwa entah bagaimana pertanyaan ini ditanyakan selama wawancara karena beberapa orang berpengaruh menambahkan pertanyaan ke daftar pertanyaan penting mereka.
Ringo
6
Anda melamar pekerjaan sekali (satu argumen), Anda [telepon] memanggil orang berkali-kali (beberapa argumen). Alternatif: ada banyak game Call of Duty.
Gras Double
1
Ketika maksudnya adalah untuk memanggil fungsi variadic dengan daftar nilai argumen terlepas dari nilai "ini", kemudian gunakan operator spread ES6, misalnya di fn(...input)mana input adalah array. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Gajus

Jawaban:

3649

Perbedaannya adalah bahwa applyAnda dapat memanggil fungsi dengan argumentssebagai array; callmembutuhkan parameter yang terdaftar secara eksplisit. Sebuah mnemonic yang berguna adalah " A untuk sebuah RRay dan C untuk c Omma."

Lihat dokumentasi MDN tentang mendaftar dan menelepon .

Sintaks semu:

theFunction.apply(valueForThis, arrayOfArgs)

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

Ada juga, pada ES6, kemungkinan spreadarray untuk digunakan dengan callfungsi, Anda dapat melihat kompatibilitas di sini .

Kode sampel:

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

garis datar
sumber
25
Satu hal yang ditambahkan adalah args harus berupa array numerik ([]). Array asosiatif ({}) tidak akan berfungsi.
Kevin Schroeder
326
@KevinSchroeder: Dalam bahasa javascript, []disebut array , {}disebut objek .
Martijn
89
Saya sering lupa mana yang mengambil array, dan yang mengharapkan Anda untuk membuat daftar argumen. Sebuah teknik yang saya digunakan untuk mengingatnya adalah jika huruf pertama dari metode ini dimulai dengan sebuah maka dibutuhkan sebuah array yaitu sebuah array yang pply
aziz Punjani
16
@ SAM Menggunakan Panggilan alih-alih panggilan fungsi normal hanya masuk akal jika Anda perlu mengubah nilai ini untuk panggilan fungsi. Contoh (yang mengonversi objek argumen-fungsi ke array): Array.prototype.slice.call(arguments)atau [].slice.call(arguments). berlaku masuk akal jika Anda memiliki argumen dalam array, misalnya dalam suatu fungsi yang memanggil fungsi lain dengan (hampir) parameter yang sama. Rekomendasi Gunakan panggilan fungsi normal funcname(arg1)jika melakukan apa yang Anda butuhkan, dan simpan panggilan dan ajukan untuk acara-acara khusus ketika Anda benar-benar membutuhkannya.
beberapa
4
@KunalSingh Keduanya calldan applymengambil dua parameter. Argumen apply' and fungsi call` pertama harus menjadi objek pemilik dan parameter kedua akan menjadi parameter array atau dipisahkan koma masing-masing. Jika Anda lulus nullatau undefinedsebagai argumen pertama maka dalam mode non-ketat mereka diganti dengan objek global yaituwindow
AJ Qarshi
229

K. Scott Allen memiliki artikel bagus tentang masalah ini.

Pada dasarnya, mereka berbeda pada bagaimana mereka menangani argumen fungsi.

Metode apply () identik dengan panggilan (), kecuali apply () membutuhkan array sebagai parameter kedua. Array mewakili argumen untuk metode target. "

Begitu:

// assuming you have f
function f(message) { ... }
f.call(receiver, "test");
f.apply(receiver, ["test"]);
tidak ada
sumber
42
parameter kedua dari apply () dan call () adalah opsional, tidak diperlukan.
Kiwi
34
Parameter pertama tidak diperlukan juga.
Ikrom
@ Ikrom, parameter pertama tidak diperlukan untuk calltetapi persyaratan untuk apply
iamcastelli
160

Untuk menjawab bagian tentang kapan harus menggunakan setiap fungsi, gunakan applyjika Anda tidak tahu jumlah argumen yang akan Anda lewati, atau jika sudah ada dalam array atau objek mirip array (seperti argumentsobjek untuk meneruskan argumen Anda sendiri. Gunakan callsebaliknya, karena tidak perlu membungkus argumen dalam array.

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

Ketika saya tidak memberikan argumen apa pun (seperti contoh Anda), saya lebih suka callkarena saya memanggil fungsi. applyakan menyiratkan Anda menerapkan fungsi ke argumen (tidak ada).

Seharusnya tidak ada perbedaan kinerja, kecuali mungkin jika Anda menggunakan applydan membungkus argumen dalam sebuah array (misalnya f.apply(thisObject, [a, b, c])bukan f.call(thisObject, a, b, c)). Saya belum mengujinya, jadi mungkin ada perbedaan, tetapi akan sangat spesifik browser. Kemungkinan calllebih cepat jika Anda belum memiliki argumen dalam array dan applylebih cepat jika Anda melakukannya.

Matthew Crumley
sumber
111

Ini mnemonik yang bagus. Seorang ply menggunakan A rrays dan A lways membutuhkan satu atau dua argumen. Ketika Anda menggunakan C semua yang Anda miliki untuk C jumlah argumen.

Joe
sumber
2
Mnemonic yang berguna di sana !. Saya akan mengubah 'satu atau dua Argumen' untuk mengatakan 'maksimum dua Argumen' karena tidak applydiperlukan parameter pertama atau kedua . Saya tidak yakin mengapa seseorang akan memanggil applyatau calltanpa parameter. Sepertinya seseorang sedang mencari tahu mengapa di sini stackoverflow.com/questions/15903782/…
dantheta
92

Meskipun ini adalah topik lama, saya hanya ingin menunjukkan bahwa .call sedikit lebih cepat daripada .apply. Saya tidak bisa memberi tahu Anda mengapa.

Lihat jsPerf, http://jsperf.com/test-call-vs-apply/3


[ UPDATE!]

Douglas Crockford menyebutkan secara singkat perbedaan antara keduanya, yang dapat membantu menjelaskan perbedaan kinerja ... http://youtu.be/ya4UHuXNygM?t=15m52s

Berlaku mengambil array argumen, sementara Panggilan mengambil nol atau lebih parameter individual! Ah hah!

.apply(this, [...])

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

kmatheny
sumber
Ini tergantung pada apa fungsinya dengan parameter / array, jika tidak perlu memproses array, apakah ini membutuhkan waktu lebih sedikit?
Eric Hodonsky
12
Menariknya bahkan tanpa array, panggilan masih jauh lebih cepat. jsperf.com/applyvscallvsfn2
Josh Mc
@ JoshMc Itu akan sangat spesifik browser. Di IE 11, saya mulai berlaku dua kali lebih cepat dari panggilan.
Vincent McNabb
1
1. Membuat array baru berarti pemulung perlu membersihkannya di beberapa titik. 2. Mengakses item dalam array menggunakan dereference kurang efisien daripada mengakses variabel (parameter) secara langsung. (Saya percaya itulah yang dimaksud kmatheny dengan "parsing", yang sebenarnya adalah sesuatu yang sangat berbeda.) Tetapi tidak satu pun dari argumen saya yang menjelaskan jsperf. Itu harus terkait dengan implementasi mesin dari dua fungsi, misalnya mungkin mereka membuat array kosong, jika tidak ada yang berlalu.
joeytwiddle
Terima kasih telah berbagi tes dan video
Gary
76

Mengikuti ekstrak dari Penutupan: Panduan Definitif oleh Michael Bolin . Ini mungkin terlihat agak panjang, tetapi penuh dengan banyak wawasan. Dari "Lampiran B. Konsep JavaScript yang Sering Disalahpahami":


Apa yang thisMerujuk Ketika Suatu Fungsi Dipanggil

Saat memanggil fungsi formulir foo.bar.baz(), objek foo.bardisebut sebagai penerima. Ketika fungsi dipanggil, itu adalah penerima yang digunakan sebagai nilai untuk 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);

Jika tidak ada penerima eksplisit ketika suatu fungsi dipanggil, maka objek global menjadi penerima. Seperti yang dijelaskan dalam "goog.global" di halaman 47, jendela adalah objek global ketika JavaScript dieksekusi di browser web. Ini mengarah pada beberapa perilaku mengejutkan:

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

Meskipun obj.addValuesdan fmerujuk ke fungsi yang sama, mereka berperilaku berbeda ketika dipanggil karena nilai penerima berbeda di setiap panggilan. Untuk alasan ini, saat memanggil fungsi yang merujuk this, penting untuk memastikan bahwa thisakan memiliki nilai yang benar ketika dipanggil. Agar jelas, jika thistidak dirujuk dalam fungsi tubuh, maka perilaku f(20)dan obj.addValues(20)akan sama.

Karena fungsi adalah objek kelas satu dalam JavaScript, mereka dapat memiliki metode mereka sendiri. Semua fungsi memiliki metode call()dan apply()yang memungkinkan untuk mendefinisikan ulang penerima (yaitu objek yang thismerujuk) ketika memanggil fungsi. Tanda tangan metode adalah sebagai berikut:

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

Perhatikan bahwa satu-satunya perbedaan antara call()dan apply()yang call()menerima parameter fungsi sebagai argumen individual, sedangkan apply()menerimanya sebagai array tunggal:

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

Panggilan berikut ini setara, seperti fdan obj.addValuesmerujuk ke fungsi yang sama:

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

Namun, karena keduanya call()tidak apply()menggunakan nilai penerimanya sendiri untuk menggantikan argumen penerima ketika tidak ditentukan, hal berikut ini tidak akan berfungsi:

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

Nilai thistidak pernah bisa nullatau undefinedketika suatu fungsi dipanggil. Ketika nullatau undefineddiberikan sebagai penerima ke call()atau apply(), objek global digunakan sebagai nilai untuk penerima sebagai gantinya. Oleh karena itu, kode sebelumnya memiliki efek samping yang tidak diinginkan yang sama dengan menambahkan properti yang dinamai valueke objek global.

Mungkin bermanfaat untuk menganggap suatu fungsi sebagai tidak memiliki pengetahuan tentang variabel yang ditugaskan padanya. Ini membantu memperkuat gagasan bahwa nilai ini akan terikat ketika fungsi dipanggil daripada ketika itu didefinisikan.


Akhir ekstrak.

Dominykas Mostauskis
sumber
Hanya untuk mencatat fakta, yang additionalValuestidak dirujuk di dalam obj.addValuestubuh
Viktor Stolbin
Saya tahu Anda menjawab pertanyaan tetapi ingin menambahkan: Anda bisa menggunakan bind saat mendefinisikan f. var f = obj.addValues;menjadi var f = obj.addValues.bind(obj) dan sekarang f (20) akan berfungsi tanpa harus menggunakan panggilan atau mendaftar setiap saat.
jhliberty
Saya tahu Anda tidak menulisnya, tetapi Anda menyoroti teks dan contoh-contoh dari buku tersebut sebagai hal yang relevan, dan saya sangat berterima kasih. Mereka sangat membantu.
Fralcon
34

Terkadang berguna untuk satu objek untuk meminjam fungsi dari objek lain, yang berarti bahwa objek pinjaman hanya menjalankan fungsi yang dipinjamkan seolah-olah itu adalah miliknya sendiri.

Contoh kode kecil:

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

Metode ini sangat berguna untuk memberikan fungsi sementara objek.

tjacks3
sumber
1
Untuk orang-orang yang ingin tahu cara melihat console.loglihat: Apa itu console.log dan bagaimana cara menggunakannya?
Michel Ayres
25

Contoh lain dengan Call, Apply dan Bind. Perbedaan antara Panggilan dan Terapkan jelas, tetapi Bind bekerja seperti ini:

  1. Bind mengembalikan sebuah instance dari fungsi yang dapat dieksekusi
  2. Parameter pertama adalah ' ini '
  3. Parameter kedua adalah daftar argumen yang dipisahkan koma (seperti Panggilan )

}

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
*/
Mahesh
sumber
23

Saya ingin menunjukkan contoh, di mana argumen 'valueForThis' digunakan:

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] 

Rincian **: http://es5.github.io/#x15.4.4.7 *


sumber
20

Panggilan () mengambil argumen yang dipisahkan koma, mis:

.call(scope, arg1, arg2, arg3)

dan apply () mengambil array argumen, mis:

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

berikut ini beberapa contoh penggunaan lainnya: http://blog.i-evaluation.com/2012/08/15/javascript-call-and-apply/

Mark Karwowski
sumber
`// panggil () === argumen yang dipisahkan koma (daftar argumen). panggilan (ini, args1, args2, args3, ...) // apply () === array argumen (array-items). berlaku (ini, [arr0, arr1, arr2, ...]) `
xgqfrms
19

Dari dokumen MDN pada Function.prototype.apply () :

Metode apply () memanggil fungsi dengan thisnilai yang diberikan dan argumen yang disediakan sebagai array (atau objek mirip array).

Sintaksis

fun.apply(thisArg, [argsArray])

Dari dokumen MDN pada Function.prototype.call () :

Metode panggilan () memanggil fungsi dengan thisnilai yang diberikan dan argumen yang disediakan secara individual.

Sintaksis

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

Dari Function.apply dan Function.call dalam JavaScript :

Metode apply () identik dengan panggilan (), kecuali apply () membutuhkan array sebagai parameter kedua. Array mewakili argumen untuk metode target.


Contoh kode:

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

Lihat juga Fiddle ini .

John Slegers
sumber
10

Ini tulisan kecil, saya menulis tentang ini:

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"
Dan
sumber
ini satu lagi: blog.i-evaluation.com/2012/08/15/javascript-call-and-apply tapi pada dasarnya itu benar: .call (ruang lingkup, arg1, arg2, arg3)
Mark Karwowski
7

Perbedaannya adalah bahwa call()mengambil argumen fungsi secara terpisah, dan apply()mengambil argumen fungsi dalam array.

Sanjib Debnath
sumber
6

Kami dapat membedakan metode panggilan dan menerapkan seperti di bawah ini

PANGGILAN: Fungsi dengan argumen yang disediakan secara individual. Jika Anda tahu argumen yang harus diteruskan atau tidak ada argumen untuk lulus, Anda dapat menggunakan panggilan.

BERLAKU: Memanggil fungsi dengan argumen yang disediakan sebagai array. Anda dapat menggunakan berlaku jika Anda tidak tahu berapa banyak argumen yang akan diteruskan ke fungsi.

Ada keuntungan menggunakan apply over call, kita tidak perlu mengubah jumlah argumen hanya kita bisa mengubah array yang diteruskan.

Tidak ada perbedaan besar dalam kinerja. Tetapi kita dapat mengatakan panggilan sedikit lebih cepat dibandingkan dengan menerapkan karena array perlu mengevaluasi dalam menerapkan metode.

Praveen D
sumber
5

Perbedaan antara metode ini adalah, bagaimana Anda ingin melewatkan parameter.

"A untuk array dan C untuk koma" adalah mnemonic yang praktis.

venkat7668
sumber
11
Apa yang disediakan jawaban ini yang belum disediakan dengan baik dalam jawaban lain?
Kyll
5

Panggilan dan terapkan keduanya digunakan untuk memaksa thisnilai ketika suatu fungsi dieksekusi. Satu-satunya perbedaan adalah bahwa callmengambil n+1argumen di mana 1 berada thisdan 'n' arguments. applyhanya membutuhkan dua argumen, satu thisadalah argumen lainnya.

Keuntungan yang saya lihat di applyatas calladalah bahwa kita dapat dengan mudah mendelegasikan pemanggilan fungsi ke fungsi lain tanpa banyak usaha;

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

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

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

Amati betapa mudahnya kita didelegasikan hellountuk sayHellomenggunakan apply, tetapi dengan callini sangat sulit untuk dicapai.

Raghavendra
sumber
4

Meskipun calldan applymencapai hal yang sama, saya pikir ada setidaknya satu tempat di mana Anda tidak dapat menggunakan calltetapi hanya dapat digunakan apply. Saat itulah Anda ingin mendukung warisan dan ingin memanggil konstruktor.

Berikut adalah fungsi yang memungkinkan Anda untuk membuat kelas yang juga mendukung pembuatan kelas dengan memperluas kelas lainnya.

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
Dhana Krishnasamy
sumber
Saya percaya panggilan akan bekerja di sana dengan operator penyebaran seperti yang dijelaskan dalam jawaban yang dipilih. Kecuali saya kehilangan sesuatu.
jhliberty
4

Ringkasan:

Keduanya call()dan apply()merupakan metode yang terletak di Function.prototype. Oleh karena itu mereka tersedia pada setiap objek fungsi melalui rantai prototipe. Keduanya call()dan apply()dapat menjalankan fungsi dengan nilai yang ditentukan dari this.

Perbedaan utama antara call()dan apply()adalah cara Anda harus menyampaikan argumen ke dalamnya. Dalam keduanya call()dan apply()Anda lulus sebagai argumen pertama objek yang Anda inginkan nilainya this. Argumen lain berbeda dengan cara berikut:

  • Dengan call() Anda harus memasukkan argumen secara normal (mulai dari argumen kedua)
  • Dengan apply()Anda harus melewati berbagai argumen.

Contoh:

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

Mengapa saya harus menggunakan fungsi-fungsi ini?

The thisnilai dapat kadang-kadang rumit dalam javascript. Nilai thisditentukan ketika suatu fungsi dieksekusi bukan ketika suatu fungsi didefinisikan. Jika fungsi kita bergantung pada thispengikatan hak kita dapat menggunakan call()dan apply()untuk menegakkan perilaku ini. Sebagai contoh:

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

Willem van der Veen
sumber
4

Perbedaan utamanya adalah, menggunakan panggilan, kita dapat mengubah ruang lingkup dan meneruskan argumen seperti biasa, tetapi berlaku memungkinkan Anda menyebutnya menggunakan argumen sebagai Array (meneruskannya sebagai array). Tetapi dalam hal apa yang harus mereka lakukan dalam kode Anda, mereka sangat mirip.

Sementara sintaks dari fungsi ini hampir identik dengan yang berlaku (), perbedaan mendasar adalah panggilan itu () menerima daftar argumen, sementara apply () menerima satu array argumen.

Jadi seperti yang Anda lihat, tidak ada perbedaan besar, tapi tetap saja, ada beberapa kasus yang kami lebih suka menggunakan panggilan () atau menerapkan (). Misalnya, lihat kode di bawah ini, yang menemukan angka terkecil dan terbesar dalam array dari MDN, menggunakan metode yang berlaku:

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

Jadi perbedaan utama adalah cara kita menyampaikan argumen:

Panggil:

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

Menerapkan:

function.apply(thisArg, [argsArray]);
Alireza
sumber
2

Biarkan saya menambahkan sedikit detail untuk ini.

dua panggilan ini hampir setara:

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

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

Hanya ada perbedaan kecil:

  • The spreadOperator ... memungkinkan melewati iterable args sebagai daftar untuk memanggil.
  • Hanya applymenerima argumen seperti array .

Jadi, panggilan ini saling melengkapi. Di mana kita mengharapkan iterable , callberfungsi, di mana kita mengharapkan seperti array , applyberfungsi.

Dan untuk objek yang bisa diubah - ubah dan mirip-array , seperti array nyata, kami secara teknis bisa menggunakan salah satunya, tetapi menerapkan mungkin akan lebih cepat karena sebagian besar mesin JavaScript mengoptimalkannya dengan lebih baik.

Pravin Divraniya
sumber