Dalam JavaScript, apakah ada bedanya jika saya memanggil fungsi dengan tanda kurung?

105

Saya melihat perbedaan saat memanggil fungsi dengan tanda kurung kosong, atau tanpa tanda kurung sama sekali. Namun, saya tidak memberikan argumen apa pun ke fungsi tersebut, jadi saya bertanya-tanya, apa perbedaan antara:

window.onload = initAll();

dan

window.onload = initAll;

Tolong jelaskan prinsip di baliknya.

Dekan
sumber
24
@JS Bangs - Hanya dalam bahasa Inggris AS; bukan di tempat lain. Meskipun pemrogram cenderung menyebutnya "tanda kurung" untuk menghindari kebingungan, dalam bahasa Inggris Inggris, yang dibulatkan hanya disebut sebagai tanda kurung. Yang persegi dikenal sebagai "tanda kurung siku". en.wikipedia.org/wiki/Bracket
Rob Levine
13
pada catatan serius, nama UNICODE resmi adalah Tanda kurung. 0028 ( LEFT PARENTHESIS = buka kurung (1.0) dan 0029 ) RIGHT PARENTHESIS = tutup kurung (1.0) - unicode.org/charts/charindex.html#P dan apa yang Dictionary.com katakan tentangnya - dictionary.reference.com/ browse / PARENTHESIS "Salah satu atau kedua garis lengkung tegak, () ..."
8
Jadi ini bukan hanya tentang "US English", ini adalah definisi standar internasional karena UNICODE adalah Standar Internasional.
2
@fuzzy - Dari mana Anda mendapatkan fakta, serius? {}disebut tanda kurung tupai.
Anurag
7
@fuzzy lollipop - Unicode adalah standar internasional tentang pengkodean karakter sebagai byte, bukan penamaan. Penulis dokumen unicode tidak mengklaim nama yang diberikan untuk karakter adalah standar internasional. Ini adalah kode vs. karakter yang mereka definisikan. Namun, Anda mungkin ingin mencatat bahwa mereka juga merujuk ke [dan] sebagai tanda kurung siku - (bukan hanya "tanda kurung"), dan bahwa mereka merujuk ke semua [, {dan (sebagai karakter tanda kurung. Anda harus berusaha untuk memahami nuansanya di tempat yang berbeda menggunakan kata yang sama. Sangat penting jika Anda adalah bagian dari tim internasional.
Rob Levine

Jawaban:

161
window.onload = initAll();

Ini langsung dijalankan dan menetapkan nilai kembali fungsi ke . Ini biasanya bukan yang Anda inginkan. harus mengembalikan fungsi agar ini masuk akal.initAll() window.onloadinitAll()

window.onload = initAll;

ini menetapkan fungsi sebenarnya ke window.onload- ini dimungkinkan karena dalam JavaScript, seperti yang dikatakan @Felix, fungsi adalah objek kelas satu - tanpa menjalankannya. initAllakan dieksekusi oleh event load.

Pekka
sumber
18
Penting untuk disebutkan di sini adalah bahwa fungsi adalah objek kelas satu dalam JavaScript.
Felix Kling
136

Apa yang dikatakan Pekka benar, tetapi saya ingin menjelaskan sedikit dengan contoh yang akan membantu menjelaskan kepada seseorang yang tidak sepenuhnya memahami penunjuk fungsi atau delegasi.

Saya tidak akan menggunakan window.onloadkarena itu sedikit dibuat-buat untuk didemonstrasikan. Saya akan menggunakan fungsi perkalian sederhana untuk mendemonstrasikan:

function Multiply(operator, operand) {
    return operator * operand;
}

Ini sama-sama bisa ditulis:

Multiply = function(operator, operand) {
    return operator * operand;
}

Sementara di contoh pertama, implikasinya mungkin tidak jelas, contoh kedua menunjukkan lebih jelas bahwa kita menetapkan fungsi yang memiliki 2 parameter ke variabel yang dipanggil Multiply, dan konsep fungsi sebagai tugas ini umum di seluruh JavaScript. Ini adalah demonstrasi kecil dari fakta bahwa fungsi adalah "warga kelas satu" , artinya, dapat diedarkan persis seperti kita sedang menyebarkan nilai.

Jadi sekarang untuk perbedaan tugas:

var operator = 3;
var operand = 4;
var ret = Multiply(operator, operand);

Pada titik mendefinisikan variabel ret, Multiplydieksekusi dan nilai kembalian ditetapkan - retmenjadi sama dengan 12.

Mari kita coba lagi dengan cara yang berbeda:

var operator = 3;
var operand = 4;
var ret = Multiply;

Sekarang, pada titik pendefinisian ret, retmenjadi Multiplyfungsi Anda dan bukan hasil yang diperoleh dari Multiplyfungsi Anda . Panggilan ke ret()akan menyebabkan Multiplyfungsi Anda dijalankan, dan Anda dapat memanggilnya persis seperti jika Anda memanggil Multiply(operator, operand):

var out = ret(3, 4);

sama dengan

var out = Multiply(3, 4);

Anda telah secara efektif mengatakan bahwa Anda akan menggunakan retsebagai delegasi untuk Multiply(). Saat memanggil ret, kami benar-benar mengacu pada Multiplyfungsinya.

Kembali ke Anda window.onload. Pikirkan ini sebagai:

window.onload = function() {
    //Doing what all good window.onload functions should do...
}

initAll = function() {
    return 12;
}

Jadi seperti yang Anda lihat, window.onloadadalah fungsi seperti fungsi lainnya, tidak ada yang istimewa tentangnya. Anda dapat menetapkan nilai, menetapkan fungsi, membatalkannya jika Anda mau - intinya adalah bahwa tidak ada yang lebih istimewa window.onloaddari pada fungsi Anda sendiri. Satu-satunya hal yang sedikit berbeda adalah ia dipanggil oleh jendela saat dimuat. [Penafian: Saya tidak pernah benar-benar membatalkan fungsi jendela, jadi saya tidak yakin apakah ini akan menyebabkan dampak negatif. Seseorang akan berharap mereka memeriksa untuk melihat apakah suatu fungsi ditugaskan sebelum memanggilnya yaitu if (window.onload) window.onload();].

Sekarang menyebut initAll()apa yang kami katakan adalah:

window.onload = initAll();

yang mungkin juga mengatakan:

window.onload = 12;

Tetapi ketika kami mengatakan initAlltanpa tanda kurung, yang sebenarnya kami katakan adalah: Saya ingin mengganti apa pun fungsi window.onload saya, dengan fungsi baru - yaitu saya ingin menggantinya dengan initAllfungsi saya , sehingga setiap panggilan untuk window.onloadmenjalankan initAllkode.

Begitu:

window.onload = function() {
    //Doing what all good window.onload functions should do...
}

diganti dengan:

window.onload = function() {
    return 12;
}

Jadi setiap panggilan ke window.onloadakan menjalankan initAllfungsi Anda, bukan apa pun window.onloadyang semula. Anda telah mengganti fungsi asli dengan fungsi baru Anda.

Bahkan, Anda juga bisa menulis:

window.onload = function() {
    //Write all your init code right in here instead of having a separate 
    //initAll function.
}

Contoh lain yang mungkin menunjukkan lebih baik adalah ini:

var d = new Date();
var currentTime = d.getTime();

Apapun waktu itu pada saat ditu ditentukan akhirnya ditetapkan ke currentTime. Bagus, tapi itu hanya berguna jika kita ingin mengetahui jam berapa fungsi yang berisi kode itu dipanggil - yaitu pada waktu buka halaman. Bagaimana jika kita menginginkan waktu saat ini setiap saat yang currentTimedisebut?

var currentTime = function() {
    var d = new Date();
    return d.getTime();
}

var a = currentTime(); //The current time at the point a is defined...
var b = currentTime;   //b is a functional reference to currentTime...
var c = b(); //The current time when variable c is defined
var d = c; //The current time when variable c was defined

Perhatikan bagaimana kita sebut b()di kami cdan dtugas persis seperti yang kita bisa menelepon currentTime()?

BenAlabaster
sumber
Jawaban yang luar biasa!
Shadi Almosri
Hai, bagaimana jika saya ingin menambahkan fungsi yang membutuhkan argumen pada pendengar acara?
Shemiroth
16

Fungsi dalam javascript adalah warga negara kelas satu, dan dengan demikian, dapat ditugaskan ke variabel lain atau diteruskan sebagai argumen.

Jadi, saat Anda melakukannya

window.onload = initAll;

Anda menyetel onloadproperti windowobjek untuk mereferensikan initAllfungsi itu sendiri.

Saat kamu melakukan

window.onload = initAll();

Anda menyetel onloadproperti untuk menampung nilai kembalian dari initAll, karena ini akan dieksekusi di tempat pada baris itu.

Peter Bailey
sumber
10

initAll adalah referensi ke nilai fungsi dan operator tanda kurung ditambahkan ke nama fungsi RUNS objek fungsi ini.

Jadi jika Anda melakukan sesuatu seperti

a = initAll

maka aakan menjadi sama seperti initAll- misalnya Anda dapat melakukannya a()- tetapi dengan

a = initAll()

variabel aakan mendapatkan nilai kembali dari initAllfungsi yang dieksekusi

Andris
sumber
8

Saya terlambat 6 tahun tetapi saya merasa ini bisa dijelaskan jauh lebih sederhana daripada jawaban di atas.

Jadi di sini adalah TLDR ; atau pandangan mata burung saat memanggil fungsi menggunakan dan tidak menggunakan ()'s

Mari kita ambil fungsi ini sebagai contoh:

function foo(){
return 123;
}

jika Anda log "foo" - tanpa ()

console.log(foo); 

---outout------
function foo(){
return 123;
}

Tidak menggunakan ()sarana untuk mengambil fungsi itu sendiri . Anda akan melakukan ini jika ingin diteruskan sebagai callback.


jika Anda memasukkan "foo ()" - dengan ()

console.log(foo());
-----output-----
 123

Menggunakan ()setelah suatu fungsi berarti menjalankan fungsi tersebut dan mengembalikan nilainya .

garrettmac
sumber