Kami menangani objek dalam JavaScript

Pada artikel ini, seorang penulis - pengembang front-end - memberikan ikhtisar tentang cara utama untuk membuat, memodifikasi dan membandingkan objek JavaScript.


Objek adalah salah satu konsep dasar dalam JavaScript. Ketika saya mulai mempelajarinya, itu tampak cukup sederhana bagi saya: hanya beberapa kunci dan nilai, seperti yang dijelaskan dalam teori.

Hanya setelah beberapa waktu saya mulai menyadari bahwa topik itu jauh lebih rumit daripada yang saya kira. Dan kemudian saya mulai mempelajari informasi dari berbagai sumber. Beberapa dari mereka memberikan ide yang bagus tentang masalah ini, tetapi saya tidak bisa langsung melihat keseluruhan gambar.

Dalam posting ini, saya mencoba untuk mencakup semua aspek bekerja dengan objek di JS, tanpa masuk terlalu jauh ke detail individu, tetapi tanpa kehilangan detail penting yang akan membantu Anda memahami subjek dan merasa lebih percaya diri selama studi lebih lanjut.

Jadi mari kita mulai dengan dasar-dasarnya.

Obyek


Objek dalam JavaScript hanyalah kumpulan properti, yang masing-masing merupakan pasangan nilai kunci. Kunci dapat diakses menggunakan notasi bertitik ( obj.a ) atau kurung kurung ( obj ['a'] ).

Ingat bahwa tanda kurung harus digunakan jika kuncinya adalah:

  • bukan pengidentifikasi JavaScript yang valid (memiliki spasi, tanda hubung, itu dimulai dengan angka ...)
  • adalah variabel.

Salah satu properti yang objek di JS dapatkan ketika mereka dibuat disebut Prototipe , dan ini adalah konsep yang sangat penting.

Prototipe


Setiap objek dalam JavaScript memiliki properti internal yang disebut Prototipe . Di sebagian besar browser, Anda dapat merujuknya dengan sebutan __proto__ .

Prototipe adalah cara untuk menyediakan warisan properti dalam JavaScript. Jadi, Anda dapat berbagi fungsionalitas tanpa menggandakan kode dalam memori. Metode ini bekerja dengan membuat hubungan antara dua objek.

Sederhananya, Prototipe membuat pointer dari satu objek ke objek lain.

Rantai prototipe

Setiap kali JS mencari properti di objek dan tidak menemukannya langsung di objek itu sendiri, JS akan memeriksa keberadaan properti di objek prototipe. Jika tidak ada properti di dalamnya, maka JS akan terus mencari dalam prototipe objek terkait. Ini akan berlanjut sampai JS menemukan properti yang cocok atau mencapai akhir rantai.

Mari kita lihat sebuah contoh:

var cons = function () {   this.a = 1;   this.b = 2; } var obj = new cons(); </i>  cons.prototype.b = 3; cons.prototype.c = 4; 

kontra adalah konstruktor (hanya fungsi yang dapat dipanggil menggunakan operator baru ).

Pada baris kelima, kita membuat objek baru - salinan kontra baru . Segera setelah membuat, obj juga mendapat properti prototipe.

Dan sekarang kita menambahkan properti ( 'b', 'c' ) ke prototipe objek kontra .
Pertimbangkan obj :

obj.a // 1 - semuanya seperti sebelumnya , obj.a masih 1.
obj.c - obj tidak memiliki properti c ! Namun, seperti yang disebutkan sebelumnya, JS sekarang akan mencarinya di prototipe objek dan mengembalikan nilai 4.

Sekarang mari kita pikirkan apa nilai obj.b itu dan apa jadinya bila kita menghapus obj.b ?

Obj.b adalah 2. Kami menetapkan properti b , tetapi kami melakukannya untuk prototipe kontra , jadi ketika kami memeriksa obj.b , kami masih mendapatkan 2. Namun, segera setelah menghapus obj.b, JS tidak lagi dapat menemukan b di o bj , dan karenanya akan melanjutkan pencarian dalam prototipe dan mengembalikan nilai 3.

Selanjutnya, saya ingin berbicara singkat tentang berbagai cara untuk membuat objek dan lebih banyak tentang prototipe.

Penciptaan Obyek


Objek literal: biarkan obj = {a: 1};
Kami membuat objek dengan rantai prototipe berikut: obj ---> Object.prototype ---> null
Seperti yang bisa Anda tebak, object.prototype adalah prototipe objek, serta akhir dari rantai prototipe.

Object.create (): var newObj = Object.create (obj);
NewObj akan memiliki rantai prototipe berikut: newObj ---> obj ---> Object.prototype ---> null

Konstruktor. Seperti pada contoh di atas, konstruktor hanyalah fungsi JS yang memungkinkan kita menggunakan operator baru untuk membuat instance baru.

Kelas ES6:

 class rectangle { constructor(height, width) { this.height = height; this.width = width; } getArea() { return this.height * this.width; } } let square = new rectangle(2, 2); 

Square adalah turunan dari konstruktor persegi panjang , jadi kita bisa memanggil square.getArea () // 4 , square.width , serta semua fungsi yang diwarisi dari object.prototype .

Metode mana yang lebih baik? Jika Anda berencana untuk membuat banyak instance, Anda dapat menggunakan ES6 atau konstruktor. Jika Anda berencana untuk membuat objek sekali, lebih baik untuk menentukan literal, karena ini adalah cara termudah.

Dan sekarang, ketika kita belajar tentang prototipe dan berkenalan dengan semua cara untuk membuat objek baru, kita dapat melanjutkan untuk membahas salah satu aspek yang paling membingungkan terkait dengan objek.

Membandingkan dan memodifikasi objek


Dalam JavaScript, objek adalah tipe referensi

Ketika kita membuat objek, biarkan obj = {a: 1}; , variabel obj mendapat alamat di memori objek, tetapi bukan nilainya! Sangat penting untuk memahami perbedaan ini, karena kesalahan dapat terjadi sebaliknya. Ketika kita membuat objek lain, biarkan newObj = obj , kita benar-benar membuat pointer ke area tertentu dari memori obj , dan bukan objek yang sepenuhnya baru.

Ini berarti bahwa dengan menjalankan newObj.a = 2 , kami benar-benar mengubah obj sehingga obj.a menjadi 2!

Pendekatan ini dengan mudah menyebabkan munculnya bug, sehingga banyak perusahaan bekerja dengan objek yang tidak dapat diubah. Alih-alih mengubah objek yang sudah dibuat, Anda harus membuat lagi objek baru (salinan aslinya) dan mengubahnya. Ini adalah betapa pentingnya perpustakaan seperti Redux bekerja, dan secara keseluruhan ini adalah salah satu konsep dasar pemrograman fungsional. Baca lebih lanjut di sini .

Kesetaraan

Dari penjelasan di atas, dapat diketahui bahwa dua objek tidak akan pernah bisa sama, walaupun mereka memiliki sifat yang sama. Hal ini disebabkan oleh fakta bahwa JS sebenarnya membandingkan lokasi objek dalam memori, dan dua objek tidak pernah berada dalam sel memori yang sama.

 // Two distinct objects with the same properties are not equal var fruit = {name: 'apple'}; var fruitbear = {name: 'apple'}; fruit === fruitbear; // return false // here fruit and fruitbear are pointing to same object var fruit = {name: 'apple'}; var fruitbear = fruit; fruit === fruitbear; // return true 

Jadi, Anda kemungkinan besar sudah bertanya-tanya bagaimana cara membandingkan objek atau bagaimana melakukan berbagai manipulasi dengan objek, mengingat persyaratan untuk kekekalannya.

Pertimbangkan beberapa kemungkinan.

Perubahan objek

Misalkan jelas bahwa dengan cara yang baik kita tidak boleh mengubah objek, jadi kami ingin membuat salinan objek yang sesuai dan mengubah propertinya. Object.assign () datang untuk menyelamatkan .

 var obj = { a : 1, b : 2}; var newObj = Object.assign({}, obj,{a:2}) // {a : 2, b : 2 } 

Jika kita ingin mengubah nilai properti obj , kita dapat menggunakan object.assign untuk membuat salinan obj dan mengubahnya.

Contoh tersebut menunjukkan bahwa kita pertama-tama membuat objek kosong, lalu menyalin nilai obj dan membuat perubahan, akhirnya mendapatkan objek baru dan siap digunakan.

Harap dicatat bahwa metode ini tidak akan berfungsi untuk penyalinan dalam. Berbicara tentang penyalinan yang dalam, kami bermaksud bahwa Anda perlu menyalin objek dengan satu properti atau lebih.

 const obj = {a : 1, b : { a : 1 } }; // b property is an object 

Object.assign () menyalin properti objek, jadi jika nilai properti adalah pointer ke objek, hanya pointer yang disalin.

Penyalinan yang dalam membutuhkan operasi rekursif. Anda dapat menulis fungsi di sini atau cukup menggunakan metode _.cloneDeep dari pustaka Lodash .

Perbandingan Objek

Ada satu cara keren untuk bekerja dengan objek - konversi baris. Dalam contoh berikut, kami mengonversi kedua objek menjadi string dan membandingkannya:

 JSON.stringify(obj1) === JSON.stringify(obj2) 

Pendekatan ini dibenarkan, karena pada akhirnya kami membandingkan string yang mewakili pointer ke tipe nilai. Kabar buruknya adalah bahwa itu tidak selalu berhasil, terutama karena satu atau urutan properti lainnya dari objek tidak dijamin.

Solusi bagus lainnya adalah dengan menggunakan metode _.isEqual dari Lodash , yang melakukan perbandingan objek secara mendalam.

Dan sebelum kita selesai, mari kita membahas beberapa pertanyaan yang sering diajukan tentang objek. Ini akan membantu menggali lebih dalam ke dalam topik dan mempraktikkan pengetahuan yang diperoleh.

Cobalah untuk memikirkan solusinya sendiri sebelum membaca jawabannya.

Bagaimana cara mengetahui panjang suatu benda?


Untuk mendapatkan jawabannya, perlu menyortir semua properti objek satu per satu dan menghitungnya. Ada beberapa cara untuk melakukan iterasi ini:

  • untuk masuk Metode ini mencakup semua properti yang dapat dihitung dari suatu objek dan rantai prototipe-nya. Kami berkenalan dengan prototipe (dan, saya harap, mempelajari materi), jadi harus jelas bahwa penggunaan untuk tidak akan selalu benar untuk mendapatkan sifat-sifat objek.
  • Objek.kunci . Metode ini mengembalikan array dengan kunci properti terhitung (miliknya ke objek yang ditentukan). Pendekatan ini lebih baik, karena kami hanya bekerja pada properti dari suatu objek, tanpa menggunakan properti prototipe . Namun, ada beberapa situasi ketika Anda mengatur atribut enumerable dari beberapa properti menjadi false, dan object.keys akhirnya melewatkannya, dan Anda mendapatkan hasil yang salah. Ini jarang terjadi, tetapi dalam kasus seperti itu getOwnPropertyNames akan berguna .
  • getOwnPropertyNames mengembalikan array yang berisi semua kunci objek sendiri (baik yang dapat dihitung maupun yang tidak terhitung).

Juga layak disebutkan:

  • Object.values ​​mengulangi properti penghitungannya sendiri dan mengembalikan array dengan nilai yang sesuai.
  • Object.entries mengulangi properti penghitungannya sendiri dan mengembalikan array dengan kunci dan nilainya .

Saya pikir Anda memperhatikan bahwa sebagian besar metode yang tercantum di atas mengembalikan array. Ini adalah peluang untuk memanfaatkan sepenuhnya metode JavaScript untuk bekerja dengan array.

Salah satu metode tersebut adalah array.length . Pada akhirnya, kita bisa menulis

 let objLength = Object.getOwnPropertyNames(obj).length; 

Bagaimana cara memeriksa apakah suatu objek kosong?


  1. JSON.stringify (myObj) === “{}” . Di sini kita kembali menggunakan alat konversi string, yang membuatnya mudah untuk memeriksa apakah suatu objek kosong (membandingkan string, bukan objek).
  2. ! Object.keys (myobj). Length // true . Seperti yang saya sebutkan, mengonversi kunci objek ke array bisa sangat berguna. Di sini kita menggunakan panjang properti nyaman yang diwarisi dari Array.prototype , dengan memeriksa panjang kunci dalam array. Di JS, 0 berubah menjadi false, jadi tambah ! kita mengubahnya menjadi benar. Angka lain akan berubah menjadi false.

Kesimpulannya


Saya harap sekarang Anda merasa lebih percaya diri dalam membuat objek dan bekerja dengannya. Mari kita simpulkan:

  • Ingatlah bahwa objek milik tipe referensi, yang berarti direkomendasikan untuk bekerja dengannya tanpa mengubah objek aslinya.
  • Berteman dengan properti prototipe dan rantai prototipe .
  • Kenali alat bantu dalam bekerja dengan objek. Ingatlah bahwa Anda dapat mengubah objek menjadi string, mendapatkan array dengan kunci mereka, atau hanya mengulangi properti mereka menggunakan serangkaian metode yang kami temui.

Selamat mencoba objek JavaScript.

gambar

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


All Articles