Apa perbedaan antara panggilan dan terapkan?
Apa perbedaan antara menggunakan call
dan apply
untuk memanggil fungsi?
var func = function() {
alert('hello!');
};
func.berlaku();
vs func.call();
Apakah ada perbedaan kinerja antara dua metode tersebut? Ketika itu yang terbaik untuk menggunakan panggilan
atas apply
dan sebaliknya?
3002
21
Perbedaannya adalah bahwa
terapkan
memungkinkan anda memanggil fungsi denganargumen
sebagai array;panggilan
membutuhkan parameter dicantumkan secara eksplisit. Berguna mnemonic adalah "A untuk array dan C untuk comma."Lihat MDN's dokumentasi pada apply dan panggilan.
Pseudo sintaks:
fungsi.menerapkan(valueForThis, arrayOfArgs)
fungsi.panggilan(valueForThis, arg1, arg2, ...)
Ada juga, seperti dari ES6, kemungkinan untuk
menyebar
array untuk digunakan denganpanggilan
fungsi, anda dapat melihat kompatibilitas di sini.Contoh kode:
K. Scott Allen telah bagus writeup tentang masalah ini.
Pada dasarnya, mereka berbeda tentang bagaimana mereka menangani argumen fungsi.
Jadi:
Untuk menjawab bagian tentang kapan harus menggunakan setiap fungsi, penggunaan
berlaku
jika anda don't tahu jumlah dari argumen anda akan lewat, atau jika mereka sudah dalam array atau array-seperti objek (sepertiargumen
objek untuk meneruskan argumen anda sendiri. Gunakanpanggilan
jika tidak, sejak ada's tidak perlu untuk membungkus argumen dalam array.Ketika saya'm tidak melewati argumen (seperti contoh), saya lebih memilih
panggilan
sejak saya'm menelepon fungsi.terapkan
akan berarti anda menerapkan fungsi untuk (tidak ada) argumen.Seharusnya't akan ada perbedaan kinerja, kecuali mungkin jika anda menggunakan
apply
dan bungkus argumen array (mis.f.menerapkan(thisObject, [a, b, c])
, bukanf.panggilan(thisObject, a, b, c)
). Aku ingin't diuji, jadi mungkin ada perbedaan, tapi itu akan sangat browser tertentu. It's kemungkinan bahwapanggilan
lebih cepat jika anda don't sudah memiliki argumen array danterapkan
lebih cepat jika anda melakukannya.Berikut ini's yang baik mnemonic. Arlaku menggunakan Arrays dan Always mengambil satu atau dua Argumen. Ketika anda menggunakan Csemua yang harus anda Cntuk jumlah argumen.
Sementara ini adalah topik lama, aku hanya ingin menunjukkan bahwa .panggilan adalah sedikit lebih cepat daripada .berlaku. Saya dapat't memberitahu anda persis 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
Menerapkan mengambil array argumen, saat Panggilan berlangsung nol atau lebih parameter individu! Ah hah!
.menerapkan(ini, [...])
.call(ini, param1, param2, param3, param4...)
Berikut kutipan dari Penutupan: Panduan Definitif oleh Michael Bolin. Mungkin terlihat sedikit panjang, tapi itu's jenuh dengan banyak wawasan. Dari "Lampiran B. Sering Disalahpahami JavaScript Konsep":
Apa yang
ini
Mengacu pada Saat Fungsi DipanggilKetika memanggil sebuah fungsi dari bentuk
foo.bar.baz()
, objekfoo.bar
ini disebut sebagai penerima. Ketika fungsi ini dipanggil, itu adalah receiver yang digunakan sebagai nilai untukini
:Jika tidak ada secara eksplisit penerima ketika fungsi dipanggil, maka objek global menjadi penerima. Seperti yang dijelaskan di "goog.global" di halaman 47, jendela objek global ketika JavaScript dijalankan di web browser. Hal ini menyebabkan beberapa perilaku mengejutkan:
Meskipun
obj.addValues
danf
mengacu pada fungsi yang sama, mereka berperilaku berbeda ketika disebut karena nilai penerima yang berbeda di setiap panggilan. Untuk alasan ini, ketika memanggil sebuah fungsi yang mengacu padaini
, itu adalah penting untuk memastikan bahwaini
akan memiliki nilai yang benar ketika dipanggil. Untuk menjadi jelas, jikaini
yang tidak disebutkan dalam fungsi tubuh, maka perilakuf(20)
danobj.addValues(20)
akan sama.Karena fungsi kelas objek dalam JavaScript, mereka dapat memiliki metode mereka sendiri. Semua fungsi memiliki metode
call()
danberlaku()
yang membuatnya mungkin untuk mendefinisikan penerima (yaitu, objek yangini
menunjuk pada) saat memanggil fungsi tersebut. Metode tanda tangan adalah sebagai berikut:Perhatikan bahwa satu-satunya perbedaan antara
call()
danberlaku()
adalahpanggilan()
menerima parameter fungsi sebagai argumen individu, sedangkanberlaku()
menerima mereka sebagai satu array:Berikut panggilan yang setara, seperti
f
danobj.addValues
merujuk kepada fungsi yang sama:Namun, karena tidak ada
panggilan()
atauberlaku()
menggunakan nilai sendiri penerima untuk pengganti penerima argumen ketika itu adalah yang tidak ditentukan, berikut tidak akan bekerja:Nilai
ini
tidak dapatnull
atauundefined
ketika fungsi dipanggil. Ketikanull
atauundefined
disediakan sebagai penerima untukcall()
atauberlaku()
, global objek digunakan sebagai nilai untuk penerima sebaliknya. Oleh karena itu, sebelumnya memiliki kode yang sama efek samping yang tidak diinginkan dari menambahkan sebuah properti bernamanilai
untuk objek global.Mungkin akan membantu untuk berpikir tentang fungsi sebagai tidak memiliki pengetahuan tentang variabel yang ditetapkan. Hal ini membantu memperkuat gagasan bahwa nilai ini akan terikat ketika fungsi ini dipanggil daripada ketika didefinisikan.
Akhir dari ekstrak.
Hal ini berguna di kali untuk satu objek untuk meminjam fungsi dari objek lain, yang berarti bahwa pinjaman objek hanya menjalankan masa prapaskah fungsi seolah-olah itu sendiri.
Kode kecil contoh:
Metode ini sangat berguna untuk memberikan benda-benda yang bersifat sementara fungsi.
Contoh lain dengan Panggilan, Berlaku dan Mengikat. Perbedaan antara Panggilan dan Menerapkan jelas, tapi Mengikat bekerja seperti ini:
}
I'd ingin menunjukkan sebuah contoh, dimana 'valueForThis' argumen yang digunakan:
*rincian: http://es5.github.io/#x15.4.4.7
Call() mengambil koma-dipisahkan argumen, ex:
.panggilan(ruang lingkup, arg1, arg2, arg3)
dan menerapkan() mengambil sebuah array argumen, ex:
.menerapkan(ruang lingkup, [arg1, arg2, arg3])
berikut ini adalah beberapa contoh penggunaan: http://blog.i-evaluation.com/2012/08/15/javascript-call-and-apply/
Dari MDN docs pada Fungsi.prototipe.berlaku() :
Dari MDN docs pada Fungsi.prototipe.call() :
Dari Fungsi.menerapkan dan Fungsi.panggilan di JavaScript :
Contoh kode :
Lihat juga [ini Biola][4].
Perbedaan mendasar adalah bahwa
call()
menerima daftar argumen, sementaraberlaku()
menerima satu array argumen.Berikut ini's kecil-ish posting, saya menulis tentang hal ini:
http://sizeableidea.com/call-versus-apply-javascript/
Perbedaannya adalah bahwa
call()
mengambil argumen fungsi secara terpisah, danberlaku()
mengambil argumen fungsi dalam array.Kita dapat membedakan panggilan dan menerapkan metode seperti di bawah ini
CALL : fungsi dengan argumen menyediakan secara individual. Jika anda tahu argumen untuk diteruskan atau tidak ada argumen untuk lulus anda dapat menggunakan panggilan.
BERLAKU : Memanggil fungsi dengan argumen yang disediakan sebagai array. Anda dapat menggunakan terapkan jika anda don't tahu berapa banyak argumen yang akan lolos ke fungsi.
Ada keuntungan menggunakan berlaku selama panggilan, kami don't perlu untuk mengubah jumlah argumen hanya kita dapat mengubah sebuah array yang dilewatkan.
Tidak ada perbedaan besar dalam kinerja. Tetapi kita dapat mengatakan panggilan adalah sedikit lebih cepat dibandingkan untuk menerapkan karena array perlu mengevaluasi dalam menerapkan metode.
Perbedaan antara kedua metode ini adalah, bagaimana anda ingin untuk melewatkan parameter.
"Untuk sebuah array dan C untuk koma" adalah berguna mnemonic.
Panggilan dan berlaku baik digunakan untuk memaksa
ini
nilai saat fungsi dijalankan. Satu-satunya perbedaan adalah bahwapanggilan
mengambiln+1
argumen di mana 1 adalahini
dan'n' argumen
.terapkan
hanya membutuhkan dua argumen, salah satunya adalahini
yang lain adalah argumen array.Keuntungan yang saya lihat di
berlaku
ataspanggilan
adalah bahwa kita dapat dengan mudah mendelegasikan fungsi yang memanggil fungsi lain tanpa banyak usaha;Mengamati bagaimana dengan mudah kita didelegasikan
hello
untuksayHello
menggunakanberlaku
, tapi dengancall
ini sangat sulit untuk mencapai.Meskipun
call
danterapkan
mencapai hal yang sama, saya pikir ada minimal satu tempat di mana anda tidak dapat menggunakanpanggilan
, tapi hanya dapat menggunakanterapkan
. Itu adalah ketika anda ingin mendukung warisan dan ingin memanggil konstruktor.Berikut ini adalah fungsi memungkinkan anda untuk membuat kelas-kelas yang juga mendukung menciptakan kelas-kelas dengan memperluas kelas-kelas lain.
Perbedaan utama adalah, menggunakan call, kita dapat mengubah lingkup dan melewati argumen seperti biasa, tapi menerapkan memungkinkan anda menelepon menggunakan argumen sebagai Array (lulus mereka sebagai array). Tetapi dalam hal apa yang mereka lakukan dalam kode anda, mereka cukup mirip.
Jadi seperti yang anda lihat, tidak ada perbedaan besar, tapi masih ada kasus-kasus yang kita sukai menggunakan panggilan() atau berlaku(). Untuk contoh, lihat kode di bawah ini, yang menemukan terkecil dan terbesar dalam array dari MDN, menggunakan terapkan metode:
Jadi perbedaan utama adalah hanya cara kita menyampaikan argumen:
Hubungi:
Berlaku:
Penjelasan:
Kedua
call()
danberlaku()
adalah metode yang terletak diFungsi.prototipe
. Oleh karena itu mereka tersedia pada setiap fungsi objek melalui prototipe rantai. Keduacall()
danberlaku()
dapat menjalankan fungsi dengan nilai tertentu dariini
.Perbedaan utama antara
call()
danberlaku()
adalah cara yang anda harus lulus dalam argumen ke dalamnya. Dalam keduacall()
danberlaku()
anda lulus sebagai argumen pertama objek yang anda ingin menjadi nilai sepertiini
. Argumen lain yang berbeda dengan cara sebagai berikut:call()
anda harus dimasukkan ke dalam argumen-argumen yang biasanya (mulai dari argumen kedua)berlaku()
anda harus lulus dalam array argumen.Contoh:
Mengapa saya perlu menggunakan fungsi-fungsi ini?
Yang
ini
nilai dapat sulit kadang-kadang dalam javascript. Nilaiini
ditentukan ketika fungsi ini tidak dieksekusi ketika suatu fungsi didefinisikan. Jika fungsi kita adalah dependend pada kananini
mengikat kita dapat menggunakancall()
danberlaku()
untuk menegakkan perilaku ini. Misalnya: