Dalam artikel ini, kita akan menutup konsep tugasan dan mutasi yang berubah -ubah dan melihat mengapa - bersama -sama - mereka boleh menjadi kesakitan yang nyata bagi pemaju. Kami akan melihat cara menguruskannya untuk mengelakkan masalah, cara menggunakan seberapa sedikit yang mungkin, dan bagaimana untuk memastikan kod anda dapat diramalkan.
Jika anda ingin meneroka topik ini dengan lebih terperinci, atau bangun untuk mempercepatkan dengan JavaScript moden, lihat bab pertama buku baru saya belajar kod dengan JavaScript secara percuma. > mari kita mulakan dengan kembali ke asas -asas jenis nilai ...
Takeaways Key
nombor, seperti 3, 0, -4, 0.625
Tugasan Variabel adalah salah satu perkara pertama yang anda pelajari dalam pengekodan. Sebagai contoh, ini adalah bagaimana kita akan menetapkan nombor 3 kepada beruang pembolehubah:
<span>const bears = 3; </span>
cara pemikiran alternatif tentang apa yang berlaku adalah sebagai rujukan, yang memetakan label beruang kepada nilai 3:
<span>const bears = 3; </span>
pembolehubah beruang dan musketeers kedua -duanya merujuk nilai primitif yang sama 3. Kita boleh mengesahkan ini menggunakan pengendali kesaksamaan yang ketat, ===:
Pengendali kesamaan mengembalikan benar jika kedua -dua pembolehubah merujuk nilai yang sama.
<span>let musketeers = 3; </span>
beberapa gotchas ketika bekerja dengan objek
Tugasan ini bermaksud bahawa Ghostbusters Variable merujuk objek:
bears <span>=== musketeers </span><span><< true </span>
Perbezaan besar apabila memberikan objek kepada pembolehubah, bagaimanapun, adalah bahawa jika anda menetapkan objek lain yang literal kepada pembolehubah lain, ia akan merujuk objek yang sama sekali berbeza - walaupun kedua -dua objek literal kelihatan sama! Sebagai contoh, tugasan di bawah kelihatan seperti pembolehubah TMNT (Teenage Mutant Ninja Turtles) merujuk objek yang sama seperti Ghostbusters Variable:
Walaupun pembolehubah Ghostbusters dan TMNT kelihatan seperti mereka merujuk objek yang sama, mereka sebenarnya merujuk objek yang sama sekali berbeza, seperti yang dapat kita lihat jika kita menyemak dengan pengendali kesamaan yang ketat:
<span>const ghostbusters = { number: 4 }; </span>
<span>let tmnt = { number: 4 }; </span>
Apabila kata kunci Const diperkenalkan di ES6, ramai orang tersilap percaya bahawa pemalar telah diperkenalkan kepada JavaScript, tetapi ini tidak berlaku. Nama kata kunci ini sedikit mengelirukan.
Rujukan kepada nombor 3 ditetapkan dan pemboleh ubah beruang tidak dapat ditugaskan semula nilai lain.
sama berlaku untuk objek. Jika kita cuba memberikan objek yang berbeza kepada Ghostbusters yang berubah -ubah, kita mendapat ralat yang sama:
ghostbusters <span>=== tmnt </span><span><< false </span>
penugasan semula variabel menggunakan LET
Apabila kata kunci LET digunakan untuk mengisytiharkan pembolehubah, ia boleh ditugaskan semula untuk merujuk nilai yang berbeza di kemudian hari dalam kod kami. Sebagai contoh, kami mengisytiharkan musketeer yang berubah -ubah menggunakan LET, jadi kami boleh mengubah nilai yang rujukan Musketeers. Jika D'Artagnan menyertai Musketeers, bilangan mereka akan meningkat kepada 4:
bears <span>= 2; </span><span><< TypeError: Attempted to assign to readonly property. </span>
Ini boleh dilakukan kerana LET digunakan untuk mengisytiharkan pembolehubah. Kita boleh mengubah nilai yang rujukan musketeers seberapa banyak yang kita suka.
pembolehubah TMNT juga diisytiharkan menggunakan LET, jadi ia juga boleh ditugaskan semula untuk merujuk objek lain (atau jenis yang berbeza sepenuhnya jika kita suka):
<span>const bears = 3; </span>
Perhatikan bahawa pembolehubah TMNT kini merujuk kepada objek objek yang sama sekali berbeza ; Kami tidak hanya menukar harta nombor kepada 5.
Ringkasnya, jika anda mengisytiharkan pembolehubah menggunakan Const, nilainya tidak boleh ditugaskan semula dan akan sentiasa merujuk nilai primitif atau objek yang sama yang ditugaskan pada asalnya. Sekiranya anda mengisytiharkan pembolehubah menggunakan LET, nilainya boleh ditugaskan semula sebanyak yang diperlukan kemudian dalam program.menggunakan const sekerap mungkin secara amnya dianggap amalan yang baik, kerana ia bermakna bahawa nilai pembolehubah tetap malar dan kod itu lebih konsisten dan boleh diramal, menjadikannya kurang terdedah kepada kesilapan dan pepijat.
tugasan pembolehubah dengan rujukan
Ini kelihatan seperti Stooges yang berubah -ubah merujuk kepada musketeer yang berubah -ubah, seperti yang ditunjukkan dalam rajah di bawah:
<span>let musketeers = 3; </span>
Ini bermakna jika D'Artagnan menyertai musketeers dan kami menetapkan nilai musketeers kepada 4, nilai stooges akan kekal sebagai 3. Malah, kerana kami mengisytiharkan pembolehubah Stooges menggunakan Const, kami tidak dapat menetapkan ia kepada sebarang nilai baru; ia akan sentiasa 3.
Ringkasnya: Jika anda mengisytiharkan pembolehubah menggunakan Const dan tetapkannya kepada nilai primitif, walaupun melalui rujukan kepada pembolehubah lain, maka nilainya tidak dapat berubah. Ini baik untuk kod anda, kerana ia bermakna ia akan lebih konsisten dan boleh diramal.
Nilai dikatakan
Mutable
jika ia boleh diubah. Itu sahaja yang ada: ASemua nilai primitif dalam JavaScript adalah tidak berubah : Anda tidak boleh mengubah sifat mereka - pernah. Sebagai contoh, jika kita menetapkan "kek" rentetan kepada makanan yang berubah -ubah, kita dapat melihat bahawa kita tidak boleh mengubah mana -mana sifatnya:
<span>const bears = 3; </span>
Jika kita cuba menukar huruf pertama kepada "f", nampaknya ia telah berubah:
<span>let musketeers = 3; </span>
Tetapi jika kita melihat nilai pembolehubah, kita melihat bahawa tiada apa yang sebenarnya berubah:
bears <span>=== musketeers </span><span><< true </span>
Perkara yang sama berlaku jika kita cuba menukar harta panjang:
<span>const ghostbusters = { number: 4 }; </span>
Walaupun nilai pulangan menyiratkan bahawa harta panjang telah diubah, pemeriksaan cepat menunjukkan bahawa ia tidak:
<span>let tmnt = { number: 4 }; </span>
Perhatikan bahawa ini tidak ada kaitan dengan mengisytiharkan pembolehubah menggunakan const dan bukannya. Sekiranya kami menggunakan LET, kami boleh menetapkan makanan untuk merujuk rentetan lain, tetapi kami tidak dapat mengubah mana -mana sifatnya. Tidak mustahil untuk mengubah sifat -sifat jenis data primitif kerana mereka tidak berubah .
Sebaliknya, semua objek dalam JavaScript boleh berubah, yang bermaksud bahawa sifat mereka boleh diubah, walaupun mereka diisytiharkan menggunakan const (ingat biarkan dan const hanya mengawal sama ada atau tidak pembolehubah boleh ditugaskan semula dan tidak ada kaitan mutabiliti). Sebagai contoh, kita boleh menukar item pertama array menggunakan kod berikut:
ghostbusters <span>=== tmnt </span><span><< false </span>
Perhatikan bahawa perubahan ini masih berlaku, walaupun pada hakikatnya kami mengisytiharkan makanan yang berubah -ubah menggunakan Const. Ini menunjukkan bahawa menggunakan const tidak menghentikan objek daripada bermutasi .
kita juga boleh menukar harta panjang array, walaupun ia telah diisytiharkan menggunakan const:
bears <span>= 2; </span><span><< TypeError: Attempted to assign to readonly property. </span>
ingat bahawa apabila kita menetapkan pembolehubah untuk membantah literals, pembolehubah akan merujuk objek yang sama sekali berbeza, walaupun mereka kelihatan sama:
ghostbusters <span>= {number: 5}; </span><span>TypeError: Attempted to assign to readonly property. </span>
sama :
musketeers <span>= 4; </span>
objek yang sama bahawa rujukan TMNT yang berubah -ubah, bukannya objek yang sama sekali berbeza.
Ini sering dirujuk sebagai penyalinan dengan rujukan, kerana kedua -dua pembolehubah ditugaskan untuk merujuk objek
. Ini penting, kerana sebarang mutasi yang dibuat untuk objek ini akan dilihat dalam
kedua -duapembolehubah. Jadi, jika Spider-Man menyertai Fantastic Four, kami mungkin mengemas kini nilai nombor dalam objek:
Ini adalah mutasi, kerana kami telah menukar harta nombor dan bukannya menetapkan Fantastic4 untuk merujuk objek baru.
tmnt <span>= {number: 5}; </span>
Ini menyebabkan kita menjadi masalah, kerana harta bilangan TMNT juga akan berubah, mungkin tanpa kita menyedari:
<span>const bears = 3; </span>
Ini kerana kedua -dua TMNT dan Fantastic4 merujuk objek yang sama, jadi sebarang mutasi yang dibuat sama ada TMNT atau Fantastic4 akan menjejaskan kedua -dua mereka.
Ini menyoroti konsep penting dalam JavaScript: Apabila objek disalin dengan rujukan dan kemudiannya bermutasi, mutasi akan menjejaskan mana -mana pembolehubah lain yang merujuk objek itu. Ini boleh membawa kepada kesan sampingan yang tidak diingini dan pepijat yang sukar untuk dijejaki.
Jadi bagaimana anda membuat salinan objek tanpa membuat rujukan kepada objek asal? Jawapannya ialah menggunakan pengendali penyebaran!
Pengendali penyebaran diperkenalkan untuk tatasusunan dan rentetan dalam ES2015 dan untuk objek di ES2018. Ia membolehkan anda dengan mudah membuat salinan cetek objek tanpa membuat rujukan kepada objek asal.
Contoh di bawah menunjukkan bagaimana kami dapat menetapkan Variable Fantastic4 untuk merujuk salinan objek TMNT. Salinan ini akan sama seperti objek TMNT, tetapi Fantastic4 akan merujuk objek yang baru. Ini dilakukan dengan meletakkan nama pembolehubah untuk disalin di dalam objek literal dengan pengendali penyebaran di hadapannya:
<span>let musketeers = 3; </span>
Apa yang telah kita lakukan di sini adalah menetapkan Variable Fantastic4 kepada objek baru literal dan kemudian menggunakan pengendali penyebaran untuk menyalin semua sifat yang boleh dibaca objek yang dirujuk oleh pembolehubah TMNT. Kerana sifat -sifat ini adalah nilai, mereka disalin ke objek Fantastic4 dengan nilai, dan bukannya dengan rujukan.
bears <span>=== musketeers </span><span><< true </span>
Pengendali penyebaran juga mempunyai notasi pintasan yang berguna yang boleh digunakan untuk membuat salinan objek dan kemudian membuat beberapa perubahan pada objek baru dalam satu baris kod.
Penyu lain semua mempunyai sifat yang sama, kecuali sifat senjata dan warna, yang berbeza untuk setiap penyu. Adalah masuk akal untuk membuat salinan objek yang rujukan Leonardo, menggunakan pengendali penyebaran, dan kemudian menukar sifat senjata dan warna, seperti:
<span>const ghostbusters = { number: 4 }; </span>
kita boleh melakukan ini dalam satu baris dengan menambahkan sifat yang kita mahu ubah selepas rujukan kepada objek penyebaran. Inilah kod untuk membuat objek baru untuk pembolehubah Donatello dan Raphael:
<span>const bears = 3; </span>
Perhatikan bahawa menggunakan pengendali penyebaran dengan cara ini hanya membuat salinan cetek objek. Untuk membuat salinan yang mendalam, anda perlu melakukan ini secara rekursif, atau menggunakan perpustakaan. Secara peribadi, saya akan menasihatkan bahawa anda cuba mengekalkan objek anda sebagai cetek.
Dalam artikel ini, kami telah meliputi konsep -konsep tugasan dan mutasi yang berubah -ubah dan melihat mengapa - bersama -sama - mereka boleh menjadi kesakitan yang nyata bagi pemaju.
Mutasi mempunyai reputasi yang buruk, tetapi mereka tidak semestinya buruk dalam diri mereka sendiri. Malah, jika anda membina aplikasi web yang dinamik, ia mesti berubah pada satu ketika. Itulah makna perkataan "dinamik"! Ini bermakna perlu ada beberapa mutasi di suatu tempat di kod anda. Setelah mengatakan bahawa, mutasi yang lebih sedikit ada, lebih banyak yang dapat diramalkan kod anda akan menjadi, menjadikannya lebih mudah untuk mengekalkan dan kurang berkemungkinan untuk mengembangkan sebarang pepijat.
Gabungan toksik terutamanya menyalin dengan rujukan dan mutasi. Ini boleh menyebabkan kesan sampingan dan pepijat yang anda tidak sedar telah berlaku. Jika anda bermutasi objek yang dirujuk oleh pembolehubah lain dalam kod anda, ia boleh menyebabkan banyak masalah yang boleh menjadi sukar untuk dijejaki. Kuncinya adalah untuk mencuba dan meminimumkan penggunaan mutasi anda kepada yang penting dan menjejaki objek yang telah bermutasi.
Dalam pengaturcaraan berfungsi, fungsi tulen adalah salah satu yang tidak menyebabkan sebarang kesan sampingan, dan mutasi adalah salah satu penyebab utama kesan sampingan.
Peraturan emas adalah untuk mengelakkan menyalin sebarang objek dengan rujukan. Jika anda ingin menyalin objek lain, gunakan pengendali penyebaran dan kemudian buat sebarang mutasi dengan segera selepas membuat salinan.
Seterusnya, kami akan melihat mutasi array dalam JavaScript.
Jangan lupa untuk menyemak buku baru saya belajar kod dengan JavaScript jika anda ingin bangun untuk mempercepatkan dengan JavaScript moden. Anda boleh membaca bab pertama secara percuma. Dan sila hubungi di Twitter jika anda mempunyai sebarang pertanyaan atau komen!
Dalam JavaScript, Var, LeT, dan const digunakan untuk mengisytiharkan pembolehubah. var berfungsi scoped, dan jika ia diisytiharkan di luar fungsi, ia secara global scoped. Let dan const blok scoped, bermakna mereka hanya wujud di dalam blok mereka diisytiharkan masuk. Perbezaan antara LET dan const adalah yang membolehkan pembentukan semula, sementara const tidak. Dalam konteks pengaturcaraan asynchronous?
Atas ialah kandungan terperinci Panduan untuk Tugasan dan Mutasi Variabel dalam JavaScript. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!