Pencarian cepat untuk sumber mutasi yang tidak diinginkan dari properti objek

Hai Hari ini saya akan memberi tahu Anda cara menggunakan debugger untuk menyelesaikan, menurut saya, masalah JavaScript yang tidak sepele.

Dalam JavaScript, objek adalah tipe data komposit, nilainya dilewatkan dengan referensi. Dengan kata lain, ketika kita mengirimkan objek ke fungsi sebagai parameter, atau di mana saja kita dapat mengubah propertinya. Menggunakan instruksi yang terdiri dari ekspresi variabel yang menyimpan tautan, serta operator titik dan penugasan. Setelah itu, instruksi lain yang berfungsi atau akan bekerja dengan variabel / parameter ini akan menerima perubahan properti dengan referensi.

Seringkali perilaku ini mendistorsi data pengguna, menyebabkan kesalahan dan tidak diinginkan.

Menemukan sumber perubahan properti yang tidak diinginkan seperti itu bisa memakan waktu lama: jadi programnya mungkin sudah besar dan terdiri dari ratusan ribu instruksi.

Mari kita lihat contoh sederhana.

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Debug property mutation example</title> <script> const user = { firstName: 'Vasilij', middleName: 'Alibabaevich', lastName: 'Radner', aka: 'Alibaba', getFullName() { return `${this.lastName} ${this.firstName.slice(0, 1)}. ${this.middleName.slice(0, 1)}.` } }; </script> <script src="object-property-mutation.js" type="application/javascript"></script> </head> </head> <body> <script> Promise.resolve(user).then(user.getFullName.bind(user)).then(console.log); </script> </body> </html> 

Sekarang program web tidak berfungsi, karena ada kesalahan di konsol dan tidak ada output dari nama lengkap.

gambar

Kami membaca pesan paling atas di konsol:

 Uncaught (in promise) TypeError: Cannot read property 'slice' of undefined 

Kesalahan seperti: tidak diproses (sebagai janji): Saya tidak dapat membaca properti slice dari yang tidak ditentukan.

Klik tautan dan pergi ke tempat kesalahan.

 getFullName() { return `${this.lastName} ${this.firstName.slice(0, 1)}. ${this.middleName.slice(0, 1)}.` } 

Kami melihat bahwa ekspresi yang salah
 this.firstName.slice(0, 1) 
terdiri dari empat operator:

  1. operator dua titik
  2. satu pemisah koma
  3. satu operator pengelompokan - sepasang tanda kurung

Mari kita baca instruksinya. Ekspresi kiri dievaluasi terlebih dahulu

 this.firstName 

Ini terdiri dari operator titik, di sebelah kiri ekspresi utama ini, dan pengidentifikasi firstName di sebelah kanan. Hasil dari ungkapan ini tidak akan ditentukan. Menjalankan pernyataan titik berikut ini menyebabkan kesalahan. Karena operator titik hanya bekerja dengan jenis objek, pelaksanaannya dari mengarah tidak terdefinisi ke kesalahan - Saya tidak bisa mendapatkan properti slice dari undefined.

Ternyata di suatu tempat properti ini ditetapkan untuk tidak ditentukan ...

Untuk mengatasi masalah ini, mari kita coba yang sebaliknya. Kami akan menggunakan alat debug untuk menghentikan pengecualian . Pindah dari tempat kesalahan ke tumpukan panggilan, kami mencoba untuk beralih ke instruksi yang mengubah properti.

Pilih alat berhenti pada pengecualian


gambar

Kami melihat bahwa hanya ada dua panggilan di stack. Pergi ke panggilan sebelumnya.

gambar

Kami melihat bahwa tidak ada instruksi eksplisit yang mengubah properti firstName.

gambar

Kami menyimpulkan bahwa perubahan tidak terjadi dalam tumpukan panggilan ini.

Bagaimana kamu suka itu?


Dan bagaimana menemukan penjahat yang mengubah properti objek saya?

Silakan tulis di komentar bagaimana Anda menemukannya?
Orang-orang yang bekerja dengan saya dan kepada siapa saya katakan, silakan tulis tanda bintang di komentar.

Saya sangat tertarik untuk mengetahui bagaimana spesialis JavaScript lainnya menyelesaikan masalah tersebut.

Anda tahu, ketika saya pertama kali menemukan perilaku JavaScript ini, saya menghabiskan beberapa jam untuk menyelidiki dan merobek seikat rambut dari poni saya ...

Nonaktifkan alat jeda pada pengecualian.

Jadi, inilah rencana baru kami, kami akan mendefinisikan properti firstName di objek pengguna menggunakan pengambil dan penyetel.

Kami menambahkan pernyataan debug ke setter menggunakan pernyataan debugger dan pernyataan titik koma.

 const user = { _firstName: 'Vasilij', set firstName(value) { debugger; this._firstName = value; }, get firstName() {return this._firstName}, middleName: 'Alibabaevich', lastName: 'Radner', aka: 'Alibaba', getFullName() { return `${this.lastName} ${this.firstName.slice(0, 1)}. ${this.middleName.slice(0, 1)}.`; } }; 

Bergerak lebih jauh di sepanjang tumpukan panggilan, kami menemukan instruksi yang mengubah properti firstName.

Debugger berhenti di setter sebelum nilai baru ditulis ke objek.

gambar

Kami melihat bahwa nilai nilai parameter tidak terdefinisi.

Sekarang, menggunakan tumpukan panggilan, kita dapat dengan mudah pergi ke panggilan sebelumnya.

gambar

iiiii, kemenangan aaaaaah.

Bahkan ada cara yang lebih sederhana untuk menyelesaikan masalah ini menggunakan alat debugging yang berhenti pada pengecualian .

Ini adalah rencana baru kami: kami akan membuat objek pengguna bukan objek dan, menggunakan alat stop-by-exception , kami dapat dengan mudah mencapai instruksi yang salah.

Karena kita tahu bahwa ketika mencoba untuk mendapatkan properti dari undefined, terjadi kesalahan.

Kami mengaktifkan alat penghenti pengecualian, mengatur variabel pengguna ke tidak terdefinisi.

  const user = undefined; 

Kami kembali berhenti di tempat properti firstName terdistorsi.

gambar

Itulah yang ingin saya sampaikan kepada Anda hari ini tentang men-debug perubahan yang tidak diinginkan pada objek.

Terima kasih telah membaca artikel ini. Seperti, berlangganan saluran, bagikan video dan artikel ini dengan teman, semuanya yang terbaik.

github.com/NVBespalov/js-lessons/tree/error/property-mutation

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


All Articles