Saya masih ingat semasa saya menemu duga sebagai pelatih di Tencent, penemuduga bertanyakan soalan ini kepada saya.
Pada mulanya saya hanya mengetahui dua kaedah pengisytiharan: pengisytiharan fungsi dan ungkapan fungsi saya tidak dapat menerangkan perbezaan khusus. Saya kebetulan melihat sebuah buku mengenai topik ini baru-baru ini dan ingin meringkaskannya.
Dalam ECMAScript, terdapat dua kaedah yang paling biasa digunakan untuk mencipta objek fungsi, iaitu menggunakan ungkapan fungsi atau menggunakan pengisytiharan fungsi. Dalam hal ini, spesifikasi ECMAScript menjelaskan bahawa pengisytiharan fungsi mesti sentiasa mempunyai pengecam (Pengecam), iaitu apa yang kita panggil nama fungsi, dan ungkapan fungsi boleh ditinggalkan.
Pengisytiharan fungsi:
1. Buat objek Fungsi baharu, FormalParameterList menentukan parameter dan FunctionBody menentukan badan fungsi. Menggunakan rantai skop dalam persekitaran yang sedang berjalan sebagai skopnya.
2. Cipta atribut bernama Pengecam untuk objek pembolehubah semasa, dengan nilai Result(1).
Ungkapan fungsi:
(Ungkapan fungsi dibahagikan kepada ungkapan fungsi tanpa nama dan dinamakan)
Proses penghuraian bagi ungkapan fungsi yang dinamakan adalah seperti berikut:
1. Cipta Objek baharu
2. Tambahkan Hasil(1) pada bahagian atas rantai skop
3. Cipta objek Function baharu, nyatakan parameter dalam FormalParameterList dan nyatakan badan fungsi dalam FunctionBody. Menggunakan rantai skop dalam persekitaran pelaksanaan yang sedang berjalan sebagai skopnya.
4. Cipta atribut bernama Identifier for Result(1), nilainya ialah Result(3), baca sahaja, tidak boleh dipadamkan
5. Alih keluar Result(1)
daripada rantai skop
6. Keputusan Pulangan(3)
Dokumentasi rasmi sangat sukar dibaca. Ringkasnya, ECMAScript membezakan keduanya melalui konteks: jika function foo(){} ialah sebahagian daripada ungkapan tugasan, ia dianggap sebagai ungkapan fungsi. Dan jika fungsi foo(){} terkandung dalam badan fungsi, atau terletak dalam (peringkat atas) atur cara, ia dihuraikan sebagai pengisytiharan fungsi. Jelas sekali, apabila pengecam ditinggalkan, "ungkapan" hanya boleh menjadi ungkapan.
Ada satu lagi situasi:
Kes ini juga merupakan ungkapan fungsi, yang merupakan fungsi yang disertakan dalam sepasang kurungan Dalam konteksnya, () membentuk operator kumpulan dan operator kumpulan hanya boleh mengandungi ungkapan Lagi Contoh:
Mari kita bincangkan secara ringkas tentang persamaan dan perbezaan antara pengisytiharan fungsi dan ungkapan fungsi. Terdapat perbezaan yang halus namun penting dalam tingkah laku pengisytiharan dan ungkapan.
Pertama, pengisytiharan fungsi dihuraikan dan dinilai sebelum sebarang ungkapan dihuraikan dan dinilai. Walaupun pengisytiharan ialah baris terakhir dalam kod sumber, ia akan dinilai sebelum ungkapan pertama dalam skop yang sama. Lebih mudah difahami dengan melihat contoh. Dalam contoh berikut, fungsi fn diisytiharkan selepas amaran. Walau bagaimanapun, apabila amaran dilaksanakan, fn sudah ditakrifkan:
Untuk meringkaskan secara ringkas, apakah perbezaannya?
Pengisytiharan fungsi mempunyai satu lagi ciri penting,
. Iaitu:
FunctionDeclaration hanya boleh muncul dalam Program atau FunctionBody. Secara sintaksis, ia tidak boleh muncul di dalam Blok ({ ... }), contohnya, dalam pernyataan if, while, atau for. Kerana Blok hanya boleh mengandungi Pernyataan, tetapi bukan SourceElement seperti FunctionDeclaration.
Sebaliknya, jika anda melihat dengan lebih dekat peraturan penjanaan, anda akan mendapati bahawa satu-satunya cara untuk Ekspresi muncul dalam Blok ialah menjadikannya sebahagian daripada Pernyataan Ungkapan. Walau bagaimanapun, spesifikasi dengan jelas menyatakan bahawa ExpressionStatement tidak boleh bermula dengan fungsi kata kunci. Perkara ini sebenarnya bermakna bahawa FunctionExpression tidak boleh muncul dalam Pernyataan atau Blok (jangan lupa bahawa Blok terdiri daripada Pernyataan).
Disebabkan oleh sekatan di atas, setiap kali fungsi muncul dalam blok (seperti dalam contoh di atas), ia sepatutnya dianggap sebagai ralat sintaks dan bukannya pengisytiharan atau ungkapan fungsi.
Jadi bilakah kita harus menggunakan pengisytiharan fungsi atau ungkapan fungsi? Pengisytiharan fungsi hanya boleh muncul dalam "kod program", yang bermaksud ia hanya boleh muncul dalam badan fungsi lain atau dalam ruang global tidak boleh diberikan kepada pembolehubah atau atribut, atau diluluskan sebagai parameter dalam panggilan fungsi; Contohnya ialah penggunaan pengisytiharan fungsi yang dibenarkan foo(), bar() dan local() semuanya diisytiharkan melalui mod pengisytiharan fungsi:
.Pengetahuan saya terhad, tolong betulkan saya jika ada kesilapan.