Apa zona mati temporal?

150

Saya pernah mendengar bahwa mengakses letdan constnilai - nilai sebelum diinisialisasi dapat menyebabkan ReferenceErrorkarena sesuatu yang disebut zona mati temporal .

Apa zona mati temporal, bagaimana hubungannya dengan ruang lingkup dan mengangkat, dan dalam situasi apa itu ditemui?

joews
sumber
6
kemungkinan duplikat dari variabel yang dideklarasikan dengan membiarkan atau const tidak diangkat dalam ES6? - walaupun pertanyaannya tidak fokus pada TDZ, jawabannya pada dasarnya sama
Bergi

Jawaban:

201

letdan constmemiliki dua perbedaan besar dari var:

  1. Mereka diblokir .
  2. Mengakses varsebelum dinyatakan memiliki hasilnya undefined; mengakses letatau constsebelum dinyatakan melempar ReferenceError:

console.log(aVar); // undefined
console.log(aLet); // causes ReferenceError: aLet is not defined
var aVar = 1;
let aLet = 2;

Tampaknya dari contoh-contoh ini bahwa letdeklarasi (dan const, yang bekerja dengan cara yang sama) mungkin tidak diangkat , karena aLettampaknya tidak ada sebelum diberi nilai.

Itu tidak terjadi, namun- letdan const yang mengangkat (seperti var, classdan function), tetapi ada periode antara memasuki ruang lingkup dan dinyatakan mana mereka tidak dapat diakses. Periode ini adalah zona mati temporal (TDZ) .

TDZ berakhir ketika aLetsedang dinyatakan , daripada ditugaskan :

//console.log(aLet)  // would throw ReferenceError

let aLet;
console.log(aLet); // undefined
aLet = 10;
console.log(aLet); // 10

Contoh ini menunjukkan yang letdiangkat:

let x = 'outer value';
(function() {
  // start TDZ for x
  console.log(x);
  let x = 'inner value'; // declaration ends TDZ for x
}());

Kredit: Zona Mati Temporal (TDZ) demistifikasi

Mengakses xdalam lingkup dalam masih menyebabkan a ReferenceError. Jika lettidak diangkat, itu akan masuk outer value.

TDZ adalah hal yang baik karena membantu menyoroti bug — mengakses nilai sebelum dinyatakan jarang disengaja.

TDZ juga berlaku untuk argumen fungsi default. Argumen dievaluasi dari kiri ke kanan, dan setiap argumen ada di TDZ sampai ditetapkan:

// b is in TDZ until its value is assigned
function testDefaults(a=b, b) { }
testDefaults(undefined, 1); // throws ReferenceError because the evaluation of a reads b before it has been evaluated.

TDZ tidak diaktifkan secara default di babel.js transpiler. Aktifkan mode "kepatuhan tinggi" untuk menggunakannya dalam REPL . Berikan es6.spec.blockScopingbendera untuk menggunakannya dengan CLI atau sebagai perpustakaan.

Rekomendasi bacaan lebih lanjut: TDZ demistified dan ES6 Let, Const dan "Temporal Dead Zone" (TDZ) di Depth .

joews
sumber
3
Juga menarik: Mengapa ada zona mati temporal
oliver yang lebih baik
@zeroflagL tautan yang bagus, terima kasih. Juga dikatakan: "foo tidak dideklarasikan, tidak diinisialisasi", bahwa bahasa akan sangat membantu untuk memperjelas / memperbaiki dalam jawaban di atas. let foodalam sebuah blok menyebabkannya diangkat dan dideklarasikan di bagian atas blok itu. Garis let foopenyebabnya diinisialisasi. Dan foo = xyzmenyebabkannya diberi nilai.
AJP
2
Saya pikir ini adalah pos yang bagus! Namun, saya mendapat kesan bahwa 'biarkan' tidak perlu diangkat? Saya menemukan ini di dokumen Mozilla: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… Saya tidak mencoba menjadi kurmudgeon, saya hanya ingin tahu dan terbuka untuk klarifikasi.
dmarges
1
@jeows Halaman MDN masih mengatakan mereka tidak diangkat. Anda harus mencoba mengeditnya, jika Anda benar-benar yakin dengan apa yang Anda katakan. Saya pikir saya harus mengirim pertanyaan tentang itu.
doubleOrt
1
@news IMO, Anda bisa mengatakan mereka telah diangkat tetapi mereka tidak dapat diakses sebelum deklarasi mereka tercapai karena TDZ, atau Anda bisa mengatakan mereka tidak diangkat tetapi TDZ akan menyebabkan referensi kepada mereka untuk membuat kesalahan. Secara praktis, kedua pernyataan itu sama benarnya. Kecuali, saya pikir, Anda menggunakan istilah "mengangkat" dalam arti abstrak, seperti dalam "mengangkat = setiap kali mesin menyadari keberadaan variabel itu". Apakah itu sebabnya? Plus, apa yang dikatakan oleh spesifikasi itu?
doubleOrt
7

Mengangkat:
let , const, varsemua proses mengangkat get.
(Apa artinya mereka naik ke atas dan menyatakan di bagian atas lingkup.)

Inisialisasi:

  • varpergi juga melalui proses awal, dan dapatkan nilai awal undefined.
  • sementara let, consttidak ikut membuang proses awal, sehingga nilainya masih tidak dapat diakses, meskipun sudah dinyatakan. whats menempatkan merekatemporal dead zone

Jadi singkatnya:

Proses mengangkat: var, let, const
proses Inisialisasi: var

ofir_aghai
sumber
0

Dalam kasus variabel let dan const, Pada dasarnya, Zona Mati Temporal adalah zona

"sebelum variabel Anda dideklarasikan",

yaitu di mana Anda tidak dapat mengakses nilai variabel-variabel ini, itu akan menimbulkan kesalahan.

ex.

let sum = a + 5;        //---------
//some other code       //         | ------>  this is TDZ for variable a
                        //         |
console.log(sum)        //---------
let a = 5;

kode di atas memberikan kesalahan

kode yang sama tidak akan memberikan kesalahan ketika kita menggunakan var untuk variabel 'a',

ex.

var sum = a;                            
console.log(sum)     //prints undefined
var a = 5;
niranjan harpale
sumber
log konsol menghasilkan "NaN" pada contoh kedua (hasil penambahan undefineddan 5). The declaratation dari var ayang mengangkat, kode inifialisation setelan telah asampai 5 tidak.
traktor53
ya, benar, a diangkat tanpa inisialisasi. Jadi a tidak akan terdefinisi.
niranjan harpale
Contoh pertama yang dikutip tidak benar, perbaiki atau hapus.
Web Spidi