Bercakap tentang masalah yang disebabkan oleh menggunakan operasi tugasan berturut-turut dalam kemahiran javascript_javascript

WBOY
Lepaskan: 2016-05-16 15:29:36
asal
1139 orang telah melayarinya

Kata Pengantar

Ayat dalam tajuk artikel ini pada asalnya dilihat dalam spesifikasi JavaScript asing Pada masa itu, ia tidak menarik perhatian yang mencukupi sehingga pepijat baru-baru ini menemui ciri-ciri (perangkap) operasi penugasan berterusan dalam JS.

Selepas mencari dalam talian, saya menemui contoh tugasan berterusan yang sangat baik (sumber 1, sumber 2):

var a = {n:1};
a.x = a = {n:2};
console.log(a.x); // 输出?
Salin selepas log masuk

Jawapannya ialah:

console.log(a.x); // undefined
Salin selepas log masuk

Saya tidak tahu sama ada anda mendapat jawapan yang betul, sekurang-kurangnya saya salah.

Jadi saya mengambil peluang ini untuk melihat dengan lebih dekat cara tugasan berterusan JS berfungsi

Pesanan tugasan?

Andaikan terdapat kod: A=B=C , susunan pelaksanaan pernyataan tugasan adalah dari kanan ke kiri, jadi masalahnya ialah:

Adakah andaian 1: B = C;

Atau teka 2: B = C;

Kita semua tahu bahawa jika dua objek menghala ke objek pada masa yang sama, maka pengubahsuaian kepada objek ini disegerakkan, seperti:

var a={n:1};
var b=a;
a.n=2;
console.log(b);//Object {n: 2}
Salin selepas log masuk

Jadi, anda boleh menguji susunan tugasan berturut-turut berdasarkan ciri ini.

Mengikut tekaan 1, gantikan C dengan objek tertentu Anda boleh melihat bahawa pengubahsuaian a tidak akan disegerakkan kepada b, kerana dua {n:1} dibuat apabila baris pertama dan kedua dilaksanakan. Seperti:

var b={n:1};
var a={n:1};
a.n=0;
console.log(b);//Object {n: 1}
Salin selepas log masuk

Mengikut tekaan 2, gantikan C dengan objek tertentu Anda boleh melihat bahawa pengubahsuaian a disegerakkan kepada b, kerana a dan b merujuk kepada objek pada masa yang sama, seperti:

.
var b={n:1};
var a=b;
a.n=0;
console.log(b);//Object {n: 0}
Salin selepas log masuk

Menguji tugasan berterusan yang benar:

var a,b;
a=b={n:1};
a.n=0;
console.log(b);//Object {n: 0}
Salin selepas log masuk

Anda dapat melihat bahawa ia konsisten dengan tekaan 2. Jika sesiapa merasakan ujian ini tidak tepat, anda boleh mengujinya semula dan menggunakan ciri penetap dan pengambil ECMA5 untuk menguji.

Pertama sekali, setter dan getter digunakan pada nama pembolehubah, bukan objek yang sebenarnya disimpan dalam pembolehubah, seperti berikut:

Object.defineProperty(window,"obj",{
 get:function(){
  console.log("getter!!!");
 }
});
var x=obj;
obj;//getter!!! undefined
x;//undefined
Salin selepas log masuk

Anda dapat melihat bahawa hanya obj mengeluarkan "pengambil!!!", tetapi x tidak menggunakan ciri ini untuk menguji.

Ujian tugasan berterusan 2:

Object.defineProperty(window,"obj",{
 get:function(){
  console.log("getter!!!");
 }
});
a=b=obj;//getter!!! undefined
Salin selepas log masuk

Disahkan sekali lagi melalui pengambil, dalam A=B=C, C hanya dibaca sekali.

Jadi, peraturan operasi sebenar penetapan berterusan ialah B = C A = B, iaitu, penetapan berterusan sentiasa mengambil hanya hasil ungkapan di sebelah kanan tanda sama dari kanan ke kiri dan menetapkannya ke kiri; sisi tanda sama.

Bolehkah tugasan berterusan ditulis secara berasingan?

Anda boleh melihat peraturan sebenar tugasan berterusan daripada di atas Kemudian kembali ke kes pada permulaan artikel Jika anda membahagikan tugasan berterusan mengikut peraturan di atas, anda akan mendapati bahawa hasilnya adalah berbeza sebagai:

var a={n:1};
a={n:2};
a.x=a;
console.log(a.x);//Object {n: 2, x: Object}
Salin selepas log masuk

Jadi, walaupun penyataan tugasan berterusan mengikut peraturan tugasan dari kanan ke kiri, ia masih tidak boleh ditulis dalam penyataan berasingan Adapun mengapa

Saya rasa: Untuk memastikan ketepatan pernyataan tugasan, js akan terlebih dahulu mengeluarkan salinan semua alamat rujukan yang akan diberikan sebelum melaksanakan pernyataan tugasan, dan kemudian memberikan nilai satu demi satu.

Jadi saya rasa logik kod ini a.x=a={n:2};

1. Sebelum pelaksanaan, alamat rujukan a dalam a dan a.x akan dikeluarkan terlebih dahulu

2. Cipta objek baharu {n:2} dalam ingatan

3. Laksanakan a={n:2} dan tukar rujukan a daripada menunjuk ke {n:1} kepada menunjuk ke {n:2}

baharu

4. Laksanakan a.x=a pada masa ini, a sudah menunjuk ke objek baharu, dan kerana a.x mengekalkan rujukan asal sebelum pelaksanaan, a.x a menunjuk ke objek {n:1} asal, jadi objek baharu diberikan kepada objek asal Tambahkan atribut x dengan kandungan {n:2}, yang kini menjadi

5. Pelaksanaan pernyataan tamat, objek asal berubah daripada {n:1} kepada {n:1,x:{n:2}}, dan objek asal dikitar semula oleh GC kerana tiada siapa yang merujuknya lagi. Pada masa ini Titik ke objek baharu {n:2}

6. Jadi, kami mempunyai hasil larian pada permulaan artikel, dan kemudian jalankan a.x, ia secara semula jadi tidak ditentukan

Proses di atas digambarkan dengan nombor siri:

Berikutan proses di atas, dapat dilihat bahawa a.x lama dan a baharu kedua-duanya menghala ke objek yang baru dibuat {n:2}, jadi ia sepatutnya kongruen.

Ujian:

Oleh kerana kami menambah var b=a, yang bermaksud menambah rujukan kepada objek asal, ia tidak akan dikeluarkan dalam langkah 5 di atas, yang mengesahkan kesimpulan di atas.

Posskrip

Melalui masa ini, saya belajar tentang ciri-ciri tugasan berterusan. Melihat kembali tajuk artikel, nampaknya ia harus dipanggil:

Cuba untuk tidak menggunakan operasi penugasan berterusan JS melainkan anda benar-benar memahami mekanisme dalaman dan kemungkinan akibatnya.

sumber:php.cn
Kenyataan Laman Web ini
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
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan