Terbuat dari apakah JavaScript?

Selama beberapa tahun pertama menggunakan JavaScript, saya merasa seperti penipu. Meskipun saya bisa membuat situs web menggunakan kerangka kerja, saya merasa bahwa saya kehilangan sesuatu. Wawancara JavaScript menginspirasi saya ketakutan karena saya tidak memiliki pemahaman yang jelas tentang dasar-dasar bahasa ini.



Selama bertahun-tahun, saya telah membangun model JavaScript mental yang memberi saya rasa percaya diri. Di sini saya akan membagikan kepada Anda versi yang sangat ringkas dari model ini. Strukturnya menyerupai kamus. Setiap konsep dijelaskan dalam beberapa kalimat.

Ketika Anda membaca materi ini, cobalah untuk mengevaluasi secara mental seberapa besar perasaan Anda terhadap setiap masalah yang dibahas di sini. Dan jika ternyata banyak hal dari sini yang menurut Anda tidak terlalu familiar, saya tidak akan menyalahkan Anda untuk itu. Tetapi jika ini benar, ada sesuatu di akhir materi yang akan membantu Anda memperbaiki situasi.

Model mental JavaScript


  • Nilai. Konsep makna agak abstrak. Itu adalah "sesuatu." Nilai dalam JavaScript sama dengan angka dalam matematika, atau titik dalam geometri. Ketika program Anda berjalan, dunia program ini penuh dengan makna. Angka seperti 1 , 2 dan 420 adalah nilai. Tetapi artinya adalah entitas lain. Misalnya, kalimat "Cows go moo" . Benar, tidak semuanya berarti. Angka adalah nilai, tetapi if tidak lagi berupa nilai. Di bawah ini kita akan berbicara tentang berbagai jenis nilai.

    • Jenis nilai. Ada berbagai "tipe" nilai. Misalnya, angka - seperti 420 , string - seperti "Cows go moo" , objek. Ada beberapa tipe nilai lainnya. Anda dapat mengetahui tipe nilai menggunakan typeof operator. Sebagai contoh, command console.log(typeof 2) akan menampilkan number ke konsol.
    • Nilai-nilai primitif. Beberapa nilai memiliki tipe "primitif". Ini adalah angka, string, dan beberapa makna lainnya. Salah satu properti menarik dari nilai primitif adalah bahwa Anda tidak dapat membuat nilai lebih dari yang ada dalam bahasa, Anda tidak dapat mengubah nilai primitif yang ada. Misalnya, setiap kali Anda menggunakan angka 2 dalam kode, itu akan bernilai sama 2 . Tidak mungkin untuk "membuat" satu lagi nilai 2 dalam program, atau untuk membuat 2 "berubah" menjadi 3 . Ini juga berlaku untuk string.
    • Nilai-nilai itu null dan undefined . Ini adalah dua arti khusus. Mereka tidak seperti orang lain, karena kenyataan bahwa banyak hal tidak dapat dilakukan dengan mereka - penampilan mereka sering mengarah pada kesalahan. Biasanya, menggunakan null adalah indikasi bahwa beberapa nilai tidak ditugaskan ke suatu variabel secara sengaja, dan undefined menunjukkan bahwa beberapa nilai hilang secara kebetulan. Namun, programmer memutuskan bagaimana menggunakan nilai-nilai ini dengan tepat. Nilai-nilai ini ada karena fakta bahwa kadang-kadang lebih baik kesalahan terjadi selama pelaksanaan operasi tertentu, dan itu tidak akan terjadi bahwa program akan melanjutkan setelah "pemrosesan" dari nilai yang tidak ada.
  • Kesetaraan Seperti konsep makna, konsep kesetaraan adalah salah satu konsep dasar JavaScript. Kami mengatakan bahwa dua nilai sama jika mereka ... pada kenyataannya, saya tidak akan mengatakan itu. Jika dua nilai sama, maka ini berarti mereka satu dan bernilai sama. Bukan dua makna yang berbeda, tetapi satu! Misalnya, persamaan "Cows go moo" === "Cows go moo" dan 2 === 2 benar. Dan di sini semuanya jelas: 2 adalah 2 . Harap perhatikan bahwa kami menggunakan tiga tanda yang sama, yang mewakili konsep persamaan nilai di atas dalam JavaScript.

    • Kesetaraan yang ketat. Kami baru saja membicarakannya di paragraf sebelumnya.
    • Kesetaraan tautan. Dan kami juga membicarakannya.
    • Kesetaraan tidak merata. Oh, tapi ini sesuatu yang sangat berbeda. Dalam JavaScript, memeriksa kesetaraan nilai yang tidak ketat dilakukan menggunakan operator yang terdiri dari dua tanda sama dengan ( == ). Entitas dapat dikenali secara longgar setara satu sama lain walaupun mereka diwakili oleh makna yang berbeda yang terlihat mirip satu sama lain (sesuatu seperti 2 dan "2" ). Operator kesetaraan yang tidak ketat ditambahkan ke JavaScript pada tahap awal pengembangan bahasa, untuk kenyamanan. Sejak itu, itu telah menjadi sumber kebingungan yang tak berdasar. Konsep kesetaraan longgar tidak bisa disebut fundamental, tetapi merupakan sumber kesalahan yang khas. Anda dapat mempelajari operator kesetaraan tidak ketat pada suatu hari hujan, tetapi banyak yang mencoba untuk tidak menggunakan operator == .
  • Secara harfiah. Literal digunakan ketika nilai direferensikan dengan menulisnya ke kode program. Misalnya, 2 adalah literal numerik, dan "Banana" adalah string literal.
  • Variabel. Variabel memungkinkan Anda untuk merujuk nilai menggunakan nama. Sebagai contoh, let message = "Cows go moo" . Setelah konstruksi yang sama digunakan dalam kode, di mana pun Anda membutuhkan kalimat "Cows go moo" , Anda dapat menulis message saja, daripada mengulangi kalimat ini. Kemudian, Anda dapat mengubah message dengan membuat titik variabel ke sesuatu yang lain. Misalnya, menggunakan konstruksi ini: message = "I am the walrus" . Harap dicatat bahwa ini tidak mengubah artinya sendiri. Ini hanya memengaruhi variabel yang dirujuk. Itu seperti "menghubungkan" nama variabel ke sesuatu yang lain. Pada awalnya variabel itu "terhubung" ke "Cows go moo" , dan sekarang ke "I am the walrus" .

    • Ruang lingkup variabel. Jika hanya satu variabel dengan message nama yang dapat digunakan di seluruh program, ini akan sangat buruk. Ketika kami mendeklarasikan variabel, itu hanya tersedia di beberapa bagian dari program. Bagian ini disebut "ruang lingkup variabel." Ada aturan yang menggambarkan fitur ruang lingkup. Anda biasanya dapat mengidentifikasi ruang lingkup variabel dengan mencari tahu di mana blok dibatasi oleh kurung kurawal ( {} ) itu dinyatakan. Blok ini juga bisa disebut ruang lingkup variabel.
    • Menetapkan nilai ke variabel. Ketika kita menulis message = "I am the walrus" dalam kode, ini mengarah pada fakta bahwa kita mengubah variabel message sehingga menunjuk ke nilai "I am the walrus" . Operasi ini disebut menugaskan suatu variabel ke suatu nilai, atau menulis sesuatu ke suatu variabel, atau mengatur suatu variabel.
    • Kata kunci let , const , dan var . Biasanya, let adalah kata kunci terbaik untuk mendeklarasikan variabel. Jika Anda ingin memastikan bahwa tidak ada yang baru yang dapat ditulis ke dalam variabel, Anda dapat menggunakan kata kunci const . (Dalam beberapa basis kode dan perintah, masalah ini pedantic, memaksa semua orang, jika nilainya ditulis ke variabel hanya sekali, gunakan const .) Cobalah untuk tidak menggunakan kata kunci var , karena dengan variabel yang dideklarasikan dengannya, aturan terkait terkait dengan definisi ruang lingkup variabel.
  • Ketik Object . Jenis Object , entitas yang dimiliki objek disebut, memainkan peran khusus dalam JavaScript. Fitur penting dari objek adalah bahwa mereka dapat dikaitkan dengan nilai-nilai lain. Misalnya, objek {flavor: "vanilla"} memiliki properti flavor yang menunjuk ke nilai "vanilla" . Objek dapat dianggap sebagai nilai independen, dari mana tautan ke nilai lain diambil.

    • Milik benda. Properti adalah sesuatu seperti "koneksi" yang berasal dari suatu objek dan menunjukkan nilai tertentu. Ini mungkin mengingatkan Anda tentang ide variabel: properti memiliki nama (seperti flavor ), itu menunjuk ke nilai (seperti "vanilla" ). Tetapi, tidak seperti variabel, properti β€œhidup” di dalam objek itu sendiri, dan bukan di suatu tempat dalam kode (dalam lingkup tertentu dari variabel). Properti dianggap sebagai bagian dari objek, dan nilai yang dirujuk oleh properti tidak dianggap sebagai bagian dari objek.
    • Objek literal. Objek literal adalah mekanisme yang memungkinkan Anda untuk membuat objek dengan memperkenalkan konstruksi yang sesuai ke dalam kode. Misalnya, ini {} atau {flavor: "vanilla"} . Dalam kurung keriting, banyak pasangan : form : , dipisahkan dengan koma, dapat dideklarasikan. Ini memungkinkan kita untuk menentukan nilai yang dirujuk oleh properti dari objek.
    • Identitas objek. Kita telah mengatakan bahwa 2 sama dengan 2 (dengan kata lain - 2 === 2 ), karena di mana pun kita menulis angka 2 , kita β€œmemanggil” nilai yang sama ke tempat ini. Tetapi setiap kali kita menulis {} , kita selalu mendapatkan nilai yang berbeda. Akibatnya, satu objek dari bentuk {} tidak sama dengan objek lain, yang juga terlihat seperti {} . Coba tulis berikut ini di konsol: {} === {} (hasilnya akan false ). Ketika komputer menemukan nomor 2 dalam kode, ia selalu bekerja dengan deuce yang sama. Tetapi objek literal adalah sesuatu yang lain. Ketika komputer bertemu {} , itu menciptakan objek baru, yang selalu merupakan nilai baru. Bagaimana cara memeriksa objek untuk kesetaraan? Konsep "kesetaraan" dapat dianggap sebagai konsep "identitas nilai-nilai." Ketika kita mengatakan: " a dan b identik" - ini berarti bahwa kita berarti bahwa a dan b menunjukkan nilai yang sama (yaitu, a === b ). Ketika kita mengatakan bahwa a dan b tidak identik, ini berarti bahwa a dan b menunjukkan nilai yang berbeda (yaitu, a !== b ).
    • Notasi titik. Saat Anda perlu membaca nilai properti objek atau menulis sesuatu ke properti, Anda bisa menggunakan notasi titik ( . ). Misalnya, jika variabel iceCream menunjuk ke objek yang flavor propertinya berisi string "chocolate" , maka konstruk iceCream.flavor akan memberi kita "chocolate" .
    • Notasi Bracket. Terkadang nama properti objek yang akan diakses tidak diketahui sebelumnya. Misalnya, kadang-kadang Anda perlu membaca nilai properti iceCream.flavor , dan kadang-kadang Anda perlu membaca nilai properti iceCream.flavor . Notasi braket ( [] ) memungkinkan Anda mengakses properti objek dengan mengatur namanya menggunakan variabel. Sebagai contoh, misalkan ada variabel seperti itu dalam kode: let ourProperty = 'flavor' . Ini berarti bahwa desain seperti iceCream[ourProperty] akan memberi kita nilai "chocolate" . Menariknya, Anda dapat menggunakan notasi tanda kurung saat membuat objek: { [ourProperty]: "vanilla" } .
    • Mutasi. Kita berbicara tentang fakta bahwa suatu objek bermutasi (atau berubah) jika seseorang menulis nilai baru ke propertinya. Misalnya, jika kita membuat objek, let iceCream = {flavor: "vanilla"} , nanti kita bisa menetapkan nilai baru ke properti menggunakan iceCream.flavor = "chocolate" . Harap perhatikan bahwa meskipun kami mendeklarasikan variabel iceCream menggunakan kata kunci const , ini tidak akan menghentikan kami untuk mengubah properti objek iceCream.flavor . Ini karena penggunaan const hanya melindungi variabel iceCream dari ditimpa, dan kami mengubah properti flavor objek yang dirujuk oleh variabel. Beberapa orang menolak untuk menggunakan const hanya karena kata kunci ini mampu menyesatkan programmer.
    • Array Array adalah objek yang merupakan kumpulan nilai-nilai tertentu. Array dapat dideklarasikan menggunakan literal array, misalnya, seperti ini: ["banana", "chocolate", "vanilla"] . Menggunakan konstruksi seperti itu mengarah pada penciptaan objek yang propertinya dengan nama 0 menunjuk ke string "banana" , properti 1 - ke string "chocolate" , properti 2 - ke nilai "vanilla" . Akan membosankan untuk menulis hal yang sama seperti ini: {0: ..., 1: ..., 2: ...} . Oleh karena itu, array adalah struktur yang berguna. Array memiliki mekanisme bawaan yang dirancang untuk bekerja dengan elemen-elemennya. Diantaranya adalah map , filter dan metode reduce . Jangan berkecil hati jika reduce nama tampaknya membingungkan Anda. Tampaknya tidak bisa dipahami oleh semua orang.
    • Prototipe. Apa yang terjadi jika Anda mencoba mengakses objek yang tidak ada? Misalnya, apa yang terjadi jika kita mengakses iceCream.taste dan objek hanya memiliki properti flavor ? Jika kita menjawab pertanyaan ini tanpa merinci, kita dapat mengatakan bahwa jika kita mencoba beralih ke properti yang tidak ada, kita mendapatkan nilai khusus yang undefined . Jika Anda memberikan jawaban terperinci untuk pertanyaan ini, maka Anda harus mulai dengan fakta bahwa sebagian besar objek dalam JavaScript memiliki apa yang disebut "prototipe". Prototipe suatu objek dapat dianggap sebagai properti "tersembunyi" yang memberi tahu sistem tempat mencari properti yang diminta jika tidak ada dalam objek itu sendiri. Dalam contoh kita, ketika ternyata objek iceCream tidak memiliki properti taste , JavaScript akan mencari properti ini dalam prototipe objek, yang juga merupakan objek. Dan jika dia tidak menemukannya di sana, maka dalam prototipe prototipe, dan sebagainya. Nilai yang undefined hanya akan .taste ketika akhir rantai prototipe tercapai, dan properti .taste tidak ditemukan. Anda jarang harus bekerja secara langsung dengan mekanisme ini, tetapi mengetahui tentang prototipe, Anda dapat memahami mengapa objek iceCream memiliki metode toString yang tidak pernah kami nyatakan. Metode ini diambil dari prototipe objek.
  • Fungsi Fungsi adalah makna khusus yang ada untuk tujuan tunggal mewakili sepotong kode program. Fungsinya nyaman dalam situasi di mana programmer tidak ingin terus-menerus menulis kode yang sama. "Panggilan" ke fungsi yang terlihat seperti sayHi() memberi tahu komputer bahwa ia perlu mengeksekusi kode di dalam fungsi, dan kemudian kembali ke tempat fungsi dipanggil. JavaScript memiliki banyak cara untuk mendeklarasikan fungsi yang sedikit berbeda.

    • Argumen (atau parameter) fungsi. Argumen memungkinkan Anda untuk melewatkan data tertentu ke fungsi dari tempat di mana fungsi dipanggil. Misalnya, mungkin terlihat seperti ini: sayHi("Amelie") . Perilaku argumen dalam suatu fungsi mirip dengan perilaku variabel. Kata-kata "parameter" dan "argumen" digunakan tergantung pada apa yang sebenarnya dibahas - tentang deklarasi fungsi, atau tentang panggilannya. Meskipun perbedaan dalam terminologi itu akurat - dalam praktiknya, istilah-istilah ini digunakan secara bergantian.
    • Ekspresi fungsional. Sebelumnya kami menulis nilai string ke dalam variabel. Sebagai contoh, let message = "I am the walrus" . Ternyata, suatu fungsi juga dapat ditulis ke dalam variabel: let sayHi = function() { } . Apa yang muncul setelah tanda = disebut ekspresi fungsional. Ini memberi kita makna khusus (fungsi), yang merupakan bagian dari kode. Jika kita perlu menjalankan kode ini, kita dapat memanggil fungsi yang sesuai.
    • Deklarasi fungsi. Seorang programmer mungkin bosan terus menulis sesuatu seperti let sayHi = function() { } . Jika demikian, maka bentuk yang lebih pendek untuk menggambarkan suatu fungsi dapat digunakan di sini: function sayHi() { } . Konstruk ini disebut deklarasi fungsi. Alih-alih menentukan nama variabel di sisi kiri ekspresi, kami menempatkan nama ini setelah kata kunci function . Biasanya, dua gaya untuk membuat fungsi yang dijelaskan di atas dapat dipertukarkan.
    • Meningkatkan fungsi ke bagian atas ruang lingkup. Biasanya variabel hanya dapat digunakan setelah dinyatakan menggunakan let atau const , di bawah tempat deklarasi. Dalam hal fungsi, ini mungkin tidak nyaman. Fungsi dapat saling memanggil. Mencari tahu mana yang harus dibuat pertama bisa menjadi tugas yang menakutkan. Hal yang baik adalah bahwa ketika menggunakan deklarasi fungsi (dan hanya ketika menggunakan pendekatan ini!), Urutan fungsi dijelaskan tidak penting. Faktanya adalah bahwa dengan pendekatan ini, fungsi "naik" ke bagian atas lingkup. Artinya, ternyata fungsinya, bahkan ketika Anda mencoba memanggil mereka dari kode yang ada sebelum deklarasi mereka, sudah ditentukan dan siap untuk bekerja.
    • Kata kunci ini. Mungkin kata kunci this adalah konsep JavaScript yang paling sering disalahpahami. Kata kunci ini dapat dibandingkan dengan argumen fungsi khusus. Tapi kami sendiri tidak mengalihkan fungsinya. JavaScript melewatinya. Nilai this tergantung pada bagaimana fungsi dipanggil. Misalnya, ketika memanggil metode objek menggunakan notasi titik, seperti iceCream.eat() , this akan menunjukkan apa yang ada di depan titik. Dalam contoh kita, ini adalah objek iceCream . Nilai this dalam suatu fungsi tergantung pada bagaimana fungsi dipanggil, dan bukan pada di mana ia dinyatakan. Ada metode khusus, seperti .bind , .call dan .apply , yang memberi programmer kemampuan untuk mengendalikan apa yang masuk ke .apply .
    • Fungsi panah. Fungsi panah menyerupai ekspresi fungsional. Mereka dinyatakan seperti ini: let sayHi = () => { } . Mereka kompak dan sering digunakan untuk desain garis tunggal. Kemampuan fungsi panah lebih terbatas daripada kemampuan fungsi konvensional. Misalnya, mereka tidak memiliki kata kunci this . Ketika kata kunci ini digunakan dalam fungsi panah, kata kunci ini diambil dari fungsi di mana fungsi panah disematkan. Ini mirip dengan memanggil argumen atau variabel dari fungsi yang bersarang di fungsi lain. Dalam praktiknya, ini berarti bahwa fungsi panah digunakan ketika mereka ingin nilai yang sama yang ada dalam kode di sekitarnya terlihat di dalamnya.
    • Mengikat nilai this ke fungsi. Biasanya, mengikat fungsi tertentu f ke nilai spesifik this dan ke set argumen tertentu berarti bahwa fungsi baru dibuat yang memanggil fungsi f dengan nilai yang telah ditentukan ini. JavaScript memiliki mekanisme bantu untuk fungsi-fungsi pengikat - metode .bind , tetapi Anda dapat mengikatnya ke fungsi dengan cara lain. Binding adalah cara populer untuk mendapatkan fungsi bersarang untuk "melihat" nilai yang sama dengan fungsi di luarnya. Sekarang, fungsi panah digunakan dalam situasi yang sama, sebagai akibatnya, pengikatan fungsi jarang digunakan di zaman kita.
    • Tumpukan panggilan Memanggil suatu fungsi seperti memasuki ruangan. Setiap kali kita memanggil fungsi, variabel di dalamnya diinisialisasi lagi. Akibatnya, setiap pemanggilan fungsi adalah seperti membangun "ruang" baru dengan kode fungsi. Ketika "ruang" adalah "dibangun", itu "dimasukkan" ke dalamnya, kode fungsi dijalankan. Variabel dideklarasikan dalam fungsi "hidup" di "ruang" ini. Ketika kembali dari fungsi dilakukan, "ruang" menghilang bersama semua isinya. Semua "kamar" yang dibuat oleh panggilan fungsi ini dapat direpresentasikan sebagai "menara" tinggi. Ini adalah tumpukan panggilan. Ketika kita keluar dari fungsi tertentu, kita sampai ke fungsi, yang terletak "di bawah" itu di tumpukan panggilan.
    • Rekursi. Rekursi adalah saat suatu fungsi memanggil dirinya sendiri. Teknik ini berguna dalam kasus-kasus di mana apa yang telah dilakukan oleh fungsi perlu diulang, tetapi menggunakan argumen lain. Misalnya, jika kami menulis mesin pencari yang mencari situs web, kami mungkin memiliki fungsi collectLinks(url) . Fungsi ini pertama-tama mengumpulkan tautan yang terletak di halaman situs, dan kemudian memanggil dirinya sendiri, melewati masing-masing tautan yang ditemukan.Ini terjadi sampai semua halaman situs dikunjungi. Bahaya rekursi adalah bahwa, secara tidak sengaja, Anda dapat menulis suatu fungsi yang akan memanggil dirinya sendiri tanpa batas. Benar, jika program benar-benar memiliki rekursi yang tak terbatas, ini akan menyebabkan limpahan tumpukan panggilan dan eksekusi program akan berhenti dengan kesalahan stack overflow. Tumpukan meluap karena fakta bahwa terlalu banyak entri tentang fungsi dipanggil jatuh ke dalamnya.
    • . β€” , , . , , β€” . β€” , β€” , , . , .
    • . () β€” , JavaScript. , , . : . . , setTimeout , … -. , . β€” . Β« Β», , .
    • . , , , , . - , . ? - . β€” . . , - . JavaScript, , . «». JavaScript, , , , .


JavaScript , . . JavaScript. , . JavaScript. β€” Just JavaScript . , , JavaScript.

! JavaScript?

Source: https://habr.com/ru/post/id482472/


All Articles