Tipe primitif (Angka, String, dll.) Dilewatkan oleh nilai, tetapi Objek tidak diketahui, karena keduanya dapat lewat-oleh-nilai (jika kami menganggap bahwa variabel yang memegang objek sebenarnya referensi ke objek ) dan lulus-oleh-referensi (ketika kita menganggap bahwa variabel ke objek memegang objek itu sendiri). Show Meskipun pada akhirnya tidak terlalu penting, saya ingin tahu apa cara yang benar untuk menyajikan argumen yang lolos dari konvensi. Apakah ada kutipan dari spesifikasi JavaScript, yang mendefinisikan apa yang seharusnya menjadi semantik mengenai ini? Sangat menarik dalam Javascript. Pertimbangkan contoh ini:
Ini menghasilkan output:
Alih-alih, situasinya adalah bahwa item yang diteruskan dilewatkan dengan nilai. Tetapi item yang dilewatkan oleh nilai adalah itu sendiri referensi. Secara teknis, ini disebut panggilan-oleh-berbagi . Dalam istilah praktis, ini berarti bahwa jika Anda mengubah parameter itu sendiri (seperti dengan Itu selalu melewati nilai, tetapi untuk objek nilai variabel adalah referensi. Karena itu, ketika Anda melewatkan objek dan mengubah anggota , perubahan itu tetap ada di luar fungsi. Ini membuatnya terlihat seperti lewat referensi. Tetapi jika Anda benar-benar mengubah nilai variabel objek Anda akan melihat bahwa perubahan itu tidak bertahan, membuktikan itu benar-benar melewati nilai. Contoh:
Keluaran:
Variabel tidak "memegang" objek, itu memegang referensi. Anda dapat menetapkan referensi itu ke variabel lain, sekarang keduanya mereferensikan objek yang sama. Itu selalu melewati nilai (bahkan ketika nilai itu adalah referensi ...). Tidak ada cara untuk mengubah nilai yang dimiliki oleh variabel yang diteruskan sebagai parameter, yang akan mungkin jika JS didukung lewat referensi. 2 Cents saya .... Ini adalah cara saya memahaminya. (Jangan ragu untuk mengoreksi saya jika saya salah) Saatnya membuang semua yang Anda ketahui tentang nilai/referensi. Karena dalam JavaScript, tidak masalah apakah itu diteruskan oleh nilai atau dengan referensi atau apa pun. Yang penting adalah mutasi vs penugasan parameter dilewatkan ke fungsi. OK, biarkan saya melakukan yang terbaik untuk menjelaskan apa yang saya maksud. Katakanlah Anda memiliki beberapa objek.
Apa yang telah kami lakukan adalah "tugas" ... Kami telah menetapkan 2 objek kosong terpisah ke variabel "object1" dan "object2". Sekarang, katakanlah kita menyukai objek1 lebih baik ... Jadi, kita "menetapkan" variabel baru.
Selanjutnya, untuk alasan apa pun, kami memutuskan bahwa kami lebih suka objek 2. Jadi, kami cukup melakukan sedikit tugas ulang.
Tidak ada yang terjadi pada object1 atau object2. Kami belum mengubah data apa pun. Yang kami lakukan hanyalah menetapkan ulang apa objek favorit kami. Penting untuk mengetahui bahwa object2 dan favoriteObject keduanya ditugaskan untuk objek yang sama. Kita dapat mengubah objek itu melalui salah satu variabel tersebut.
OK, sekarang mari kita lihat primitif seperti string misalnya
Sekali lagi, kami memilih favorit.
Variabel favoriteString dan string1 kami ditugaskan ke 'Hello world'. Sekarang, bagaimana jika kita ingin mengubah Stringsing favorit kita ??? Apa yang akan terjadi???
Uh oh .... Apa yang terjadi. Kami tidak dapat mengubah string1 dengan mengubahString favorit ... Mengapa ?? karena string tidak berubah dan kami tidak mengubahnya. Yang kami lakukan adalah "RE ASSIGN" favoriteString ke string baru. Ini pada dasarnya memutusnya dari string1. Dalam contoh sebelumnya, ketika kami mengganti nama objek kami, kami tidak menetapkan apa pun. (Yah, sebenarnya ... kami lakukan, kami menetapkan properti nama ke string baru.) Sebaliknya, kami hanya bermutasi objek yang membuat koneksi antara 2 variabel dan objek yang mendasarinya. Sekarang, ke fungsi dan melewati parameter .... Ketika Anda memanggil fungsi, dan melewatkan parameter, apa yang Anda lakukan pada dasarnya adalah "tugas" ke variabel baru, dan berfungsi persis sama seperti jika Anda hanya ditugaskan menggunakan sama dengan (=) tanda. Ambil contoh ini.
Sekarang, hal yang sama, tetapi dengan suatu fungsi
OK, sekarang mari kita berikan beberapa contoh menggunakan objek saja ... pertama, tanpa fungsi.
Sekarang, hal yang sama, tetapi dengan pemanggilan fungsi
OK, jika Anda membaca seluruh posting ini, mungkin Anda sekarang memiliki pemahaman yang lebih baik tentang bagaimana panggilan fungsi bekerja di javascript. Tidak masalah apakah sesuatu dilewatkan dengan referensi atau dengan nilai ... Yang penting adalah penugasan vs mutasi. Setiap kali Anda melewatkan variabel ke suatu fungsi, Anda "Menugaskan" ke apa pun nama variabel parameternya, sama seperti jika Anda menggunakan tanda sama dengan (=). Selalu ingat bahwa tanda sama dengan (=) berarti tugas. Selalu ingat bahwa meneruskan parameter ke suatu fungsi juga berarti tugas. Mereka sama dan 2 variabel terhubung dengan cara yang persis sama. Satu-satunya waktu memodifikasi variabel mempengaruhi variabel yang berbeda adalah ketika objek yang mendasarinya dimutasi. Tidak ada gunanya membuat perbedaan antara objek dan primitif, karena ia bekerja dengan cara yang persis sama seolah-olah Anda tidak memiliki fungsi dan hanya menggunakan tanda sama dengan untuk menetapkan ke variabel baru. Satu-satunya gotcha adalah ketika nama variabel yang Anda masukkan ke dalam fungsi sama dengan nama parameter fungsi. Ketika ini terjadi, Anda harus memperlakukan parameter di dalam fungsi seolah-olah itu adalah variabel baru pribadi untuk fungsi (karena itu)
Pertimbangkan yang berikut ini:
Begitu, lupakan "lewat referensi/nilai" jangan terpaku pada "pass by reference/value" karena:
Untuk menjawab pertanyaan Anda: petunjuk diberikan.
Beberapa komentar terakhir:
Objek di luar fungsi dilewatkan ke fungsi dengan memberikan referensi ke luar obejct. Saat Anda menggunakan referensi itu untuk memanipulasi objeknya, objek di luar akan terpengaruh. Namun, jika di dalam fungsi Anda memutuskan untuk mengarahkan referensi ke sesuatu yang lain, Anda tidak mempengaruhi objek di luar sama sekali, karena semua yang Anda lakukan adalah mengarahkan kembali referensi ke sesuatu yang lain. Pikirkan seperti ini: Itu selalu melewati nilai. Namun, nilai suatu objek bukanlah objek itu sendiri, tetapi referensi ke objek itu. Berikut ini sebuah contoh, melewati angka (tipe primitif)
Mengulanginya dengan objek menghasilkan hasil yang berbeda:
Satu lagi contoh:
Javascript selalu pass-by-value , semuanya bertipe nilai. Objek adalah nilai, fungsi anggota dari objek adalah nilai itu sendiri (ingat bahwa fungsi adalah objek kelas satu dalam Javascript). Juga, mengenai konsep bahwa semua yang ada di Javascript adalah objek , ini salah. String, simbol, angka, boolean, null, dan undefined adalah primitif . Kadang-kadang mereka dapat memanfaatkan beberapa fungsi anggota dan properti yang diwarisi dari prototipe dasar mereka, tetapi ini hanya untuk kenyamanan, tidak berarti bahwa mereka adalah objek itu sendiri. Coba yang berikut untuk referensi
Di kedua peringatan Anda akan menemukan nilai yang tidak terdefinisi. Dalam JavaScript, jenis nilai hanya mengontrol apakah nilai itu akan ditetapkan oleh value-copy atau oleh reference-copy . Nilai-nilai primitif selalu ditetapkan/diteruskan oleh copy-nilai:
Nilai gabungan selalu diberikan/diteruskan dengan salinan-rujukan
Sebagai contoh
Dalam cuplikan di atas, karena Tetapi
Ketika kami
membuat tugas
Ketika kita meneruskan argumen Untuk secara efektif meneruskan nilai majemuk (seperti
Nilai majemuk (objek, array, dll) yang dapat dilewatkan oleh salinan referensi
Di sini, Sumber Penjelasan yang sangat terperinci tentang menyalin, meneruskan, dan membandingkan berdasarkan nilai dan referensi ada di bab ini dari buku "JavaScript: The Definitive Guide".
Satu hal yang masih belum saya pahami. Periksa kode di bawah ini. Adakah pikiran?
JavaScript melewati tipe primitif berdasarkan nilai dan tipe objek dengan referensi
- Brian Bi - Bahasa pemrograman manakah yang dilewati oleh referensi? MemperbaruiInilah bantahan untuk ini: Tidak ada "pass by reference" yang tersedia di JavaScript. Sebuah Semantik!! Menetapkan definisi konkret tentu akan membuat beberapa jawaban dan komentar tidak kompatibel karena mereka tidak menggambarkan hal yang sama bahkan ketika menggunakan kata dan frasa yang sama, tetapi sangat penting untuk melewati kebingungan (terutama untuk programmer baru). Pertama-tama, ada beberapa tingkatan abstraksi yang tampaknya tidak semua orang pahami. Programer yang lebih baru yang telah belajar bahasa generasi ke-4 atau ke-5 mungkin mengalami kesulitan membungkus pikiran mereka di sekitar konsep yang akrab bagi programmer atau programmer C tidak secara bertahap oleh pointer ke pointer ke pointer. Pass-by-reference tidak hanya berarti kemampuan untuk mengubah objek yang direferensikan menggunakan variabel parameter fungsi. Variable : Konsep gabungan dari simbol yang mereferensikan nilai pada lokasi tertentu dalam memori. Istilah ini biasanya terlalu dimuat untuk digunakan sendiri dalam membahas detail. Simbol : String teks yang digunakan untuk merujuk ke variabel (mis. Nama variabel). Nilai : Bit tertentu disimpan dalam memori dan direferensikan menggunakan simbol variabel. Lokasi memori : Di mana nilai variabel disimpan. (Lokasi itu sendiri diwakili oleh angka yang terpisah dari nilai yang disimpan di lokasi.) Parameter fungsi : Variabel dideklarasikan dalam definisi fungsi, digunakan untuk referensi variabel yang diteruskan ke fungsi. Argumen fungsi : Variabel di luar fungsi yang diteruskan ke fungsi oleh pemanggil. Variabel objek : Variabel yang nilai dasarnya yang mendasarinya bukan "objek" itu sendiri, melainkan nilainya adalah penunjuk (nilai lokasi memori) ke lokasi lain di memori tempat data aktual objek disimpan. Dalam sebagian besar bahasa generasi yang lebih tinggi, aspek "penunjuk" secara efektif disembunyikan oleh rujukan otomatis dalam berbagai konteks. Variabel primitif : Variabel yang nilainya IS nilai sebenarnya. Bahkan konsep ini dapat menjadi rumit dengan konteks auto-boxing dan objek-seperti dari berbagai bahasa, tetapi ide umumnya adalah bahwa nilai variabel IS nilai aktual diwakili oleh simbol variabel daripada pointer ke memori lain lokasi. Argumen fungsi dan parameter bukan hal yang sama. Juga, nilai variabel bukanlah objek variabel (seperti yang telah ditunjukkan oleh berbagai orang, tetapi tampaknya diabaikan). Perbedaan ini sangat penting untuk pemahaman yang tepat. Pass-by-value atau Call-by-sharing (untuk objek) : Nilai argumen fungsi COPIED ke lokasi memori lain yang direferensikan oleh simbol parameter fungsi (terlepas dari apakah itu di stack atau heap). Dengan kata lain, parameter fungsi menerima salinan dari nilai argumen yang diteruskan ... DAN (kritis) nilai argumen IS TIDAK PERNAH DIPERBARUI/DIUBAH/DIUBAH oleh fungsi panggilan. Ingat, nilai variabel objek BUKAN objek itu sendiri, melainkan itu adalah pointer ke objek, jadi meneruskan variabel objek dengan nilai menyalin pointer ke variabel parameter fungsi. Nilai parameter fungsi menunjuk ke objek yang sama persis di memori. Data objek itu sendiri dapat diubah secara langsung melalui parameter fungsi, TETAPI nilai argumen fungsi IS TIDAK PERNAH DIPERBARUI, sehingga akan terus menunjuk ke objek sama di seluruh dan bahkan setelah fungsi panggilan (bahkan jika data objeknya telah diubah atau jika parameter fungsi ditetapkan objek yang berbeda sama sekali). Tidaklah tepat untuk menyimpulkan bahwa argumen fungsi disahkan oleh referensi hanya karena objek yang direferensikan dapat diperbarui melalui variabel parameter fungsi. Call/Pass-by-reference : Nilai argumen fungsi dapat/akan diperbarui secara langsung oleh parameter fungsi yang sesuai. Jika itu membantu, parameter fungsi menjadi "alias" yang efektif untuk argumen - mereka secara efektif merujuk ke nilai yang sama di lokasi memori yang sama. Jika argumen fungsi adalah variabel objek, kemampuan untuk mengubah data objek tidak berbeda dari kasus pass-by-value karena parameter fungsi masih akan menunjuk ke objek yang sama dengan argumen. Tetapi dalam kasus variabel objek, jika parameter fungsi diatur ke objek yang sama sekali berbeda, maka argumen juga akan menunjuk ke objek yang berbeda - ini tidak terjadi dalam kasus pass-by-value. JavaScript tidak lulus dengan referensi. Jika Anda membaca dengan seksama, Anda akan menyadari bahwa semua pendapat yang bertentangan salah mengerti apa yang dimaksud dengan nilai demi nilai dan mereka secara keliru menyimpulkan bahwa kemampuan untuk memperbarui data objek melalui parameter fungsi identik dengan "nilai demi nilai". Objek clone/copy : Objek baru dibuat dan data objek asli disalin. Ini bisa berupa salinan yang dalam atau salinan yang dangkal, tetapi intinya adalah bahwa objek baru dibuat. Membuat salinan objek adalah konsep terpisah dari nilai per nilai. Beberapa bahasa membedakan antara objek kelas dan struct (atau sejenisnya), dan mungkin memiliki perilaku yang berbeda untuk meneruskan variabel dari jenis yang berbeda. Tetapi JavaScript tidak melakukan hal seperti ini secara otomatis ketika melewati variabel objek. Tetapi tidak adanya kloning objek otomatis tidak diterjemahkan menjadi pass-by-reference. Melewati argumen ke fungsi dalam JavaScript analog dengan melewati parameter dengan nilai pointer di C:
Ada beberapa diskusi tentang penggunaan istilah "pass by reference" di JS sini , tetapi untuk menjawab pertanyaan Anda:
(Dari artikel yang disebutkan di atas.) Ini sedikit penjelasan untuk Pass by value dan Pass by reference (Javascript). Dalam konsep ini, mereka berbicara tentang melewati variabel dengan referensi dan melewati variabel dengan referensi. Lewati nilai (Tipe Primitif)
Lulus dengan referensi (objek)
Kasus khusus, Lulus dengan referensi (objek)
Saya sudah membaca jawaban ini beberapa kali, tetapi tidak BENAR-BENAR mendapatkannya sampai saya belajar tentang definisi teknis dari "Panggil dengan berbagi" sebagaimana disebut oleh Barbara Liskov
Artinya, referensi parameter dapat diubah jika Anda pergi dan mengakses nilai parameter itu sendiri. Di sisi lain, penugasan ke parameter akan hilang setelah evaluasi, dan tidak dapat diakses oleh pemanggil fungsi. Cara sederhana saya untuk memahami ini ...
Untuk pengacara bahasa pemrograman, saya telah melalui bagian ECMAScript 5.1 berikut (yang lebih mudah dibaca daripada edisi terbaru), dan sejauh meminta di milis ECMAScript. TL; DR: Segala sesuatu disahkan oleh nilai, tetapi properti Object adalah referensi, dan definisi Object secara menyeramkan kurang dalam standar. Konstruksi Daftar ArgumenBagian 11.2.4 "Daftar Argumen" mengatakan yang berikut tentang membuat daftar argumen yang hanya terdiri dari 1 argumen:
Bagian ini juga menyebutkan kasus-kasus di mana daftar argumen memiliki 0 atau> 1 argumen. Dengan demikian, semuanya dilewatkan dengan referensi. Akses Properti ObyekBagian 11.2.1 "Aksesor Properti"
Dengan demikian, properti Objek selalu tersedia sebagai referensi. Tentang ReferensiDijelaskan di bagian 8.7 "Tipe Spesifikasi Referensi", bahwa referensi tersebut bukan tipe nyata dalam bahasa - mereka hanya digunakan untuk menggambarkan perilaku dari penghapusan, typeof, dan operator penugasan. Definisi "Objek"Didefinisikan dalam edisi 5.1 bahwa "Objek adalah kumpulan properti". Oleh karena itu, kita dapat menyimpulkan, bahwa nilai objek adalah koleksi, tetapi untuk apa nilai koleksi tidak didefinisikan dengan jelas dalam spesifikasi, dan membutuhkan sedikit upaya untuk memahami. Dalam bahasa tingkat rendah, jika Anda ingin melewatkan variabel dengan referensi Anda harus menggunakan sintaks tertentu dalam pembuatan fungsi:
Javascript adalah bahasa tingkat tinggi yang melakukan konversi ini untuk Anda. Jadi, meskipun objek dilewatkan oleh referensi, bahasa mengubah parameter referensi ke nilai. Anda tidak perlu menggunakan Itulah sebabnya ketika Anda mencoba mengubah objek di dalam suatu fungsi, dengan mengganti
nilainya (mis. Belajarlah lagi
Dalam Javascript, objects disimpan sebagai referensi:
Penjelasan paling ringkas yang saya temukan ada di panduan gaya AirBNB :
Misalnya.:
Misalnya.:
Yaitu. tipe primitif efektif dilewatkan oleh nilai, dan tipe kompleks dilewatkan oleh referensi. Cara mudah untuk menentukan apakah sesuatu itu "lewat referensi" adalah apakah Anda dapat menulis fungsi "tukar". Misalnya, dalam C, Anda dapat melakukan:
Jika Anda tidak dapat melakukan hal yang sama dalam Javascript, itu bukan "lewat referensi". Saya telah menemukan metode extended dari Underscore.js library sangat berguna ketika saya ingin mengirimkan objek sebagai parameter yang dapat dimodifikasi atau diganti seluruhnya.
Dokumen MDN menjelaskannya dengan jelas, tanpa terlalu bertele-tele:
Sumber: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Fungsi#Description
Saya akan mengatakan itu pass-by-copy - Pertimbangkan argumen dan objek variabel adalah objek yang dibuat selama konteks eksekusi yang dibuat di awal pemanggilan fungsi - dan nilai/referensi aktual Anda yang diteruskan ke fungsi hanya tersimpan dalam argumen ini + objek variabel. Secara sederhana, untuk tipe primitif, nilai-nilai disalin di awal pemanggilan fungsi, untuk tipe objek, referensi disalin. |