Apa perbedaan antara menggunakan "let" dan "var"?

4544

ECMAScript 6 diperkenalkan pada letpernyataan .

Saya pernah mendengar bahwa itu digambarkan sebagai variabel "lokal", tapi saya masih tidak yakin bagaimana ia berperilaku berbeda dari varkata kunci.

Apa perbedaannya? Kapan sebaiknya letdigunakan var?

TM.
sumber
105
ECMAScript adalah standar dan lettermasuk dalam draft edisi ke - 6 dan kemungkinan besar akan berada dalam spesifikasi akhir.
Richard Ayotte
5
Lihat kangax.github.io/es5-compat-table/es6 untuk matriks dukungan terkini fitur ES6 (termasuk let). Pada saat penulisan Firefox, Chrome dan IE11 semuanya mendukungnya (walaupun saya percaya implementasi FF tidak cukup standar).
Nico Burns
22
Untuk waktu yang paling lama saya tidak tahu bahwa vars di for for loop dicakup ke fungsi itu dibungkus. Saya ingat mencari tahu ini untuk pertama kalinya dan berpikir itu sangat bodoh. Saya melihat beberapa kekuatan meskipun mengetahui sekarang bagaimana keduanya dapat digunakan untuk alasan yang berbeda dan bagaimana dalam beberapa kasus Anda mungkin benar-benar ingin menggunakan var dalam for loop dan tidak memilikinya melingkup ke blok.
Eric Bishard
1
Ini adalah bacaan yang sangat baik wesbos.com/javascript-scoping
onmyway133
1
Jawabannya dijelaskan dengan baik di sini stackoverflow.com/a/43994458/5043867
Pardeep Jain

Jawaban:

6101

Aturan pelingkupan

Perbedaan utama adalah aturan pelingkupan. Variabel yang dideklarasikan oleh varkata kunci dilingkupi ke badan fungsi langsung (maka lingkup fungsi) sementara letvariabel dilingkupi ke blok penutup langsung yang dilambangkan dengan { }( oleh karenanya ruang lingkup blok).

function run() {
  var foo = "Foo";
  let bar = "Bar";

  console.log(foo, bar);

  {
    let baz = "Bazz";
    console.log(baz);
  }

  console.log(baz); // ReferenceError
}

run();

Alasan mengapa letkata kunci diperkenalkan ke bahasa adalah ruang lingkup fungsi membingungkan dan merupakan salah satu sumber utama bug dalam JavaScript.

Lihatlah contoh ini dari pertanyaan stackoverflow lain :

var funcs = [];
// let's create 3 functions
for (var i = 0; i < 3; i++) {
  // and store them in funcs
  funcs[i] = function() {
    // each should log its value.
    console.log("My value: " + i);
  };
}
for (var j = 0; j < 3; j++) {
  // and now let's run each one to see
  funcs[j]();
}

My value: 3adalah output ke konsol setiap kali funcs[j]();dipanggil karena fungsi anonim terikat ke variabel yang sama.

Orang harus segera membuat fungsi yang dipanggil untuk mengambil nilai yang benar dari loop tetapi itu juga berbulu.

Mengangkat

Sementara variabel yang dideklarasikan dengan varkata kunci diangkat (diinisialisasi dengan undefinedsebelum kode dijalankan) yang berarti mereka dapat diakses dalam lingkup terlampir mereka bahkan sebelum mereka dideklarasikan:

function run() {
  console.log(foo); // undefined
  var foo = "Foo";
  console.log(foo); // Foo
}

run();

letvariabel tidak diinisialisasi sampai definisi mereka dievaluasi. Mengaksesnya sebelum inisialisasi menghasilkan a ReferenceError. Variabel dikatakan berada di "zona mati temporal" dari awal blok sampai inisialisasi diproses.

function checkHoisting() {
  console.log(foo); // ReferenceError
  let foo = "Foo";
  console.log(foo); // Foo
}

checkHoisting();

Membuat properti objek global

Di tingkat atas let, tidak seperti var, tidak membuat properti pada objek global:

var foo = "Foo";  // globally scoped
let bar = "Bar"; // globally scoped

console.log(window.foo); // Foo
console.log(window.bar); // undefined

Deklarasi ulang

Dalam mode ketat, varAnda akan mendeklarasikan ulang variabel yang sama dalam cakupan yang sama sambil letmemunculkan SyntaxError.

'use strict';
var foo = "foo1";
var foo = "foo2"; // No problem, 'foo' is replaced.

let bar = "bar1";
let bar = "bar2"; // SyntaxError: Identifier 'bar' has already been declared
ThinkingStiff
sumber
23
Ingat Anda dapat membuat blok kapan pun Anda mau. function () {code; {let inBlock = 5; } kode; };
Rata
177
Jadi, apakah tujuan membiarkan pernyataan hanya untuk membebaskan memori ketika tidak diperlukan di blok tertentu?
NoBugs
219
@NoBugs, Ya, dan dianjurkan bahwa variabel hanya ada jika diperlukan.
Batman
67
letekspresi blok let (variable declaration) statementtidak standar dan akan dihapus di masa depan, bugzilla.mozilla.org/show_bug.cgi?id=1023609 .
Gajus
19
Jadi, saya tidak bisa memikirkan kasus di mana menggunakan var ada gunanya. Bisakah seseorang memberi saya contoh situasi di mana lebih baik menggunakan var?
Luis Sieira 8-15
622

letjuga dapat digunakan untuk menghindari masalah dengan penutupan. Itu mengikat nilai segar daripada menjaga referensi lama seperti yang ditunjukkan dalam contoh di bawah ini.

for(var i=1; i<6; i++) {
  $("#div" + i).click(function () { console.log(i); });
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p>Clicking on each number will log to console:</p> 
<div id="div1">1</div>
<div id="div2">2</div>
<div id="div3">3</div>
<div id="div4">4</div>
<div id="div5">5</div>

Kode di atas menunjukkan masalah penutupan JavaScript klasik. Referensi ke ivariabel disimpan dalam penutupan penangan klik, bukan nilai aktual i.

Setiap handler klik tunggal akan merujuk ke objek yang sama karena hanya ada satu objek penghitung yang menampung 6 sehingga Anda mendapatkan enam pada setiap klik.

Solusi umum adalah untuk membungkus ini dalam fungsi anonim dan lulus isebagai argumen. Isu-isu tersebut juga dapat dihindari sekarang dengan menggunakan letbukannya varseperti yang ditunjukkan pada kode di bawah ini.

(Diuji di Chrome dan Firefox 50)

for(let i=1; i<6; i++) {
  $("#div" + i).click(function () { console.log(i); });
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p>Clicking on each number will log to console:</p> 
<div id="div1">1</div>
<div id="div2">2</div>
<div id="div3">3</div>
<div id="div4">4</div>
<div id="div5">5</div>

Gurpreet Singh
sumber
54
Itu sebenarnya keren. Saya akan mengharapkan "i" untuk didefinisikan di luar loop body berisi di dalam tanda kurung dan TIDAK membentuk "penutupan" di sekitar "i". Tentu saja contoh Anda membuktikan sebaliknya. Saya pikir ini agak membingungkan dari sudut pandang sintaksis tetapi skenario ini sangat umum sehingga masuk akal untuk mendukungnya dengan cara itu. Terima kasih banyak telah membahas ini.
Karol Kolenda
9
IE 11 mendukung let, tetapi peringatan "6" untuk semua tombol. Apakah Anda memiliki sumber yang mengatakan bagaimana letseharusnya bersikap?
Jim Hunziker
10
Sepertinya jawaban Anda adalah perilaku yang benar: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Jim Hunziker
11
Memang ini adalah perangkap umum dalam Javascript dan sekarang saya bisa melihat mengapa letakan sangat berguna. Mengatur pendengar peristiwa dalam satu lingkaran tidak lagi membutuhkan ekspresi fungsi yang segera dipanggil untuk pelingkupan lokal idi setiap iterasi.
Adrian Moisa
19
Penggunaan "biarkan" hanya mengatasi masalah ini. Jadi setiap iterasi menciptakan ruang lingkup blok independen swasta, tetapi variabel "i" masih dapat rusak oleh perubahan berikutnya dalam blok, (diberikan variabel iterator biasanya tidak berubah dalam blok, tetapi variabel biarkan lain yang dinyatakan dalam blok mungkin juga be) dan fungsi apa pun yang dideklarasikan di dalam blok dapat, ketika dipanggil, merusak nilai "i" untuk fungsi lain yang dinyatakan dalam blok karena mereka memang berbagi ruang lingkup blok pribadi yang sama sehingga referensi yang sama dengan "i".
gary
199

Apa perbedaan antara letdan var?

  • Variabel yang didefinisikan menggunakan varpernyataan dikenal di seluruh fungsi yang didefinisikan dalam, dari awal fungsi.(*)
  • Variabel yang didefinisikan menggunakan letpernyataan hanya diketahui dalam blok yang didefinisikan, sejak saat didefinisikan selanjutnya. (**)

Untuk memahami perbedaannya, pertimbangkan kode berikut:

// i IS NOT known here
// j IS NOT known here
// k IS known here, but undefined
// l IS NOT known here

function loop(arr) {
    // i IS known here, but undefined
    // j IS NOT known here
    // k IS known here, but has a value only the second time loop is called
    // l IS NOT known here

    for( var i = 0; i < arr.length; i++ ) {
        // i IS known here, and has a value
        // j IS NOT known here
        // k IS known here, but has a value only the second time loop is called
        // l IS NOT known here
    };

    // i IS known here, and has a value
    // j IS NOT known here
    // k IS known here, but has a value only the second time loop is called
    // l IS NOT known here

    for( let j = 0; j < arr.length; j++ ) {
        // i IS known here, and has a value
        // j IS known here, and has a value
        // k IS known here, but has a value only the second time loop is called
        // l IS NOT known here
    };

    // i IS known here, and has a value
    // j IS NOT known here
    // k IS known here, but has a value only the second time loop is called
    // l IS NOT known here
}

loop([1,2,3,4]);

for( var k = 0; k < arr.length; k++ ) {
    // i IS NOT known here
    // j IS NOT known here
    // k IS known here, and has a value
    // l IS NOT known here
};

for( let l = 0; l < arr.length; l++ ) {
    // i IS NOT known here
    // j IS NOT known here
    // k IS known here, and has a value
    // l IS known here, and has a value
};

loop([1,2,3,4]);

// i IS NOT known here
// j IS NOT known here
// k IS known here, and has a value
// l IS NOT known here

Di sini, kita dapat melihat bahwa variabel kita jhanya dikenal di awal untuk loop, tetapi tidak sebelum dan sesudah. Namun, variabel kamii dikenal di seluruh fungsi.

Juga, pertimbangkan bahwa variabel blok ruang tidak diketahui sebelum mereka dinyatakan karena mereka tidak diangkat. Anda juga tidak diizinkan untuk mendeklarasikan ulang variabel scoping blok yang sama dalam blok yang sama. Hal ini membuat variabel yang dicakup blok lebih rentan kesalahan daripada variabel yang dicakup secara global atau fungsional, yang diangkat dan yang tidak menghasilkan kesalahan apa pun jika terjadi beberapa deklarasi.


Apakah aman digunakan lethari ini?

Beberapa orang akan berpendapat bahwa di masa depan kita HANYA akan menggunakan pernyataan let dan pernyataan var akan menjadi usang. Guru JavaScript Kyle Simpson menulis artikel yang sangat rumit tentang mengapa ia percaya itu tidak akan terjadi .

Namun, hari ini jelas bukan itu masalahnya. Sebenarnya, kita perlu bertanya pada diri sendiri apakah aman menggunakan letpernyataan itu. Jawaban untuk pertanyaan itu tergantung pada lingkungan Anda:

  • Jika Anda menulis kode JavaScript sisi-server ( Node.js ), Anda dapat menggunakan letpernyataan dengan aman .

  • Jika Anda menulis kode JavaScript sisi klien dan menggunakan transpiler berbasis browser (seperti Traceur atau babel-standalone ), Anda dapat menggunakan letpernyataan itu dengan aman , namun kode Anda kemungkinan tidak optimal sehubungan dengan kinerja.

  • Jika Anda menulis kode JavaScript sisi klien dan menggunakan transpiler berbasis Node (seperti skrip traceur shell atau Babel ), Anda dapat menggunakan letpernyataan dengan aman . Dan karena browser Anda hanya akan tahu tentang kode yang diubahnya, kelemahan kinerja harus dibatasi.

  • Jika Anda menulis kode JavaScript sisi klien dan tidak menggunakan transpiler, Anda perlu mempertimbangkan dukungan browser.

    Masih ada beberapa browser yang tidak mendukung letsama sekali:

masukkan deskripsi gambar di sini


Bagaimana cara melacak dukungan browser

Untuk gambaran umum terkini tentang browser yang mendukung letpernyataan pada saat Anda membaca jawaban ini, lihat halaman iniCan I Use .


(*) Variabel cakupan global dan fungsional dapat diinisialisasi dan digunakan sebelum mereka dinyatakan karena variabel JavaScript diangkat .Ini berarti bahwa deklarasi selalu jauh di atas cakupan.

(**) Variabel yang dicakup blok tidak diangkat

John Slegers
sumber
14
mengenai jawaban v4: iDiketahui di mana-mana di blok fungsi! Dimulai sebagai undefined(karena mengangkat) hingga Anda menetapkan nilai! ps: letjuga diangkat (ke bagian atas blok yang berisi), tetapi akan memberikan ReferenceErrorketika direferensikan di blok sebelum tugas pertama. (ps2: Saya agak pro-titik koma tapi Anda benar-benar tidak memerlukan titik koma setelah satu blok). Yang sedang berkata, terima kasih telah menambahkan kenyataan-periksa tentang dukungan!
GitaarLAB
@GitaarLAB: Menurut Mozilla Developer Network : "Dalam ECMAScript 2015, biarkan binding tidak tunduk pada Variable Hoisting, yang berarti membiarkan deklarasi tidak bergerak ke bagian atas konteks eksekusi saat ini." - Bagaimanapun, saya membuat beberapa perbaikan pada jawaban saya yang seharusnya menjelaskan perbedaan dalam mengangkat perilaku antara letdan var!
John Slegers
1
Jawaban Anda meningkat banyak (saya teliti memeriksa). Perhatikan bahwa tautan yang sama yang Anda referensikan dalam komentar Anda juga mengatakan: "Variabel (biarkan) ada di" zona mati temporal "dari awal blok sampai inisialisasi diproses." Itu berarti bahwa 'pengidentifikasi' (string teks 'dicadangkan' untuk menunjuk ke 'sesuatu') sudah dicadangkan dalam ruang lingkup yang relevan, jika tidak maka itu akan menjadi bagian dari ruang lingkup root / host / jendela. Bagi saya pribadi, 'mengangkat' berarti tidak lebih dari mencadangkan / menghubungkan 'pengidentifikasi' yang dinyatakan dengan ruang lingkup yang relevan; tidak termasuk inisialisasi / penugasan / modifikasi mereka!
GitaarLAB
Dan .. +1 Artikel Kyle Simpson yang Anda tautkan adalah bacaan yang sangat bagus , terima kasih untuk itu! Juga jelas tentang "zona mati sementara" alias "TDZ". Satu hal menarik yang saya ingin menambahkan: Saya sudah membaca di MDN yang letdan constyang direkomendasikan hanya digunakan ketika Anda benar-benar membutuhkan fungsi tambahan mereka , karena menegakkan / memeriksa fitur tambahan (seperti write-satunya const) hasil di 'kerja yang lebih '(dan node-lingkup tambahan di pohon-lingkup) untuk mesin (saat ini) untuk menegakkan / memeriksa / memverifikasi / pengaturan.
GitaarLAB
1
Perhatikan bahwa MDN mengatakan bahwa IE TIDAK menerjemahkan dengan benar. Yang mana itu? developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Katinka Hesselink
146

Berikut penjelasan letkata kunci dengan beberapa contoh.

letbekerja sangat mirip var. Perbedaan utama adalah bahwa ruang lingkup varvariabel adalah seluruh fungsi penutup

Meja ini di Wikipedia menunjukkan browser mana yang mendukung Javascript 1.7.

Perhatikan bahwa hanya browser Mozilla dan Chrome yang mendukungnya. IE, Safari, dan yang lainnya tidak.

Ben S
sumber
5
Bit kunci teks dari dokumen yang ditautkan tampaknya adalah, "mari bekerja sangat mirip dengan var. Perbedaan utama adalah bahwa ruang lingkup variabel var adalah seluruh fungsi melampirkan".
Michael Burr
50
Meskipun secara teknis benar untuk mengatakan IE tidak mendukungnya, itu lebih benar untuk mengatakan bahwa itu hanya ekstensi mozilla.
olliej
55
@olliej, sebenarnya Mozilla ada di depan permainan. Lihat halaman 19 dari ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf
Tyler Crompton
@TylerCrompton itu hanya seperangkat kata yang telah dicadangkan selama bertahun-tahun. Ketika mozilla ditambahkan, biarkan ekstensi murni mozilla, tanpa spesifikasi terkait. ES6 harus mendefinisikan perilaku untuk pernyataan let, tetapi itu terjadi setelah mozilla memperkenalkan sintaksnya. Ingat moz juga memiliki E4X, yang sepenuhnya mati dan hanya moz.
olliej
9
IE11 menambahkan dukungan untuk let msdn.microsoft.com/en-us/library/ie/dn342892%28v=vs.85%29.aspx
eloyesp
112

Jawaban yang diterima tidak ada benarnya:

{
  let a = 123;
};

console.log(a); // ReferenceError: a is not defined
Lcf.vs
sumber
19
Jawaban yang diterima TIDAK menjelaskan hal ini dalam contohnya. Jawaban yang diterima hanya menunjukkannya dalam forpenginisialisasi loop, secara dramatis mempersempit ruang lingkup penerapan pembatasan let. Terpilih.
Jon Davis
37
@ stimpy77 Secara eksplisit menyatakan "biarkan dilingkupi ke blok penutup terdekat"; Apakah setiap cara yang bermanifestasi perlu dimasukkan?
Dave Newton
6
ada banyak contoh dan tidak ada satupun yang menunjukkan masalah ini dengan baik .. Saya mungkin telah mengangkat jawaban yang diterima dan yang ini?
Jon Davis
5
Kontribusi ini menunjukkan bahwa "blok" dapat berupa sekumpulan garis yang tertutup kurung; yaitu tidak perlu dikaitkan dengan aliran kontrol, loop, dll.
webelo
81

let

Lingkup blok

Variabel yang dideklarasikan menggunakan letkata kunci adalah blok-lingkup, yang berarti bahwa mereka hanya tersedia di blok di mana mereka dinyatakan.

Di tingkat atas (di luar fungsi)

Di tingkat atas, variabel yang dideklarasikan menggunakan lettidak membuat properti pada objek global.

var globalVariable = 42;
let blockScopedVariable = 43;

console.log(globalVariable); // 42
console.log(blockScopedVariable); // 43

console.log(this.globalVariable); // 42
console.log(this.blockScopedVariable); // undefined

Di dalam suatu fungsi

Di dalam fungsi (tetapi di luar blok), letmemiliki cakupan yang sama dengan var.

(() => {
  var functionScopedVariable = 42;
  let blockScopedVariable = 43;

  console.log(functionScopedVariable); // 42
  console.log(blockScopedVariable); // 43
})();

console.log(functionScopedVariable); // ReferenceError: functionScopedVariable is not defined
console.log(blockScopedVariable); // ReferenceError: blockScopedVariable is not defined

Di dalam blok

Variabel yang dinyatakan menggunakan letdi dalam blok tidak dapat diakses di luar blok itu.

{
  var globalVariable = 42;
  let blockScopedVariable = 43;
  console.log(globalVariable); // 42
  console.log(blockScopedVariable); // 43
}

console.log(globalVariable); // 42
console.log(blockScopedVariable); // ReferenceError: blockScopedVariable is not defined

Di dalam lingkaran

Variabel yang dideklarasikan dengan letin loop hanya dapat dirujuk di dalam loop itu.

for (var i = 0; i < 3; i++) {
  var j = i * 2;
}
console.log(i); // 3
console.log(j); // 4

for (let k = 0; k < 3; k++) {
  let l = k * 2;
}
console.log(typeof k); // undefined
console.log(typeof l); // undefined
// Trying to do console.log(k) or console.log(l) here would throw a ReferenceError.

Loop dengan penutupan

Jika Anda menggunakan letalih-alih vardalam satu lingkaran, dengan setiap iterasi Anda mendapatkan variabel baru. Itu berarti bahwa Anda dapat menggunakan penutupan di dalam lingkaran dengan aman.

// Logs 3 thrice, not what we meant.
for (var i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 0);
}

// Logs 0, 1 and 2, as expected.
for (let j = 0; j < 3; j++) {
  setTimeout(() => console.log(j), 0);
}

Zona mati temporal

Karena zona mati temporal , variabel yang dideklarasikan menggunakan lettidak dapat diakses sebelum dideklarasikan. Mencoba melakukannya akan menimbulkan kesalahan.

console.log(noTDZ); // undefined
var noTDZ = 43;
console.log(hasTDZ); // ReferenceError: hasTDZ is not defined
let hasTDZ = 42;

Tidak mendeklarasikan ulang

Anda tidak dapat mendeklarasikan variabel yang sama beberapa kali menggunakan let. Anda juga tidak bisa mendeklarasikan variabel menggunakan letdengan pengidentifikasi yang sama dengan variabel lain yang dideklarasikan menggunakan var.

var a;
var a; // Works fine.

let b;
let b; // SyntaxError: Identifier 'b' has already been declared

var c;
let c; // SyntaxError: Identifier 'c' has already been declared

const

constsangat mirip dengan let—batas-blok dan memiliki TDZ. Namun, ada dua hal yang berbeda.

Tidak ada penetapan ulang

Variabel yang dinyatakan menggunakan consttidak dapat ditugaskan kembali.

const a = 42;
a = 43; // TypeError: Assignment to constant variable.

Perhatikan bahwa itu tidak berarti bahwa nilainya tidak berubah. Sifat-sifatnya masih bisa diubah.

const obj = {};
obj.a = 42;
console.log(obj.a); // 42

Jika Anda ingin memiliki objek yang tidak dapat diubah, Anda harus menggunakannya Object.freeze().

Diperlukan inisialisasi

Anda selalu harus menentukan nilai saat mendeklarasikan variabel menggunakan const.

const a; // SyntaxError: Missing initializer in const declaration
Michał Perłakowski
sumber
51

Berikut adalah contoh untuk perbedaan antara keduanya (dukungan baru saja dimulai untuk chrome):
masukkan deskripsi gambar di sini

Seperti yang Anda lihat, var jvariabel masih memiliki nilai di luar lingkup loop (Blok Lingkup), tetapi let ivariabel tidak ditentukan di luar lingkup loop.

"use strict";
console.log("var:");
for (var j = 0; j < 2; j++) {
  console.log(j);
}

console.log(j);

console.log("let:");
for (let i = 0; i < 2; i++) {
  console.log(i);
}

console.log(i);

vlio20
sumber
2
Alat apa yang saya cari di sini?
Barton
20
Chrome devtools
vlio20
Sebagai pengembang applet desktop untuk Cinnamon, saya belum pernah terpapar oleh alat mengkilap seperti itu.
Barton
48

Ada beberapa perbedaan halus - letpelingkupan berperilaku lebih seperti pelingkupan variabel dalam kurang lebih bahasa lainnya.

mis. Ini lingkup ke blok terlampir, Mereka tidak ada sebelum mereka dinyatakan, dll.

Namun perlu dicatat bahwa letini hanya bagian dari implementasi Javascript yang lebih baru dan memiliki berbagai tingkat dukungan browser .

olliej
sumber
11
Perlu juga dicatat bahwa ECMAScript adalah standar dan lettermasuk dalam draft edisi ke - 6 dan kemungkinan besar akan berada dalam spesifikasi akhir.
Richard Ayotte
23
Itulah perbedaan yang dibuat 3 tahun: D
olliej
4
Hanya terbata-bata di pertanyaan ini dan pada tahun 2012 masih ada kasus yang hanya didukung oleh browser Mozilla let. Safari, IE, dan Chome semuanya tidak.
pseudosavant
2
Gagasan untuk secara tidak sengaja membuat lingkup blok parsial pada kecelakaan adalah poin yang baik, berhati-hatilah, lettidak mengangkat, untuk menggunakan variabel yang didefinisikan oleh yang letdidefinisikan di bagian atas blok Anda. Jika Anda memiliki ifpernyataan yang lebih dari beberapa baris kode, Anda mungkin lupa bahwa Anda tidak dapat menggunakan variabel itu sampai setelah itu ditentukan. TITIK BESAR !!!
Eric Bishard
2
@ EricB: ya dan tidak: "Dalam ECMAScript 2015, let akan mengangkat variabel ke atas blok. Namun, merujuk variabel di blok sebelum hasil deklarasi variabel dalam ReferenceError (catatan saya: bukan yang lama yang baik undefined). The variabel berada dalam 'zona mati temporal' dari awal blok hingga deklarasi diproses. " Hal yang sama berlaku untuk "beralih pernyataan karena hanya ada satu blok yang mendasarinya". Sumber: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
GitaarLAB
29

Perbedaan utama adalah perbedaan ruang lingkup , sementara mari bisa hanya tersedia di dalam lingkup yang dideklarasikan, seperti di untuk loop, var dapat diakses di luar loop misalnya. Dari dokumentasi di MDN (contoh juga dari MDN):

membiarkan memungkinkan Anda untuk mendeklarasikan variabel yang terbatas dalam ruang lingkup blok, pernyataan, atau ekspresi yang digunakan. Ini tidak seperti var kata kunci , yang mendefinisikan variabel secara global, atau secara lokal untuk seluruh fungsi terlepas dari cakupan blok.

Variabel yang dideklarasikan oleh let memiliki ruang lingkup blok di mana mereka didefinisikan, serta di setiap sub-blok yang terkandung. Dengan cara ini, biarkan bekerja seperti var . Perbedaan utama adalah bahwa ruang lingkup variabel var adalah seluruh fungsi penutup:

function varTest() {
  var x = 1;
  if (true) {
    var x = 2;  // same variable!
    console.log(x);  // 2
  }
  console.log(x);  // 2
}

function letTest() {
  let x = 1;
  if (true) {
    let x = 2;  // different variable
    console.log(x);  // 2
  }
  console.log(x);  // 1
}`

Di tingkat atas program dan fungsi, biarkan , tidak seperti var , tidak membuat properti pada objek global. Sebagai contoh:

var x = 'global';
let y = 'global';
console.log(this.x); // "global"
console.log(this.y); // undefined

Saat digunakan di dalam blok, biarkan membatasi ruang lingkup variabel untuk blok itu. Perhatikan perbedaan antara var yang ruang lingkupnya berada di dalam fungsi tempat dideklarasikan.

var a = 1;
var b = 2;

if (a === 1) {
  var a = 11; // the scope is global
  let b = 22; // the scope is inside the if-block

  console.log(a);  // 11
  console.log(b);  // 22
} 

console.log(a); // 11
console.log(b); // 2

Juga jangan lupa itu fitur ECMA6, jadi belum sepenuhnya didukung, jadi lebih baik selalu mentransmisikannya ke ECMA5 menggunakan Babel dll ... untuk info lebih lanjut tentang kunjungi situs web babel

Alireza
sumber
24
  • Variabel Tidak Mengangkat

    lettidak akan mengerek ke seluruh ruang lingkup blok tempat mereka muncul. Sebaliknya, varbisa mengerek seperti di bawah ini.

    {
       console.log(cc); // undefined. Caused by hoisting
       var cc = 23;
    }
    
    {
       console.log(bb); // ReferenceError: bb is not defined
       let bb = 23;
    }

    Sebenarnya, Per @Bergi, Keduanya vardan letsedang diangkat .

  • Pengumpulan Sampah

    Ruang lingkup blok letberguna berkaitan dengan penutupan dan pengumpulan sampah untuk merebut kembali memori. Mempertimbangkan,

    function process(data) {
        //...
    }
    
    var hugeData = { .. };
    
    process(hugeData);
    
    var btn = document.getElementById("mybutton");
    btn.addEventListener( "click", function click(evt){
        //....
    });

    The clickhandler callback tidak perlu hugeDatavariabel sama sekali. Secara teoritis, setelahprocess(..) dijalankan, struktur data yang sangat besar hugeDatabisa berupa sampah yang dikumpulkan. Namun, ada kemungkinan bahwa beberapa mesin JS masih harus mempertahankan struktur besar ini, karena clickfungsinya memiliki penutupan atas seluruh ruang lingkup.

    Namun, ruang lingkup blok dapat membuat struktur data yang sangat besar ini menjadi sampah yang dikumpulkan.

    function process(data) {
        //...
    }
    
    { // anything declared inside this block can be garbage collected
        let hugeData = { .. };
        process(hugeData);
    }
    
    var btn = document.getElementById("mybutton");
    btn.addEventListener( "click", function click(evt){
        //....
    });
  • let loop

    letdalam loop dapat mengikat kembali ke setiap iterasi dari loop, pastikan untuk menetapkan kembali nilai dari akhir iterasi loop sebelumnya. Mempertimbangkan,

    // print '5' 5 times
    for (var i = 0; i < 5; ++i) {
        setTimeout(function () {
            console.log(i);
        }, 1000);  
    }

    Namun, ganti vardenganlet

    // print 1, 2, 3, 4, 5. now
    for (let i = 0; i < 5; ++i) {
        setTimeout(function () {
            console.log(i);
        }, 1000);  
    }

    Karena letmembuat lingkungan leksikal baru dengan nama-nama untuk a) ekspresi penginisialisasi b) setiap iterasi (sebelumnya untuk mengevaluasi ekspresi kenaikan), rincian lebih lanjut ada di sini .

zangw
sumber
4
Yip mereka diangkat, tetapi berperilaku seolah-olah tidak diangkat karena Zona Drum Temporal (drum roll) - nama yang sangat dramatis untuk pengidentifikasi yang tidak dapat diakses sampai dinyatakan :-)
Drenai
Jadi biarkan diangkat, tetapi tidak tersedia? Bagaimana itu berbeda dari 'tidak diangkat'?
N-makan
Semoga Brian atau Bergi kembali untuk menjawab ini. Apakah deklarasi let diangkat, tetapi bukan penugasan? Terima kasih!
N-makan
1
@T-makan, Ini salah satu pos Bergi, mungkin Anda bisa menemukan jawabannya.
zangw
Sangat menarik bahkan disebut mengangkat ketika dibiarkan. Saya mendapatkan bahwa secara teknis mesin parsing adalah pra-menangkapnya, tetapi untuk semua maksud dan tujuan seorang programmer harus memperlakukannya seolah-olah itu tidak ada. Mengangkat var di sisi lain memiliki implikasi pada programmer.
N-makan
19

Berikut adalah contoh untuk menambahkan apa yang sudah ditulis orang lain. Misalkan Anda ingin membuat array fungsi,, di adderFunctionsmana setiap fungsi mengambil argumen Number tunggal dan mengembalikan jumlah argumen dan indeks fungsi dalam array. Mencoba menghasilkan adderFunctionsdengan loop menggunakan varkata kunci tidak akan bekerja seperti yang diharapkan orang dengan naif:

// An array of adder functions.
var adderFunctions = [];

for (var i = 0; i < 1000; i++) {
  // We want the function at index i to add the index to its argument.
  adderFunctions[i] = function(x) {
    // What is i bound to here?
    return x + i;
  };
}

var add12 = adderFunctions[12];

// Uh oh. The function is bound to i in the outer scope, which is currently 1000.
console.log(add12(8) === 20); // => false
console.log(add12(8) === 1008); // => true
console.log(i); // => 1000

// It gets worse.
i = -8;
console.log(add12(8) === 0); // => true

Proses di atas tidak menghasilkan array fungsi yang diinginkan karena iruang lingkup melampaui iterasi dari forblok di mana setiap fungsi dibuat. Sebagai gantinya, pada akhir loop, ipenutupan di setiap fungsi mengacu pada inilai di akhir loop (1000) untuk setiap fungsi anonim di adderFunctions. Ini sama sekali bukan yang kita inginkan: kita sekarang memiliki array 1000 fungsi berbeda dalam memori dengan perilaku yang persis sama. Dan jika kami selanjutnya memperbarui nilai i, mutasi akan mempengaruhi semuaadderFunctions .

Namun, kami dapat mencoba lagi menggunakan letkata kunci:

// Let's try this again.
// NOTE: We're using another ES6 keyword, const, for values that won't
// be reassigned. const and let have similar scoping behavior.
const adderFunctions = [];

for (let i = 0; i < 1000; i++) {
  // NOTE: We're using the newer arrow function syntax this time, but 
  // using the "function(x) { ..." syntax from the previous example 
  // here would not change the behavior shown.
  adderFunctions[i] = x => x + i;
}

const add12 = adderFunctions[12];

// Yay! The behavior is as expected. 
console.log(add12(8) === 20); // => true

// i's scope doesn't extend outside the for loop.
console.log(i); // => ReferenceError: i is not defined

Kali ini, irebound pada setiap iterasi forloop. Setiap fungsi sekarang menyimpan nilai ipada saat penciptaan fungsi, dan adderFunctionsberperilaku seperti yang diharapkan.

Sekarang, pencampuran gambar dua perilaku dan Anda mungkin akan melihat mengapa tidak disarankan untuk menggabungkan yang lebih baru letdan constyang lebih lama vardalam skrip yang sama. Melakukannya dapat menghasilkan kode yang membingungkan.

const doubleAdderFunctions = [];

for (var i = 0; i < 1000; i++) {
    const j = i;
    doubleAdderFunctions[i] = x => x + i + j;
}

const add18 = doubleAdderFunctions[9];
const add24 = doubleAdderFunctions[12];

// It's not fun debugging situations like this, especially when the
// code is more complex than in this example.
console.log(add18(24) === 42); // => false
console.log(add24(18) === 42); // => false
console.log(add18(24) === add24(18)); // => false
console.log(add18(24) === 2018); // => false
console.log(add24(18) === 2018); // => false
console.log(add18(24) === 1033); // => true
console.log(add24(18) === 1030); // => true

Jangan biarkan ini terjadi pada Anda. Gunakan linter.

CATATAN: Ini adalah contoh pengajaran yang dimaksudkan untuk menunjukkan var/ letperilaku dalam loop dan dengan penutupan fungsi yang juga mudah dimengerti. Ini akan menjadi cara yang mengerikan untuk menambahkan angka. Tetapi teknik umum menangkap data dalam penutupan fungsi anonim mungkin ditemui di dunia nyata dalam konteks lain. YMMV.

abroz
sumber
2
@aborz: Sintaks fungsi anonim yang sangat keren dalam contoh kedua. Hanya saja saya terbiasa dengan C #. Saya telah belajar sesuatu hari ini.
Barton
Koreksi: Secara teknis, sintaks fungsi panah dijelaskan di sini => developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Barton
3
Sebenarnya, kamu tidak perlu let value = i;. The forpernyataan menciptakan blok leksikal.
Sikat gigi
17

Perbedaannya terletak pada ruang lingkupnya variabel yang dideklarasikan dengan masing-masing.

Dalam praktiknya, ada sejumlah konsekuensi berguna dari perbedaan ruang lingkup:

  1. letvariabel hanya terlihat di blok terlampir terdekat ( { ... }).
  2. letvariabel hanya dapat digunakan dalam baris kode yang terjadi setelah variabel dideklarasikan (meskipun mereka dinaikkan !).
  3. letvariabel tidak boleh dideklarasikan ulang oleh variabel berikutnya varatau let.
  4. letVariabel global tidak ditambahkan ke windowobjek global .
  5. letvariabel mudah digunakan dengan penutupan (mereka tidak menyebabkan kondisi balapan ).

Pembatasan yang diberlakukan dengan letmengurangi visibilitas variabel dan meningkatkan kemungkinan tabrakan nama yang tidak terduga akan ditemukan lebih awal. Ini membuatnya lebih mudah untuk dilacak dan alasan tentang variabel, termasuk jangkauannya (membantu memulihkan kembali memori yang tidak digunakan).

Akibatnya, letvariabel cenderung menyebabkan masalah ketika digunakan dalam program besar atau ketika kerangka kerja yang dikembangkan secara independen dikombinasikan dengan cara-cara baru dan tidak terduga.

varmungkin masih berguna jika Anda yakin Anda ingin efek ikatan tunggal saat menggunakan penutupan dalam satu lingkaran (# 5) atau untuk mendeklarasikan variabel global yang terlihat secara eksternal dalam kode Anda (# 4). Penggunaan varuntuk ekspor dapat digantikan jikaexport bermigrasi keluar dari ruang transpiler dan ke dalam bahasa inti.

Contohnya

1. Tidak digunakan di luar blok penutup terdekat: Blok kode ini akan melempar kesalahan referensi karena penggunaan kedua xterjadi di luar blok di mana dinyatakan dengan let:

{
    let x = 1;
}
console.log(`x is ${x}`);  // ReferenceError during parsing: "x is not defined".

Sebaliknya, contoh yang sama dengan varkarya.

2. Tidak ada gunanya sebelum deklarasi:
Blok kode ini akan melempar ReferenceErrorsebelum kode dapat dijalankan karena xdigunakan sebelum dideklarasikan:

{
    x = x + 1;  // ReferenceError during parsing: "x is not defined".
    let x;
    console.log(`x is ${x}`);  // Never runs.
}

Sebaliknya, contoh yang sama dengan varmem - parsing dan menjalankan tanpa melemparkan pengecualian.

3. Tidak ada deklarasi ulang: Kode berikut menunjukkan bahwa variabel yang dideklarasikan dengan letmungkin tidak akan dideklar ulang nanti:

let x = 1;
let x = 2;  // SyntaxError: Identifier 'x' has already been declared

4. Global tidak melekat pada window:

var button = "I cause accidents because my name is too common.";
let link = "Though my name is common, I am harder to access from other JS files.";
console.log(link);  // OK
console.log(window.link);  // undefined (GOOD!)
console.log(window.button);  // OK

5. Mudah digunakan dengan penutupan: Variabel dideklarasikan dengan vartidak bekerja dengan baik dengan penutupan di dalam loop. Berikut ini adalah loop sederhana yang menampilkan urutan nilai yang dimiliki variabel ipada titik waktu yang berbeda:

for (let i = 0; i < 5; i++) {
    console.log(`i is ${i}`), 125/*ms*/);
}

Secara khusus, output ini:

i is 0
i is 1
i is 2
i is 3
i is 4

Dalam JavaScript kita sering menggunakan variabel pada waktu yang lebih lama daripada saat mereka dibuat. Ketika kami menunjukkan ini dengan menunda output dengan penutupan diteruskan ke setTimeout:

for (let i = 0; i < 5; i++) {
    setTimeout(_ => console.log(`i is ${i}`), 125/*ms*/);
}

... output tetap tidak berubah selama kita tetap dengan let. Sebaliknya, jika kita menggunakan var isebagai gantinya:

for (var i = 0; i < 5; i++) {
    setTimeout(_ => console.log(`i is ${i}`), 125/*ms*/);
}

... loop secara tak terduga menampilkan "i is 5" lima kali:

i is 5
i is 5
i is 5
i is 5
i is 5
mormegil
sumber
5
# 5 tidak disebabkan oleh kondisi balapan. Dengan menggunakan varalih-alih let, kode ini setara dengan: di var i = 0; while (i < 5) { doSomethingLater(); i++; } iluar penutupan, dan pada saat doSomethingLater()dieksekusi, itelah meningkat 5 kali, maka outputnya i is 5lima kali. Dengan menggunakan let, variabel iberada dalam penutupan, sehingga setiap panggilan async mendapatkan salinannya sendiri idaripada menggunakan 'global' yang dibuat dengan var.
Daniel T.
@DanielT.: Saya tidak berpikir transformasi mengangkat definisi variabel dari penginisialisasi loop menjelaskan apa pun. Itu hanyalah definisi normal dari semantik for. Transformasi yang lebih akurat, meskipun lebih rumit, adalah klasik for (var i = 0; i < 5; i++) { (function(j) { setTimeout(_ => console.log(i adalah $ {j} ), 125/*ms*/); })(i); }yang memperkenalkan "catatan fungsi-aktivasi" untuk menyimpan setiap nilai idengan nama jdi dalam fungsi.
mormegil
14

Semoga dua fungsi berikut menunjukkan perbedaan:

function varTest() {
    var x = 31;
    if (true) {
        var x = 71;  // Same variable!
        console.log(x);  // 71
    }
    console.log(x);  // 71
}

function letTest() {
    let x = 31;
    if (true) {
        let x = 71;  // Different variable
        console.log(x);  // 71
    }
    console.log(x);  // 31
}
Abdennour TOUMI
sumber
13

let menarik, karena memungkinkan kita untuk melakukan sesuatu seperti ini:

(() => {
    var count = 0;

    for (let i = 0; i < 2; ++i) {
        for (let i = 0; i < 2; ++i) {
            for (let i = 0; i < 2; ++i) {
                console.log(count++);
            }
        }
    }
})();

Yang menghasilkan penghitungan [0, 7].

Sedangkan

(() => {
    var count = 0;

    for (var i = 0; i < 2; ++i) {
        for (var i = 0; i < 2; ++i) {
            for (var i = 0; i < 2; ++i) {
                console.log(count++);
            }
        }
    }
})();

Hanya dihitung [0, 1].

Dmitry
sumber
2
ini adalah pertama kalinya saya pernah melihat seseorang bertindak seperti variabel shadowing diinginkan. tidak, tujuan let tidak untuk memungkinkan pembayangan
John Haugeland
1
tujuan? itu adalah konstruksi, Anda dapat menggunakannya sesuka Anda, salah satu cara yang menarik adalah seperti ini.
Dmitry
13

Fungsi VS blok ruang lingkup:

Perbedaan utama antara vardan letadalah bahwa variabel yang dideklarasikan dengan varadalah scoped fungsi . Sedangkan fungsi yang dideklarasikan dengan letadalah blok scoped . Sebagai contoh:

function testVar () {
  if(true) {
    var foo = 'foo';
  }

  console.log(foo);
}

testVar();  
// logs 'foo'


function testLet () {
  if(true) {
    let bar = 'bar';
  }

  console.log(bar);
}

testLet(); 
// reference error
// bar is scoped to the block of the if statement 

variabel dengan var:

Ketika fungsi pertama testVardipanggil variabel foo, dideklarasikan dengan var, masih dapat diakses di luar ifpernyataan. Variabel ini fooakan tersedia di mana - mana dalam lingkup testVar fungsi .

variabel dengan let:

Ketika fungsi kedua testLetdipanggil sebagai bilah variabel, dideklarasikan dengan let, hanya dapat diakses di dalam ifpernyataan. Karena variabel yang dideklarasikan dengan letyang blok scoped (di mana blok adalah kode antara kurung keriting misalnya if{}, for{}, function{}).

let variabel tidak diangkat:

Perbedaan lain antara vardan letadalah variabel-variabel dengan yang dideklarasikan dengan let tidak mendapatkan dukungan . Contoh adalah cara terbaik untuk menggambarkan perilaku ini:

variabel dengan let jangan diangkat:

console.log(letVar);

let letVar = 10;
// referenceError, the variable doesn't get hoisted

variabel dengan var do hoisted:

console.log(varVar);

var varVar = 10;
// logs undefined, the variable gets hoisted

Global lettidak terikat pada window:

Variabel dideklarasikan dengan letdalam lingkup global (yang merupakan kode yang tidak ada dalam suatu fungsi) tidak ditambahkan sebagai properti pada windowobjek global . Misalnya (kode ini dalam lingkup global):

var bar = 5;
let foo  = 10;

console.log(bar); // logs 5
console.log(foo); // logs 10

console.log(window.bar);  
// logs 5, variable added to window object

console.log(window.foo);
// logs undefined, variable not added to window object


Kapan sebaiknya letdigunakan var?

Gunakan letlebih dari varkapan pun Anda bisa karena itu hanya mencakup lebih spesifik. Ini mengurangi potensi konflik penamaan yang dapat terjadi ketika berhadapan dengan sejumlah besar variabel. vardapat digunakan ketika Anda ingin variabel global secara eksplisit berada di windowobjek (selalu pertimbangkan dengan hati-hati jika ini benar-benar diperlukan).

Willem van der Veen
sumber
9

Tampaknya juga, setidaknya dalam Visual Studio 2015, TypeScript 1.5, "var" memungkinkan beberapa deklarasi dari nama variabel yang sama dalam sebuah blok, dan "let" tidak.

Ini tidak akan menghasilkan kesalahan kompilasi:

var x = 1;
var x = 2;

Ini akan:

let x = 1;
let x = 2;
RDoc
sumber
9

var adalah variabel lingkup global (mampu-hoist).

letdan construang lingkup blok.

test.js

{
    let l = 'let';
    const c = 'const';
    var v = 'var';
    v2 = 'var 2';
}

console.log(v, this.v);
console.log(v2, this.v2);
console.log(l); // ReferenceError: l is not defined
console.log(c); // ReferenceError: c is not defined

Muslim Shahsavan
sumber
8

Ketika menggunakan let

Kata letkunci melampirkan deklarasi variabel ke ruang lingkup blok apa pun (umumnya { .. }pasangan) yang terkandung di dalamnya. Dengan kata lain, letsecara implisit membajak ruang lingkup blok apa pun untuk deklarasi variabelnya.

letvariabel tidak dapat diakses di windowobjek karena mereka tidak dapat diakses secara global.

function a(){
    { // this is the Max Scope for let variable
        let x = 12;
    }
    console.log(x);
}
a(); // Uncaught ReferenceError: x is not defined

Ketika menggunakan var

var dan variabel dalam ES5 memiliki cakupan fungsi yang berarti variabel tersebut valid di dalam fungsi dan tidak di luar fungsi itu sendiri.

varvariabel dapat diakses di windowobjek karena mereka tidak dapat diakses secara global.

function a(){ // this is the Max Scope for var variable
    { 
        var x = 12;
    }
    console.log(x);
}
a(); // 12

Jika Anda ingin tahu lebih lanjut, baca terus di bawah ini

salah satu pertanyaan wawancara paling terkenal tentang ruang lingkup juga dapat mencukupi penggunaan tepat letdan varseperti di bawah ini;

Ketika menggunakan let

for (let i = 0; i < 10 ; i++) {
    setTimeout(
        function a() {
            console.log(i); //print 0 to 9, that is literally AWW!!!
        }, 
        100 * i);
}

Ini karena ketika menggunakan let, untuk setiap iterasi loop variabel dicakup dan memiliki salinannya sendiri.

Ketika menggunakan var

for (var i = 0; i < 10 ; i++) {
    setTimeout(
        function a() {
            console.log(i); //print 10 times 10
        }, 
        100 * i);
}

Ini karena ketika menggunakan var, untuk setiap iterasi loop variabel dicakup dan telah berbagi salinan.

Ankur Soni
sumber
8

Dalam kebanyakan istilah dasar,

for (let i = 0; i < 5; i++) {
  // i accessible ✔️
}
// i not accessible ❌

for (var i = 0; i < 5; i++) {
  // i accessible ✔️
}
// i accessible ✔️

⚡️ Sandbox untuk bermain-main ↓

Edit let vs var

Hasan Sefa Ozalp
sumber
7

Jika saya membaca spesifikasi dengan benar maka let untungnya juga dapat dimanfaatkan untuk menghindari fungsi yang digunakan sendiri untuk mensimulasikan anggota pribadi saja - pola desain populer yang mengurangi pembacaan kode, menyulitkan debugging, yang tidak menambahkan perlindungan kode nyata atau manfaat lainnya - kecuali mungkin memuaskan seseorang keinginan untuk semantik, jadi berhentilah menggunakannya. / kata-kata kasar

var SomeConstructor;

{
    let privateScope = {};

    SomeConstructor = function SomeConstructor () {
        this.someProperty = "foo";
        privateScope.hiddenProperty = "bar";
    }

    SomeConstructor.prototype.showPublic = function () {
        console.log(this.someProperty); // foo
    }

    SomeConstructor.prototype.showPrivate = function () {
        console.log(privateScope.hiddenProperty); // bar
    }

}

var myInstance = new SomeConstructor();

myInstance.showPublic();
myInstance.showPrivate();

console.log(privateScope.hiddenProperty); // error

Lihat ' Mengemulasi antarmuka pribadi '

Daniel Sokolowski
sumber
Bisakah Anda menguraikan bagaimana Ekspresi Fungsi yang Segera Diminta tidak menyediakan "perlindungan kode" dan lettidak? (Saya anggap Anda maksud IIFE dengan "fungsi memohon sendiri".)
Robert Siemer
Dan mengapa Anda mengatur hiddenPropertykonstruktor? Hanya ada satu hiddenPropertyuntuk semua instance di "kelas" Anda.
Robert Siemer
4

Beberapa peretasan dengan let:

1.

    let statistics = [16, 170, 10];
    let [age, height, grade] = statistics;

    console.log(height)

2.

    let x = 120,
    y = 12;
    [x, y] = [y, x];
    console.log(`x: ${x} y: ${y}`);

3.

    let node = {
                   type: "Identifier",
                   name: "foo"
               };

    let { type, name, value } = node;

    console.log(type);      // "Identifier"
    console.log(name);      // "foo"
    console.log(value);     // undefined

    let node = {
        type: "Identifier"
    };

    let { type: localType, name: localName = "bar" } = node;

    console.log(localType);     // "Identifier"
    console.log(localName);     // "bar"

Getter dan setter dengan let:

let jar = {
    numberOfCookies: 10,
    get cookies() {
        return this.numberOfCookies;
    },
    set cookies(value) {
        this.numberOfCookies = value;
    }
};

console.log(jar.cookies)
jar.cookies = 7;

console.log(jar.cookies)
zloctb
sumber
tolong apa artinya ini let { type, name, value } = node;? Anda membuat objek baru dengan 3 tipe properti / nama / nilai dan menginisialisasinya dengan nilai properti dari node?
AlainIb
Dalam contoh 3 Anda mendeklarasikan ulang simpul yang menyebabkan pengecualian. Semua contoh ini juga berfungsi dengan baik var.
Rehan Haider
4

biarkan vs var. Ini semua tentang ruang lingkup .

variabel var bersifat global dan pada dasarnya dapat diakses di mana-mana, sementara variabel tidak bersifat global dan hanya ada sampai tanda kurung tutup membunuhnya.

Lihat contoh saya di bawah ini, dan perhatikan bagaimana variabel singa (biarkan) bertindak berbeda di dua console.logs; itu menjadi di luar ruang lingkup di console.log 2.

var cat = "cat";
let dog = "dog";

var animals = () => {
    var giraffe = "giraffe";
    let lion = "lion";

    console.log(cat);  //will print 'cat'.
    console.log(dog);  //will print 'dog', because dog was declared outside this function (like var cat).

    console.log(giraffe); //will print 'giraffe'.
    console.log(lion); //will print 'lion', as lion is within scope.
}

console.log(giraffe); //will print 'giraffe', as giraffe is a global variable (var).
console.log(lion); //will print UNDEFINED, as lion is a 'let' variable and is now out of scope.
daCoda
sumber
4

ES6 memperkenalkan dua kata kunci baru ( biarkan dan const ) sebagai pengganti var .

Ketika Anda membutuhkan deselerasi level blok, Anda bisa menggunakan let dan const sebagai ganti var.

Tabel di bawah ini merangkum perbedaan antara var, let dan const

masukkan deskripsi gambar di sini

Srikrushna
sumber
3

biarkan adalah bagian dari es6. Fungsi-fungsi ini akan menjelaskan perbedaannya dengan cara yang mudah.

function varTest() {
  var x = 1;
  if (true) {
    var x = 2;  // same variable!
    console.log(x);  // 2
  }
  console.log(x);  // 2
}

function letTest() {
  let x = 1;
  if (true) {
    let x = 2;  // different variable
    console.log(x);  // 2
  }
  console.log(x);  // 1
}
vipul jain
sumber
3

Di bawah ini menunjukkan perbedaan 'let' dan 'var' dalam cakupan:

let gfoo = 123;
if (true) {
    let gfoo = 456;
}
console.log(gfoo); // 123

var hfoo = 123;
if (true) {
    var hfoo = 456;
}
console.log(hfoo); // 456

The gfoo, yang didefinisikan oleh letawalnya adalah di lingkup global , dan ketika kita mendeklarasikan gfoolagi di dalam if clausenya lingkup berubah dan ketika nilai baru ditugaskan untuk variabel dalam lingkup yang tidak mempengaruhi lingkup global.

Sedangkan hfoo, yang didefinisikan oleh varawalnya dalam lingkup global , tetapi sekali lagi ketika kami mendeklarasikannya di dalam if clause, itu menganggap lingkup global hfoo, meskipun var telah digunakan lagi untuk mendeklarasikannya. Dan ketika kita menetapkan ulang nilainya, kita melihat bahwa ruang lingkup global hfoo juga terpengaruh. Inilah perbedaan utama.

Piklu Dey
sumber
2

Seperti disebutkan di atas:

Perbedaannya adalah pelingkupan. vardilingkupi ke blok fungsi terdekat dan letdilingkupi ke blok penutup terdekat , yang bisa lebih kecil dari blok fungsi. Keduanya bersifat global jika di luar blok apa pun. Mari kita lihat sebuah contoh:

Contoh 1:

Dalam kedua contoh saya, saya memiliki fungsi myfunc. myfuncberisi variabel myvarsama dengan 10. Dalam contoh pertama saya, saya memeriksa apakah myvarsama dengan 10 ( myvar==10). Jika ya, saya agian mendeklarasikan variabel myvar(sekarang saya memiliki dua variabel myvar) menggunakan varkata kunci dan menetapkannya nilai baru (20). Pada baris berikutnya saya mencetak nilainya di konsol saya. Setelah blok bersyarat saya kembali mencetak nilai myvarpada konsol saya. Jika Anda melihat output dari myfunc, myvarmemiliki nilai sama dengan 20.

biarkan kata kunci

Contoh2: Dalam contoh kedua saya alih-alih menggunakan varkata kunci di blok bersyarat saya menyatakan myvarmenggunakan letkata kunci. Sekarang ketika saya menelepon myfunc saya mendapatkan dua output yang berbeda: myvar=20dan myvar=10.

Jadi perbedaannya sangat sederhana yaitu cakupannya.

N Randhawa
sumber
3
Tolong jangan memposting gambar kode, itu dianggap praktik buruk pada SO karena tidak akan dapat dicari untuk pengguna masa depan (serta masalah aksesibilitas). Selain itu, jawaban ini tidak menambahkan apa pun yang belum dijawab oleh jawaban lain.
inostia
2

Saya ingin menautkan kata kunci ini ke Konteks Eksekusi, karena Konteks Eksekusi penting dalam semua ini. Konteks Eksekusi memiliki dua fase: Fase Penciptaan dan Fase Eksekusi. Selain itu, setiap Konteks Eksekusi memiliki Lingkungan Variabel dan Lingkungan Luar (Lingkungan Leksikalalnya).

Selama Fase Pembuatan Konteks Eksekusi, var, let dan const masih akan menyimpan variabelnya dalam memori dengan nilai yang tidak ditentukan dalam Lingkungan Variabel dari Konteks Eksekusi yang diberikan. Perbedaannya ada pada Tahap Eksekusi. Jika Anda menggunakan referensi variabel yang didefinisikan dengan var sebelum diberi nilai, itu hanya akan tidak ditentukan. Tidak ada pengecualian akan dimunculkan.

Namun, Anda tidak dapat mereferensi variabel yang dideklarasikan dengan let atau const hingga dinyatakan. Jika Anda mencoba menggunakannya sebelum diumumkan, maka pengecualian akan dimunculkan selama Fase Eksekusi dari Konteks Eksekusi. Sekarang variabel masih akan berada dalam memori, milik Fase Penciptaan Konteks Eksekusi, tetapi Mesin tidak akan memungkinkan Anda untuk menggunakannya:

function a(){
    b;
    let b;
}
a();
> Uncaught ReferenceError: b is not defined

Dengan variabel yang didefinisikan dengan var, jika Mesin tidak dapat menemukan variabel dalam Lingkungan Variabel Konteks Eksekusi saat ini, maka itu akan naik rantai lingkup (Lingkungan Luar) dan memeriksa Lingkungan Variabel Lingkungan Luar untuk variabel. Jika tidak dapat menemukannya di sana, ia akan terus mencari Rantai Lingkup. Ini tidak terjadi dengan let dan const.

Fitur kedua let adalah ia memperkenalkan ruang lingkup blok. Blok didefinisikan oleh kurung kurawal. Contohnya termasuk blok fungsi, jika blok, untuk blok, dll. Ketika Anda mendeklarasikan variabel dengan membiarkan bagian dalam blok, variabel hanya tersedia di dalam blok. Bahkan, setiap kali blok dijalankan, seperti di dalam for loop, itu akan membuat variabel baru di memori.

ES6 juga memperkenalkan kata kunci const untuk mendeklarasikan variabel. const juga blok scoped. Perbedaan antara let dan const adalah bahwa variabel const perlu dideklarasikan menggunakan penginisialisasi, atau itu akan menghasilkan kesalahan.

Dan, akhirnya, ketika sampai pada Konteks Eksekusi, variabel yang didefinisikan dengan var akan dilampirkan ke objek 'ini'. Dalam Konteks Eksekusi global, itu akan menjadi objek jendela di browser. Ini bukan kasus untuk let atau const.

Donato
sumber
2

Saya pikir istilah dan sebagian besar contohnya agak luar biasa, Masalah utama yang saya miliki secara pribadi dengan perbedaannya adalah memahami apa itu "Block". Pada titik yang saya sadari, sebuah blok akan berupa kurung keriting kecuali IFpernyataan. braket pembuka {dari suatu fungsi atau loop akan menentukan blok baru, apa pun yang didefinisikan letdi dalamnya, tidak akan tersedia setelah braket penutup }dari hal yang sama (fungsi atau loop); Dengan mengingat hal itu, lebih mudah untuk dipahami:

let msg = "Hello World";

function doWork() { // msg will be available since it was defined above this opening bracket!
  let friends = 0;
  console.log(msg);

  // with VAR though:
  for (var iCount2 = 0; iCount2 < 5; iCount2++) {} // iCount2 will be available after this closing bracket!
  console.log(iCount2);
  
    for (let iCount1 = 0; iCount1 < 5; iCount1++) {} // iCount1 will not be available behind this closing bracket, it will return undefined
  console.log(iCount1);
  
} // friends will no be available after this closing bracket!
doWork();
console.log(friends);

Demensik
sumber
1

Sekarang saya pikir ada pelingkupan variabel yang lebih baik ke blok pernyataan menggunakan let:

function printnums()
{
    // i is not accessible here
    for(let i = 0; i <10; i+=)
    {
       console.log(i);
    }
    // i is not accessible here

    // j is accessible here
    for(var j = 0; j <10; j++)
    {
       console.log(j);
    }
    // j is accessible here
}

Saya pikir orang akan mulai menggunakan biarkan di sini setelah sehingga mereka akan memiliki ruang lingkup yang sama dalam JavaScript seperti bahasa lain, Java, C #, dll.

Orang-orang yang tidak memiliki pemahaman yang jelas tentang pelingkupan dalam JavaScript digunakan untuk melakukan kesalahan sebelumnya.

Mengangkat tidak didukung menggunakan let.

Dengan pendekatan ini kesalahan yang ada dalam JavaScript semakin dihapus.

Lihat ES6 Dalam Kedalaman: biarkan dan const untuk memahaminya dengan lebih baik.

swaraj patil
sumber
Untuk pemahaman mendalam tentang hal itu lihat tautan - davidwalsh.name/for-and-against-let
swaraj patil
1

Artikel ini dengan jelas mendefinisikan perbedaan antara var, let dan const

const adalah sinyal bahwa pengidentifikasi tidak akan dipindahkan.

let, adalah sinyal bahwa variabel dapat dipindahkan, seperti penghitung dalam satu lingkaran, atau pertukaran nilai dalam suatu algoritma. Ini juga menandakan bahwa variabel hanya akan digunakan di blok yang telah ditentukan, yang tidak selalu merupakan seluruh fungsi yang mengandung.

varsekarang sinyal terlemah yang tersedia saat Anda mendefinisikan variabel dalam JavaScript. Variabel mungkin atau mungkin tidak dipindahkan, dan variabel mungkin atau mungkin tidak digunakan untuk seluruh fungsi, atau hanya untuk tujuan blok atau loop.

https://medium.com/javascript-scene/javascript-es6-var-let-or-const-ba58b8dcde75#.esmkpbg9b

anandharshan
sumber