mata teras
if
ketinggian dalam JavaScript bermakna pembolehubah dan pengisytiharan fungsi dipindahkan ke bahagian atas skop mereka yang disertakan semasa penyusunan, tetapi permulaan tidak dinaikkan. for
with
table.sp_table { width: 100%; border-collapse: collapse; border-spacing: 0; } table.sp_table td, table.sp_table th { border: solid 1px #ccc; padding: 10px; line-height: 1.5; text-align: center; width: 20%; } table.sp_table tr td:first-child { font-weight: bold; }
skop with
Kebanyakan pemaju mula menggunakan JavaScript kerana mereka terpaksa berbuat demikian, dan hampir semua pemaju mula menulis kod sebelum mereka menghabiskan masa belajar bahasa. Setiap pemaju sedemikian telah tertipu oleh skop JavaScript sekurang -kurangnya sekali. Kerana sintaks JavaScript sangat mirip dengan C-Series (sengaja), memisahkan badan fungsi, jika dan dengan pendakap, orang secara munasabah mengharapkan lobak leksis leksikal. Malangnya, ini tidak berlaku. Pertama, dalam JavaScript, skop berubah -ubah ditentukan oleh fungsi, bukan oleh kurungan. Dalam erti kata lain, jika dan untuk badan tidak membuat skop baru, dan pembolehubah yang diisytiharkan di dalam badan mereka sebenarnya dipromosikan, iaitu dicipta pada permulaan fungsi paling dalam yang mengisytiharkannya, jika tidak, skop global. Kedua, kewujudan kenyataan with
memaksa skop JavaScript menjadi dinamik dan tidak dapat ditentukan sehingga runtime. Anda mungkin tidak terkejut mendengar bahawa penggunaan kenyataan with
telah ditolak: JavaScript tanpa with
sebenarnya akan menjadi bahasa leksikal, iaitu, skop dapat ditentukan sepenuhnya dengan melihat kod tersebut. Formal, dalam JavaScript, terdapat empat cara untuk masuk ke dalam skop: - Definisi Bahasa: Secara lalai, semua skop mengandungi nama this
dan arguments
. - Parameter rasmi: Skop mana -mana (formal) parameter yang diisytiharkan untuk fungsi milik badan fungsi. - Pengisytiharan fungsi. - Pengisytiharan Variabel.
Satu lagi kerumitan disebabkan oleh skop global yang tersirat bagi tugasan yang berubah -ubah untuk (secara tersirat) tidak diisytiharkan dalam kata kunci var
. Kegilaan ini digabungkan dengan penyerahan skop global yang tersirat ke this
rujukan apabila memanggil fungsi tanpa mengikat eksplisit (lebih banyak pada bahagian seterusnya). Sebelum menggali butiran, mari kita jelaskan corak yang baik boleh digunakan untuk mengelakkan kekeliruan: Gunakan Corak ketat ('use strict';
), dan gerakkan semua pembolehubah dan pengisytiharan fungsi ke bahagian atas setiap fungsi; Di dalam dan jika blok, dan pengisytiharan fungsi dalam blok tersebut (ini adalah di luar skop artikel ini atas sebab -sebab yang berbeza).
ketinggian adalah kaedah yang mudah untuk menjelaskan tingkah laku sebenar pernyataan. Pemboleh ubah yang dipromosikan diisytiharkan pada permulaan fungsi yang terkandung dan diasaskan kepada undefined
. Tugasan itu kemudiannya berlaku dalam barisan sebenar perisytiharan asal. Sila lihat contoh berikut:
table.sp_table { width: 100%; border-collapse: collapse; border-spacing: 0; } table.sp_table td, table.sp_table th { border: solid 1px #ccc; padding: 10px; line-height: 1.5; text-align: center; width: 20%; } table.sp_table tr td:first-child { font-weight: bold; }
Apakah nilai yang anda harapkan untuk mencetak ke konsol? Adakah anda akan terkejut dengan output berikut?
table.sp_table { width: 100%; border-collapse: collapse; border-spacing: 0; } table.sp_table td, table.sp_table th { border: solid 1px #ccc; padding: 10px; line-height: 1.5; text-align: center; width: 20%; } table.sp_table tr td:first-child { font-weight: bold; }
Dalam blok if
, pernyataan var
tidak mengisytiharkan salinan tempatan pembolehubah i
, melainkan menimpa pembolehubah yang diisytiharkan sebelumnya. Ambil perhatian bahawa pernyataan console.log
pertama mencetak nilai sebenar pembolehubah i
, yang diasaskan kepada undefined
. Anda boleh mengujinya dengan menggunakan arahan "use strict";
sebagai baris pertama dalam fungsi. Dalam mod yang ketat, pembolehubah mesti diisytiharkan sebelum menggunakannya, tetapi anda boleh menyemak bahawa enjin JavaScript tidak melaporkan kesilapan kerana perisytiharan itu. Dengan cara ini, sila ambil perhatian bahawa anda tidak akan melaporkan kesilapan kerana redeclaring var
: Jika anda ingin menangkap kesilapan tersebut, anda lebih baik menggunakan Linter seperti JSHINT atau JSLINT untuk mengendalikan kod anda. Sekarang mari kita lihat contoh lain untuk menyerlahkan satu lagi kegunaan rawan kesilapan yang berubah-ubah:
function myFunction() { console.log(i); var i = 0; console.log(i); if (true) { var i = 5; console.log(i); } console.log(i); }
Walaupun anda mungkin mengharapkan secara berbeza, badan if
dilaksanakan kerana salinan tempatan pembolehubah yang dinamakan test()
diisytiharkan di dalam fungsi notNull
, dan ia dipromosikan oleh . Jenis kerja mandatori di sini juga.
ekspresi fungsi (mereka sebenarnya pembolehubah) dan pengisytiharan fungsi juga akan dipromosikan. Topik ini perlu ditangani dengan lebih berhati -hati daripada yang saya lakukan di sini, tetapi ringkasnya, pengisytiharan fungsi berkelakuan kira -kira sama dengan ekspresi fungsi, kecuali pengisytiharan mereka dipindahkan ke permulaan skop mereka. Pertimbangkan contoh berikut yang menunjukkan tingkah laku pengisytiharan fungsi:
<code>undefined 0 5 5</code>
var notNull = 1; function test() { if (!notNull) { console.log("Null-ish, so far", notNull); for(var notNull = 10; notNull < 20; notNull++) { //.. } console.log("Now it's not null", notNull); } console.log(notNull); }
dengan
function foo() { // 函数声明 function bar() { return 3; } return bar(); // 此函数声明将被提升并覆盖之前的声明 function bar() { return 8; } }
mempunyai medan bernama y
, fungsi x
akan kembali foo()
, jika tidak, 123 akan dikembalikan. Amalan pengekodan ini mungkin menjadi sumber kesilapan runtime, jadi sangat disyorkan agar anda mengelakkan pernyataan y.x
. with
. Pertimbangkan kod berikut: let
function foo() { // 函数表达式 var bar = function() { return 3; }; return bar(); // 变量 bar 已经存在,并且永远不会到达此代码 var bar = function() { return 8; }; }
di dalam badan if
mengisytiharkan untuk membuat pembolehubah baru tempatan ke blok let
. Sebagai alternatif yang tidak standard, blok i
boleh diisytiharkan seperti berikut: if
let
function foo(y) { var x = 123; with(y) { return x; } }
hanya wujud dalam blok. Pada masa penulisan, sokongan untuk i
adalah terhad, walaupun untuk Chrome. j
let
Ringkasan Skop
特性 | Java | Python | JavaScript | 警告 |
---|---|---|---|---|
作用域 | 词法(块) | 词法(函数、类或模块) | 是 | 它与 Java 或 C 的工作方式大相径庭 |
块作用域 | 是 | 否 | let 关键字(ES6) |
再一次警告:这不是 Java! |
提升 | 不可能! | 否 | 是 | 仅提升变量和函数表达式的声明。对于函数声明,也会提升定义 |
函数 | 作为内置类型 | 是 | 是 | 回调/命令模式对象(或 Java 8 的 lambda) |
动态创建 | 否 | 否 | eval – Function 对象 |
eval 存在安全问题,Function 对象可能无法按预期工作 |
属性 | 否 | 否 | 可以具有属性 | 无法限制对函数属性的访问 |
闭包 | 弱化,只读,在匿名内部类中 | 弱化,只读,在嵌套的 def 中 | 是 | 内存泄漏 |
Fungsi
Satu lagi ciri yang sangat disalahpahami oleh JavaScript ialah fungsi, terutamanya dalam bahasa pengaturcaraan yang penting seperti Java, tidak ada konsep fungsi. Malah, JavaScript adalah bahasa pengaturcaraan berfungsi. Nah, ia bukan bahasa pengaturcaraan fungsional yang murni seperti Haskell - ia masih mempunyai gaya yang penting selepas semua, dan menggalakkan mutabiliti dan bukan hanya membenarkan, seperti Scala. Walau bagaimanapun, JavaScript boleh digunakan sebagai bahasa pengaturcaraan yang semata -mata berfungsi, dengan panggilan fungsi tanpa sebarang kesan sampingan.
Fungsi dalam JavaScript boleh dirawat seperti mana -mana jenis lain, seperti rentetan dan nombor: mereka boleh disimpan dalam pembolehubah, diluluskan sebagai parameter ke fungsi, dikembalikan oleh fungsi, dan disimpan dalam array. Fungsi juga boleh mempunyai sifat dan boleh diubah secara dinamik, kerana ...
Fakta yang sangat mengejutkan untuk kebanyakan pemula JavaScript ialah fungsi sebenarnya objek. Dalam JavaScript, setiap fungsi sebenarnya merupakan objek fungsi. Fungsi Pembina Membuat Objek Fungsi Baru:
table.sp_table { width: 100%; border-collapse: collapse; border-spacing: 0; } table.sp_table td, table.sp_table th { border: solid 1px #ccc; padding: 10px; line-height: 1.5; text-align: center; width: 20%; } table.sp_table tr td:first-child { font-weight: bold; }
Ini hampir sama dengan:
function myFunction() { console.log(i); var i = 0; console.log(i); if (true) { var i = 5; console.log(i); } console.log(i); }
Saya katakan mereka hampir setara kerana menggunakan pembina fungsi kurang efisien, menghasilkan fungsi tanpa nama dan tidak mewujudkan penutupan untuk konteks penciptaan mereka. Objek fungsi sentiasa dibuat dalam skop global. Fungsi (jenis fungsi) dibina di atas objek. Ini dapat dilihat dengan mudah dengan memeriksa sebarang fungsi yang anda nyatakan:
<code>undefined 0 5 5</code>
Ini bermakna fungsi itu boleh dan mempunyai sifat. Sesetengahnya ditugaskan untuk berfungsi pada masa penciptaan, seperti nama atau panjang. Ciri -ciri ini mengembalikan nama dan bilangan parameter dalam definisi fungsi masing -masing. Pertimbangkan contoh berikut:
var notNull = 1; function test() { if (!notNull) { console.log("Null-ish, so far", notNull); for(var notNull = 10; notNull < 20; notNull++) { //.. } console.log("Now it's not null", notNull); } console.log(notNull); }
tetapi anda juga boleh menetapkan sifat baru untuk sebarang fungsi sendiri:
function foo() { // 函数声明 function bar() { return 3; } return bar(); // 此函数声明将被提升并覆盖之前的声明 function bar() { return 8; } }
Jadual berikut menerangkan fungsi dalam Java, Python, dan JavaScript:
特性 | Java | Python | JavaScript | 警告 |
---|---|---|---|---|
函数作为内置类型 | lambda,Java 8 | 是 | 是 | 回调/命令模式对象(或 Java 8 的 lambda) |
动态创建 | 否 | 否 | eval – Function 对象 |
eval 存在安全问题,Function 对象可能无法按预期工作 |
属性 | 否 | 否 | 可以具有属性 | 无法限制对函数属性的访问 |
Penutup
Jika saya diminta memilih ciri JavaScript kegemaran saya, saya akan memilih penutupan tanpa ragu -ragu. JavaScript adalah bahasa pengaturcaraan arus perdana pertama untuk memperkenalkan penutupan. Seperti yang anda ketahui, Java dan Python telah lama melemahkan versi penutupan dari mana anda hanya boleh membaca (beberapa) nilai skop tertutup. Sebagai contoh, di Java, kelas dalaman tanpa nama menyediakan fungsi seperti penutupan dengan batasan tertentu. Sebagai contoh, pembolehubah tempatan akhir hanya boleh digunakan dalam skop mereka -lebih tepatnya, nilai mereka boleh dibaca. JavaScript membolehkan akses penuh ke pembolehubah dan fungsi luaran luaran. Mereka boleh dibaca, ditulis, dan juga tersembunyi oleh definisi tempatan jika diperlukan: Anda dapat melihat contoh semua kes ini dalam bahagian skop. Apa yang lebih menarik ialah fungsi yang dibuat dalam penutupan mengingati persekitaran di mana ia dicipta. Dengan menggabungkan penutupan dan bersarang fungsi, anda boleh mempunyai fungsi luaran mengembalikan fungsi dalaman tanpa melaksanakannya. Di samping itu, anda boleh membuat pembolehubah tempatan fungsi luaran bertahan lama dalam penutupan fungsi dalaman mereka, walaupun pelaksanaan fungsi yang mengisytiharkan mereka telah berakhir. Ini adalah ciri yang sangat kuat, tetapi ia juga mempunyai kelemahannya, kerana ia merupakan punca kebocoran memori dalam aplikasi JavaScript. Beberapa contoh akan menggambarkan konsep -konsep ini:
table.sp_table { width: 100%; border-collapse: collapse; border-spacing: 0; } table.sp_table td, table.sp_table th { border: solid 1px #ccc; padding: 10px; line-height: 1.5; text-align: center; width: 20%; } table.sp_table tr td:first-child { font-weight: bold; }
fungsi di atas makeCounter()
membuat dan mengembalikan fungsi lain yang menjejaki persekitaran yang dibuatnya. Walaupun pelaksanaan counter
selesai apabila pembolehubah makeCounter()
diperuntukkan, pembolehubah tempatan i
kekal dalam penutupan displayCounter
dan oleh itu boleh diakses di dalam badannya. Sekiranya kita mahu menjalankan makeCounter
sekali lagi, ia akan mewujudkan penutupan baru di mana entri untuk i
berbeza:
function myFunction() { console.log(i); var i = 0; console.log(i); if (true) { var i = 5; console.log(i); } console.log(i); }
untuk menjadikannya lebih menarik, kita boleh mengemas kini fungsi makeCounter()
untuk menerima parameter:
<code>undefined 0 5 5</code>
Parameter fungsi luaran juga disimpan dalam penutupan, jadi kami tidak perlu mengisytiharkan pembolehubah tempatan kali ini. Setiap panggilan makeCounter()
akan ingat nilai awal yang kami tetapkan dan terus mengira. Penutupan adalah penting untuk banyak corak JavaScript asas: ruang nama, modul, pembolehubah peribadi, ingatan hanya yang paling terkenal. Sebagai contoh, mari kita lihat bagaimana mensimulasikan pembolehubah peribadi untuk objek:
var notNull = 1; function test() { if (!notNull) { console.log("Null-ish, so far", notNull); for(var notNull = 10; notNull < 20; notNull++) { //.. } console.log("Now it's not null", notNull); } console.log(notNull); }
Menggunakan corak ini, menggunakan penutupan, kita boleh membuat pembalut untuk nama harta dan menggunakan setter dan getter kami sendiri. ES5 menjadikan ini lebih mudah kerana anda boleh membuat objek untuk sifat mereka menggunakan getters dan setters dan mengendalikan akses kepada sifat -sifat itu sendiri di bijirin terbaik.
Jadual berikut menerangkan penutupan di Java, Python, dan JavaScript:
特性 | Java | Python | JavaScript | 警告 |
---|---|---|---|---|
闭包 | 弱化,只读,在匿名内部类中 | 弱化,只读,在嵌套的 def 中 | 是 | 内存泄漏 |
记忆化模式 | 必须使用共享对象 | 可以使用列表或字典 | 是 | 最好使用惰性求值 |
命名空间/模块模式 | 不需要 | 不需要 | 是 | |
私有属性模式 | 不需要 | 不可能 | 是 | 可能令人困惑 |
Kesimpulan
Dalam artikel ini, saya memperkenalkan tiga ciri JavaScript yang sering disalahpahami oleh pemaju dari pelbagai bahasa, terutama Java dan C. Khususnya, kita membincangkan konsep seperti skop, promosi, fungsi dan penutupan. Jika anda ingin menggali topik ini, berikut adalah senarai beberapa artikel yang boleh anda baca: - Skop dalam JavaScript - Pengisytiharan Fungsi dan Ekspresi Fungsi - let
Penyataan dan
di JavaScript, "==" dan "===" adalah pengendali perbandingan, tetapi mereka bekerja dengan cara yang berbeza. Operator "==" dipanggil pengendali kesamaan longgar. Ia membandingkan sama ada kedua -dua nilai adalah sama selepas melakukan apa -apa penukaran jenis yang diperlukan. Ini bermakna jika anda membandingkan nombor dengan rentetan dengan literal angka, ia akan kembali benar. Sebagai contoh, "5" == 5 akan kembali benar. Sebaliknya, "===" adalah pengendali kesamaan yang ketat. Ia tidak melakukan penukaran jenis, jadi jika kedua -dua jenis nilai berbeza, ia akan kembali palsu. Sebagai contoh, "5" === 5 akan kembali palsu kerana satu adalah rentetan dan yang lain adalah nombor.
Dalam JavaScript, Null dan Undefined adalah nilai khas yang tidak wujud. Walau bagaimanapun, mereka digunakan sedikit berbeza. Tidak jelas bermakna pembolehubah telah diisytiharkan tetapi belum ditugaskan lagi. Null, sebaliknya, adalah nilai tugasan, menunjukkan tiada nilai atau tiada objek. Ia menunjukkan bahawa nilai pembolehubah tidak wujud, sementara tidak jelas bermakna pembolehubah itu sendiri tidak wujud.
ketinggian adalah mekanisme dalam JavaScript yang menggerakkan pembolehubah dan pengisytiharan fungsi ke bahagian atas skop yang disertakan semasa fasa kompilasi. Ini bermakna anda boleh menggunakan pembolehubah dan fungsi sebelum mengisytiharkannya. Walau bagaimanapun, perlu diperhatikan bahawa hanya pengisytiharan akan dipromosikan, dan permulaan tidak akan dipromosikan. Jika pembolehubah diisytiharkan dan diisytiharkan selepas menggunakannya, nilai tidak akan ditentukan.
Dalam JavaScript, pembolehubah boleh menjadi pembolehubah global atau tempatan. Pembolehubah global adalah pembolehubah yang diisytiharkan di luar sebarang fungsi, atau pembolehubah yang diisytiharkan dengan kata kunci "VAR" sama sekali. Ia boleh diakses dari sebarang fungsi dalam skrip. Pembolehubah tempatan, sebaliknya, adalah pembolehubah yang diisytiharkan dalam fungsi menggunakan kata kunci "VAR". Ia hanya boleh diakses dalam fungsi yang diisytiharkan.
Kata kunci "ini" dalam JavaScript adalah kata kunci khas, yang merujuk kepada konteks memanggil fungsi. Nilainya bergantung pada bagaimana fungsi dipanggil. Dalam satu kaedah, "ini" merujuk kepada objek pemilik. Individu, "ini" merujuk kepada objek global. Dalam fungsi, "ini" merujuk kepada objek global. Dalam satu acara, "ini" merujuk kepada elemen yang menerima acara tersebut.
Penutupan dalam JavaScript adalah fungsi yang boleh mengakses skopnya sendiri, skop dan skop global fungsi luaran, serta parameter fungsi akses dan pembolehubah. Ini membolehkan fungsi untuk mengakses pembolehubah dalam fungsi luaran yang dikembalikan, mengekalkan pembolehubah dalam ingatan, dan membolehkan kilang privasi dan fungsi data.
Dalam JavaScript, fungsi boleh ditakrifkan dalam banyak cara, dua daripadanya adalah pengisytiharan fungsi dan ekspresi fungsi. Pengisytiharan fungsi mentakrifkan fungsi yang dinamakan, dan perisytiharan dipromosikan, yang membolehkan fungsi digunakan sebelum mendefinisikannya. Ekspresi fungsi mentakrifkan fungsi dalam ungkapan dan tidak dipromosikan, bermakna ia tidak boleh digunakan sebelum definisi.
"biarkan", "var" dan "const" semuanya digunakan untuk mengisytiharkan pembolehubah dalam JavaScript, tetapi mereka mempunyai peraturan skop yang berbeza. "var" berfungsi scoped, bermakna ia hanya boleh digunakan dalam fungsi yang diisytiharkan. "Biarkan" dan "const" adalah blok-scoped, bermakna mereka hanya boleh digunakan dalam blok yang mereka nyatakan. Perbezaan antara "biarkan" dan "const" ialah "biarkan" membolehkan anda menetapkan semula pembolehubah, sementara "const" tidak.
Dalam JavaScript, objek dan tatasusunan digunakan untuk menyimpan data, tetapi ia disimpan dengan cara yang berbeza. Objek adalah koleksi sifat, di mana setiap harta adalah pasangan nilai utama. Kunci adalah rentetan dan nilai boleh menjadi jenis data. Arahan adalah jenis objek khas yang mewakili senarai item. Kekunci adalah indeks angka, dan nilai boleh menjadi jenis data.
Dalam JavaScript, fungsi adalah blok kod yang direka untuk melaksanakan tugas tertentu, dan ia adalah entiti berasingan yang boleh digunakan seperti yang diperlukan. Sebaliknya, kaedah adalah fungsi yang berkaitan dengan objek, atau dengan kata lain, kaedah adalah sifat objek sebagai fungsi. Kaedah ditakrifkan dengan cara yang sama seperti fungsi biasa, kecuali bahawa mereka mesti diberikan nilai sebagai atribut objek.
Atas ialah kandungan terperinci Tiga JavaScript Queirks yang harus diketahui oleh pemaju Java/C. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!