Rumah >hujung hadapan web >tutorial js >Perbincangan sama ada nilai dalam JavaScript diluluskan oleh nilai atau oleh kemahiran reference_javascript

Perbincangan sama ada nilai dalam JavaScript diluluskan oleh nilai atau oleh kemahiran reference_javascript

WBOY
WBOYasal
2016-05-16 16:16:491126semak imbas

Saya menemui soalan yang menarik baru-baru ini: "Adakah nilai dalam JS diluluskan mengikut nilai atau rujukan?"
Sebelum menganalisis masalah ini, kita perlu memahami apa yang dipanggil dengan nilai dan apa yang dipanggil dengan rujukan. Dalam sains komputer, bahagian ini dipanggil Strategi Penilaian. Ia menentukan cara nilai dihantar antara pembolehubah dan antara parameter sebenar dan parameter formal apabila fungsi dipanggil.


Lulus mengikut nilai VS. Lulus dengan rujukan

Panggilan mengikut nilai ialah strategi penilaian yang paling biasa digunakan: parameter formal fungsi ialah salinan parameter sebenar yang diluluskan apabila dipanggil. Menukar nilai parameter formal tidak menjejaskan parameter sebenar.


Apabila melalui rujukan (panggilan melalui rujukan), parameter formal fungsi menerima rujukan tersirat kepada parameter sebenar, bukannya salinan. Ini bermakna jika nilai parameter fungsi diubah, parameter sebenar juga akan diubah suai. Pada masa yang sama kedua-duanya menunjukkan nilai yang sama.

Melewati rujukan menjadikannya lebih sukar untuk mengesan panggilan fungsi dan kadangkala menyebabkan pepijat halus.

Melepasi nilai memerlukan klon setiap kali, jadi prestasi lebih rendah untuk beberapa jenis yang kompleks. Kedua-dua kaedah lulus nilai mempunyai masalah mereka sendiri.

Mari kita lihat contoh C untuk memahami perbezaan antara lulus mengikut nilai dan rujukan:

Salin kod Kod adalah seperti berikut:
batal Ubah suai(int p, int * q)
{
p = 27; // Nilai lulus – p ialah salinan parameter sebenar a, hanya p diubah suai
*q = 27; // q ialah rujukan kepada b, kedua-dua q dan b diubah suai
}
int main()
{
int a = 1;
int b = 1;
Ubah suai(a, &b); // a diluluskan dengan nilai, b diluluskan dengan rujukan,
// a tidak berubah, b telah berubah
Pulangan(0);
}

Di sini kita boleh lihat:


a => Apabila p diluluskan dengan nilai, mengubah suai nilai parameter formal p tidak menjejaskan parameter sebenar a, iaitu hanya salinan a.
b => q diluluskan melalui rujukan Mengubah suai nilai parameter formal q juga mempengaruhi nilai parameter sebenar b.
Terokai cara nilai JS diluluskan
Jenis asas JS diluluskan mengikut nilai.

Salin kod Kod adalah seperti berikut:
var a = 1;
fungsi foo(x) {
x = 2;
}
foo(a);
console.log(a); // Masih 1, tidak terjejas oleh tugasan x = 2

Mari lihat objek sekali lagi:

Salin kod Kod adalah seperti berikut:
var obj = {x : 1};
fungsi foo(o) {
o.x = 3;
}
foo(obj);
console.log(obj.x); // 3, diubah suai!

Jelaskan bahawa o dan obj ialah objek yang sama, dan o bukan salinan obj. Jadi ia tidak diluluskan oleh nilai. Tetapi adakah ini bermakna objek JS diluluskan dengan rujukan? Mari lihat contoh berikut:

Salin kod Kod adalah seperti berikut:
var obj = {x : 1};
fungsi foo(o) {
o = 100;
}
foo(obj);
console.log(obj.x); // Masih 1, obj belum diubah suai kepada 100.

Jika ia diluluskan melalui rujukan, mengubah suai nilai parameter formal o harus mempengaruhi parameter sebenar. Tetapi mengubah suai nilai o di sini tidak menjejaskan obj. Oleh itu objek dalam JS tidak diluluskan dengan rujukan. Jadi bagaimanakah nilai objek dipindahkan dalam JS?


panggil dengan berkongsi Secara tepatnya, jenis asas dalam JS dihantar mengikut nilai dan jenis objek diluluskan dengan perkongsian (panggilan dengan perkongsian, juga dipanggil melalui objek dan lulus melalui perkongsian objek). Ia pertama kali dicadangkan oleh Barbara Liskov dalam bahasa GLU pada tahun 1974. Strategi penilaian ini digunakan dalam Python, Java, Ruby, JS dan bahasa lain.


Perkara utama strategi ini ialah: apabila memanggil fungsi untuk menghantar parameter, fungsi menerima salinan rujukan hujah objek (bukan salinan objek yang diluluskan mengikut nilai, mahupun rujukan tersirat yang diluluskan melalui rujukan). Perbezaan antaranya dan lulus melalui rujukan ialah penetapan parameter fungsi dalam pemindahan kongsi tidak akan menjejaskan nilai parameter sebenar. Seperti dalam contoh berikut, nilai obj tidak boleh diubah suai dengan mengubahsuai nilai parameter formal o.

Salin kod Kod adalah seperti berikut:

var obj = {x : 1};
fungsi foo(o) {
o = 100;
}
foo(obj);
console.log(obj.x); // Masih 1, obj belum diubah suai kepada 100.

Walau bagaimanapun, walaupun rujukan adalah salinan, objek yang dirujuk adalah sama. Mereka berkongsi objek yang sama, jadi mengubah suai nilai harta objek parameter formal juga akan mempengaruhi nilai harta parameter sebenar.
Salin kod Kod adalah seperti berikut:

var obj = {x : 1};
fungsi foo(o) {
o.x = 3;
}
foo(obj);
console.log(obj.x); // 3, diubah suai!

Untuk jenis objek, memandangkan objek boleh berubah, mengubah suai objek itu sendiri akan menjejaskan rujukan dan salinan rujukan yang berkongsi objek. Bagi jenis asas, kerana mereka semua tidak berubah, tidak ada perbezaan antara lulus dengan berkongsi dan lulus dengan nilai (panggilan mengikut nilai Oleh itu, jenis asas JS mematuhi kedua-dua lulus dengan nilai dan lulus dengan perkongsian).
Salin kod Kod adalah seperti berikut:

var a = 1; // 1 ialah jenis nombor, var b = a;
Mengikut strategi penilaian pass-by-share, a dan b ialah dua rujukan berbeza (b ialah salinan rujukan a), tetapi merujuk kepada nilai yang sama. Oleh kerana jenis asas nombor 1 di sini tidak boleh diubah, tidak ada perbezaan antara lulus mengikut nilai dan lulus dengan berkongsi.


Sifat tidak berubah jenis asas Jenis asas tidak boleh diubah (tidak boleh berubah), hanya objek boleh berubah (boleh berubah Sebagai contoh, nilai berangka 100, nilai Boolean benar, salah, ubah suai nilai ini (contohnya, tukar 1 kepada 3, tukar). benar kepada 100 ) tidak mempunyai makna. Apa yang lebih mudah untuk salah faham ialah rentetan dalam JS. Kadangkala kami cuba "menukar" kandungan rentetan, tetapi dalam JS, sebarang operasi yang kelihatan "mengubah suai" nilai rentetan sebenarnya mencipta nilai rentetan baharu.


Salin kod Kod adalah seperti berikut:
var str = "abc";
str[0]; // "a"
str[0] = “d”;
str; // Masih "abc"; Tiada cara untuk mengubah suai kandungan rentetan

Tetapi objek berbeza, objek boleh berubah.

Salin kod Kod adalah seperti berikut:
var obj = {x : 1};
obj.x = 100;
var o = obj;
o.x = 1;
obj.x; // 1, diubah suai
o = benar;
obj.x; // 1, tidak akan berubah kerana o = true

Di sini kita mentakrifkan obj pembolehubah, nilainya ialah objek, dan kemudian tetapkan nilai atribut obj.x kepada 100. Kemudian tentukan pembolehubah lain o, yang nilainya masih objek objek Pada masa ini, nilai dua pembolehubah obj dan o menunjuk ke objek yang sama (berkongsi rujukan kepada objek yang sama). Oleh itu, mengubah suai kandungan objek akan mempengaruhi kedua-dua obj dan o. Tetapi objek tidak diluluskan oleh rujukan Nilai o diubah suai oleh o = benar, yang tidak akan menjejaskan obj.
Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn