Saya baru -baru ini menemukan pertanyaan yang menarik: "Apakah nilai -nilai dalam JS diteruskan berdasarkan nilai atau referensi?"
Sebelum menganalisis masalah ini, kita perlu memahami apa yang disebut nilai dan apa yang disebut dengan referensi. Dalam ilmu komputer, bagian ini disebut strategi evaluasi. Ini menentukan bagaimana nilai dilewatkan antara variabel, antara parameter nyata dan parameter formal saat memanggil fungsi.
Lulus dengan Nilai Vs. Lulus dengan referensi
Panggilan berdasarkan nilai adalah strategi evaluasi yang paling umum digunakan: parameter formal suatu fungsi adalah salinan parameter aktual yang dilewati ketika dipanggil. Memodifikasi nilai parameter formal tidak akan mempengaruhi parameter aktual.
Saat melewati referensi (panggilan dengan referensi), parameter formal fungsi menerima referensi implisit dari parameter aktual, bukan salinan. Ini berarti bahwa jika nilai parameter fungsi dimodifikasi, parameter aktual juga akan dimodifikasi. Keduanya menunjuk pada nilai yang sama.
Lulus dengan referensi membuat pelacakan fungsi panggilan lebih sulit dan kadang -kadang menyebabkan beberapa bug halus.
Lewati nilai karena replika dikloning setiap kali, kinerja lebih rendah untuk beberapa jenis kompleks. Kedua metode nilai lewat memiliki masalah sendiri.
Mari kita lihat contoh C untuk memahami perbedaan antara melewati nilai dan referensi:
Salinan kode adalah sebagai berikut:
void odify (int p, int * q)
{
p = 27; // Lewati P menurut nilai adalah salinan parameter aktual A, hanya p yang dimodifikasi
*q = 27; // Q adalah referensi ke B, dan kedua Q dan B dimodifikasi
}
int main ()
{
int a = 1;
int b = 1;
Modifikasi (A, & B); // A Pass by Nilai, B Pass dengan Referensi,
// A belum berubah, B telah berubah
kembali (0);
}
Di sini kita dapat melihat:
A => Ketika P dilewatkan berdasarkan nilai, memodifikasi nilai parameter formal P tidak mempengaruhi parameter aktual A, P hanyalah salinan a.
b => q disahkan dengan referensi. Saat memodifikasi nilai parameter formal Q, itu juga mempengaruhi nilai parameter aktual b.
Jelajahi bagaimana nilai JS dilewati
Jenis dasar JS dilewatkan berdasarkan nilai.
Salinan kode adalah sebagai berikut:
var a = 1;
fungsi foo (x) {
x = 2;
}
foo (a);
console.log (a); // Masih 1, tidak terpengaruh oleh penugasan x = 2
Mari kita lihat objek:
Salinan kode adalah sebagai berikut:
var obj = {x: 1};
fungsi foo (o) {
sapi = 3;
}
foo (obj);
console.log (obj.x); // 3, dimodifikasi!
Jelaskan O dan OBJ adalah objek yang sama, dan O bukan salinan OBJ. Jadi itu tidak diteruskan berdasarkan nilai. Tetapi apakah ini berarti bahwa objek JS dilewatkan dengan referensi? Mari kita lihat contoh -contoh berikut:
Salinan kode adalah sebagai berikut:
var obj = {x: 1};
fungsi foo (o) {
o = 100;
}
foo (obj);
console.log (obj.x); // Masih 1, OBJ belum dimodifikasi menjadi 100.
Jika dilewati dengan referensi, memodifikasi nilai parameter formal O, itu harus mempengaruhi parameter aktual. Tetapi memodifikasi nilai O di sini tidak mempengaruhi OBJ. Oleh karena itu, objek di JS tidak dilewatkan dengan referensi. Jadi bagaimana nilai objek diteruskan di JS?
Lulus panggilan dengan berbagi
Lebih tepatnya, tipe dasar dalam JS dilewatkan oleh nilai -nilai, dan tipe objek dilewatkan dengan berbagi (panggilan dengan berbagi, juga dipanggil berdasarkan objek dan dibagikan berdasarkan objek). Ini pertama kali diusulkan oleh Barbara Liskov. Dalam bahasa Glu 1974. Strategi evaluasi ini digunakan dalam Python, Java, Ruby, JS dan bahasa lainnya.
Inti dari strategi ini adalah bahwa ketika suatu fungsi melewati argumen, fungsi menerima salinan referensi argumen aktual objek (tidak ada salinan objek yang dilewati oleh nilai, atau referensi implisit yang disahkan oleh referensi). Perbedaan antara itu dan lulus dengan referensi adalah bahwa penugasan parameter fungsi dalam pass bersama tidak akan mempengaruhi nilai parameter aktual. Seperti dalam contoh berikut, nilai OBJ tidak dapat dimodifikasi dengan memodifikasi nilai parameter formal o.
Salinan kode adalah sebagai berikut:
var obj = {x: 1};
fungsi foo (o) {
o = 100;
}
foo (obj);
console.log (obj.x); // Masih 1, OBJ belum dimodifikasi menjadi 100.
Namun, meskipun referensi adalah salinan, objek yang direferensikan adalah sama. Mereka berbagi objek yang sama, sehingga memodifikasi nilai atribut dari objek parameter formal juga akan mempengaruhi nilai atribut dari parameter aktual.
Salinan kode adalah sebagai berikut:
var obj = {x: 1};
fungsi foo (o) {
sapi = 3;
}
foo (obj);
console.log (obj.x); // 3, dimodifikasi!
Untuk tipe objek, karena objek dapat berubah, memodifikasi objek itu sendiri akan mempengaruhi berbagi referensi dan salinan referensi objek. Untuk tipe dasar, karena keduanya tidak dapat diubah, tidak ada perbedaan antara melewati dengan berbagi dan melewati nilai (panggilan demi nilai), sehingga tipe dasar JS keduanya sejalan dengan melewati nilai dan sejalan dengan melewati berbagi.
Salinan kode adalah sebagai berikut:
var a = 1; // 1 adalah nomor tipe, var b = a; a; B = 6;
Menurut strategi evaluasi yang disahkan oleh dibagikan, A dan B adalah dua referensi yang berbeda (B adalah salinan referensi A), tetapi referensi nilai yang sama. Karena tipe dasar nomor 1 di sini tidak dapat diubah, tidak ada perbedaan antara melewati nilai dan melewati berbagi di sini.
Sifat tidak jelas dari tipe dasar
Tipe dasarnya tidak berubah, dan hanya objek yang dapat berubah. Misalnya, nilai numerik 100, nilai boolean benar, salah, dan memodifikasi nilai -nilai ini (misalnya, mengubah 1 menjadi 3, dan mengubah true menjadi 100) tidak masuk akal. Yang lebih mudah disalahpahami adalah string di JS. Kadang -kadang kami mencoba untuk "mengubah" isi string, tetapi dalam JS, operasi "memodifikasi" apa pun yang tampaknya menjadi nilai string sebenarnya menciptakan nilai string baru.
Salinan kode adalah sebagai berikut:
var str = "ABC";
str [0]; // "A"
str [0] = "d";
str; // Masih "ABC"; tugas tidak valid. Tidak ada cara untuk memodifikasi konten string
Objeknya berbeda, objeknya bervariasi.
Salinan kode adalah sebagai berikut:
var obj = {x: 1};
obj.x = 100;
var o = obj;
sapi = 1;
obj.x; // 1, dimodifikasi
o = true;
obj.x; // 1, tidak akan berubah karena o = true
Di sini variabel OBJ didefinisikan, nilainya adalah objek, dan kemudian nilai properti OBJ.X diatur ke 100. Kemudian tentukan variabel lain O, dan nilainya masih objek objek ini. Pada saat ini, nilai -nilai dari dua variabel OBJ dan O menunjuk ke objek yang sama (berbagi referensi ke objek yang sama). Oleh karena itu, memodifikasi konten objek memiliki dampak pada OBJ dan O. Namun, objek tidak diteruskan dengan referensi. Nilai O dimodifikasi oleh O = true dan tidak akan mempengaruhi OBJ.