Pertanyaan Apa perbedaan antara menelepon dan mendaftar?


Apa perbedaan antara menggunakan call dan apply untuk memanggil suatu fungsi?

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

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

Apakah ada perbedaan kinerja antara kedua metode tersebut? Kapan sebaiknya digunakan call lebih apply dan sebaliknya?


2737
2017-12-31 19:56


asal


Jawaban:


Perbedaannya adalah itu apply memungkinkan Anda menjalankan fungsi dengan arguments sebagai larik; call membutuhkan parameter dicantumkan secara eksplisit. Sebuah mnemonic yang berguna adalah "SEBUAH untuk Sebuahrray dan C untuk comma. "

Lihat dokumentasi MDN di menerapkan dan panggilan.

Sintaks pseudo:

theFunction.apply(valueForThis, arrayOfArgs)

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

Ada juga, pada ES6, kemungkinan untuk spread array untuk digunakan dengan call berfungsi, Anda dapat melihat kompatibilitas 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


3304
2017-12-31 20:00



K. Scott Allen punya Langgan bagus tentang masalah itu.

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

Metode apply () identik dengan call (), 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"]);

209
2017-12-31 19:59



Untuk menjawab bagian tentang kapan menggunakan setiap fungsi, gunakan apply jika Anda tidak tahu jumlah argumen yang akan Anda lewati, atau jika mereka sudah berada dalam array atau objek seperti array (seperti arguments keberatan untuk meneruskan argumen Anda sendiri. Menggunakan call jika tidak, karena tidak perlu membungkus argumen dalam sebuah 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 menyampaikan argumen (seperti contoh Anda), saya lebih suka call sejak saya panggilan fungsi itu. apply akan menyiratkan Anda melamar fungsi ke argumen (tidak ada).

Seharusnya tidak ada perbedaan kinerja, kecuali mungkin jika Anda menggunakan apply dan membungkus argumen dalam larik (mis. f.apply(thisObject, [a, b, c]) dari pada f.call(thisObject, a, b, c)). Saya belum mengujinya, jadi mungkin ada perbedaan, tetapi akan sangat spesifik browser. Sepertinya begitu call lebih cepat jika Anda belum memiliki argumen dalam array dan apply lebih cepat jika Anda melakukannya.


150
2017-12-31 21:50



Ini mnemonik yang bagus. SEBUAHmenggunakan pply SEBUAHrays dan SEBUAHlways membutuhkan satu atau dua Argumen. Ketika Anda menggunakan Csemua yang harus Anda lakukan Countuk jumlah argumen.


102
2017-09-04 13:36



Meskipun ini adalah topik lama, saya hanya ingin menunjukkan bahwa. Panggilan sedikit lebih cepat daripada .apply. Saya tidak bisa mengatakan dengan tepat 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

Terapkan mengambil larik argumen, sementara Panggil mengambil nol atau lebih parameter individual! Ah hah!

.apply(this, [...])

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


91
2017-11-07 17:36



Mengikuti ekstrak dari Penutupan: The Definitive Guide oleh Michael Bolin. Mungkin terlihat agak panjang, tapi itu jenuh dengan banyak wawasan. Dari "Lampiran B. Konsep JavaScript yang Sering Disalahpahami":


Apa this Mengacu pada Ketika suatu Fungsi Disebut

Saat memanggil fungsi formulir foo.bar.baz(), objeknya foo.bar disebut sebagai penerima. Ketika fungsi ini 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. Sebagaimana dijelaskan dalam "goog.global" di halaman 47, jendela adalah objek global ketika JavaScript dijalankan di browser web. Ini mengarah pada beberapa perilaku yang 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.addValues dan f merujuk pada fungsi yang sama, mereka berperilaku berbeda ketika dipanggil karena nilai penerima berbeda dalam setiap panggilan. Untuk alasan ini, ketika memanggil fungsi yang mengacu this, penting untuk memastikan hal itu this akan memiliki nilai yang benar ketika dipanggil. Jelas, jika this tidak direferensikan dalam tubuh fungsi, maka perilaku f(20) dan obj.addValues(20) akan sama.

Karena fungsi adalah objek kelas satu di JavaScript, mereka dapat memiliki metode sendiri. Semua fungsi memiliki metode call() dan apply() yang memungkinkan untuk mendefinisikan kembali penerima (yaitu, objek itu this mengacu pada) saat 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() Apakah itu call() menerima parameter fungsi sebagai argumen individu, sedangkan apply() menerima mereka sebagai larik 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 f dan obj.addValues lihat fungsi yang sama:

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

Namun, karena keduanya call() maupun apply() menggunakan nilai penerima sendiri untuk menggantikan argumen receiver ketika tidak ditentukan, yang 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 dari this tidak akan pernah bisa null atau undefined ketika suatu fungsi dipanggil. Kapan null atau undefined diberikan sebagai penerima ke call() atau apply(), objek global digunakan sebagai nilai untuk penerima. Oleh karena itu, kode sebelumnya memiliki efek samping yang tidak diinginkan yang sama dengan penambahan properti bernama value ke objek global.

Mungkin berguna untuk memikirkan fungsi karena tidak memiliki pengetahuan tentang variabel yang ditugaskan. Ini membantu memperkuat gagasan bahwa nilai ini akan terikat ketika fungsi dipanggil daripada ketika didefinisikan.


Akhir dari ekstrak.


71
2017-12-04 12:41



Kadang-kadang berguna untuk satu objek untuk meminjam fungsi objek lain, yang berarti bahwa objek pinjaman hanya menjalankan fungsi yang dipinjamkan seolah-olah itu 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-metode ini sangat berguna untuk memberikan objek fungsi sementara.


33
2018-02-25 19:31



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

  1. Bind mengembalikan sebuah instance dari fungsi yang dapat dieksekusi
  2. Parameter Pertama adalah 'ini'
  3. Parameter kedua adalah a Dipisahkan koma daftar argumen (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
*/

23
2018-03-31 07:32



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] 

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


21
2017-07-05 10:56