“Let” ve “var” kullanmak arasındaki fark nedir?


4540

ECMAScript 6 tanıtıldı deyimi .let

"Yerel" bir değişken olarak tanımlandığını duydum, ancak yine de varanahtar kelimeden nasıl farklı davrandığından emin değilim .

Farklılıklar nedir? Ne zaman letkullanılmalıdır var?


104
ECMAScript standarttır ve 6. baskı taslağınalet dahil edilmiştir ve büyük olasılıkla nihai spesifikasyonda olacaktır.
Richard Ayotte

5
ES6 özelliklerinin güncel destek matrisi (let dahil) için kangax.github.io/es5-compat-table/es6 adresine bakın . Firefox, Chrome ve IE11'i yazarken hepsi destekliyor (her ne kadar FF uygulamasının oldukça standart olmadığına inanıyorum).
Nico Burns

22
Uzun bir süre için bir for döngüsünde vars'ların sarıldığı işleve dahil edildiğini bilmiyordum. Bunu ilk kez anladığımı hatırlıyorum ve çok aptalca olduğunu düşündüm. Şimdi ikisinin farklı nedenlerle nasıl kullanılabileceğini ve bazı durumlarda bir for döngüsünde bir var'ı nasıl kullanmak isteyebileceğinizi ve bloğa dahil olamayacağını bilerek biraz güç görüyorum.
Eric Bishard

1
Bu çok iyi bir okuma wesbos.com/javascript-scoping
onmyway133

1
Burada iyi açıklanmış cevap stackoverflow.com/a/43994458/5043867
Pardeep Jain

Yanıtlar:


6099

Kapsam belirleme kuralları

Temel fark, kapsam belirleme kurallarıdır. varAnahtar kelime tarafından bildirilen değişkenler , hemen işlev gövdesine (dolayısıyla işlev kapsamına), letdeğişkenler ise hemen gösterilen kapalı bloğa { }(dolayısıyla blok kapsamına) dahil edilir.

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

  console.log(foo, bar);

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

  console.log(baz); // ReferenceError
}

run();

letAnahtar kelimenin dile tanıtılmasının nedeni işlev kapsamı kafa karıştırıcıydı ve JavaScript'teki ana hata kaynaklarından biriydi.

Bu örneğe başka bir yığın akışı sorusundan göz atın :

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: 3funcs[j]();anonim işlevler aynı değişkene bağlı olduğu için her seferinde konsola çıktı .

İnsanlar döngülerden doğru değeri yakalamak için hemen çağrılan işlevler oluşturmak zorundaydılar, ancak bu da kıllıydı.

kaldırma

varAnahtar kelime ile bildirilen değişkenler kaldırılırken ( undefinedkod çalıştırılmadan önce başlatılır ), bu, bildirilmeden önce bile kapalı kapsamlarında erişilebilir oldukları anlamına gelir:

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

run();

lettanımları değerlendirilene kadar değişkenler başlatılmaz. Başlatmadan önce bunlara erişmek a ReferenceError. Değişkenin, blok başlangıcından başlatma işlemine kadar "geçici ölü bölgede" olduğu söylenir.

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

checkHoisting();

Global nesne özelliği oluşturma

Üst düzeyde, letaksine var, genel nesne üzerinde bir özellik oluşturmaz:

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

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

yeniden bildirilmiş

Katı modda, SyntaxError'ı yükseltirken varaynı değişkeni aynı kapsamda yeniden bildirmenize izin verir let.

'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

23
İstediğiniz zaman blok oluşturabileceğinizi unutmayın. function () {kod; {let inBlock = 5; } kod; };
ortalama Joe

177
Öyleyse izin ifadelerinin amacı sadece belirli bir blokta gerekli olmadığında hafızayı boşaltmak mı?
NoBugs

219
@NoBugs, Yes ve değişkenlerin sadece ihtiyaç duyuldukları yerde mevcut olması teşvik edilir.
batman

67
letblok ifadesi let (variable declaration) statementstandart değildir ve gelecekte kaldırılacaktır, bugzilla.mozilla.org/show_bug.cgi?id=1023609 .
Aralık'ta Gajus

19
Yani, var kullanmanın herhangi bir kullanımının olduğu herhangi bir durumu düşünemiyorum. Birisi bana var kullanmanın tercih edildiği bir durum örneği verebilir mi?
Luis Sieira

622

letkapaklarla ilgili sorunları önlemek için de kullanılabilir. Aşağıdaki örneklerde gösterildiği gibi eski bir referans tutmak yerine yeni bir değer bağlar.

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>

Yukarıdaki kod, klasik bir JavaScript kapatma sorunu olduğunu gösterir. iDeğişkene yapılan referans , gerçek değeri yerine tıklama işleyici kapatmasında saklanıyor i.

Her bir tıklama işleyicisi aynı nesneye atıfta bulunacaktır, çünkü her bir tıklamada altı tane alacak şekilde 6 tutan tek bir sayaç nesnesi vardır.

Genel bir çözüm, bunu anonim bir işleve sarmak ve iargüman olarak iletmektir. Bu konular da kullanarak artık önlenebilir letyerine varaşağıda kodda gösterildiği.

(Chrome ve Firefox 50'de test edilmiştir)

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>


54
Bu gerçekten harika. Ben döngü gövdesi parantez içinde içerir dışında ve "i" etrafında bir "kapatma" OLUŞTURMAK için "i" beklenir.Tabii ki örnek aksi kanıtlar. Ben sözdizimi açısından biraz kafa karıştırıcı olduğunu düşünüyorum ama bu senaryo o kadar yaygın ki bu şekilde desteklemek mantıklı. Bunu getirdiğin için çok teşekkürler.
Karol Kolenda

9
IE 11 destekler let, ancak tüm düğmeler için "6" uyarısı verir. Nasıl letdavranması gerektiğini söyleyen bir kaynağınız var mı?
Jim Hunziker

10
Cevabınız doğru davranış gibi görünüyor: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Jim Hunziker

11
Gerçekten bu Javascript ortak bir tuzak olduğunu ve şimdi neden letgerçekten yararlı olacağını görebilirsiniz . Olay dinleyicilerini bir döngüde ayarlamak artık iher yinelemede yerel olarak kapsam oluşturmak için hemen çağrılan bir işlev ifadesi gerektirmez .
Adrian Moisa

19
"Let" kullanımı sadece bu sorunu çözer. Bu nedenle, her yineleme özel bağımsız bir blok kapsamı oluşturur, ancak "i" değişkeni bloktaki sonraki değişikliklerle yine de bozulabilir (yineleyici değişkeni genellikle blok içinde değiştirilmez, ancak blok içindeki bildirilen diğer izin değişkenleri iyi olabilir onlar çünkü olması) ve her türlü fonksiyon bloğu kutu içinde bildirilen, çağrıldığında, bozuk değer "i" diğer fonksiyonlar için blok içinde beyan do "i" için pay dolayısıyla aynı özel blok kapsamını aynı referans.
gary

199

Arasındaki fark nedir letve var?

  • İfade kullanılarak tanımlanan bir değişken, tanımlandığı fonksiyonvar boyunca , fonksiyonun başlangıcından itibaren bilinir . (*)
  • Bir ifade kullanılarak tanımlanan bir değişken let, sadece tanımlandığı blokta , tanımlandığı andan itibaren bilinir . (**)

Farkı anlamak için aşağıdaki kodu göz önünde bulundurun:

// 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

Burada, değişkenimizin jsadece döngü için ilkinde bilindiğini görüyoruz , ancak önce ve sonra değil. Ancak değişkenimiz itüm fonksiyonda bilinir.

Ayrıca, blok kapsamındaki değişkenlerin, kaldırılmadıkları için bildirilmeden önce bilinmediğini düşünün. Aynı blok kapsamındaki değişkeni aynı blok içinde yeniden bildirmenize de izin verilmez. Bu, blok kapsamındaki değişkenleri, genel veya işlevsel kapsamdaki değişkenlerden daha az hataya eğilimli hale getirir, bu da kaldırılır ve birden fazla bildirim olması durumunda hata üretmez.


letBugün kullanmak güvenli mi?

Bazı insanlar ileride YALNIZCA izin ifadeleri kullanacağımızı ve var ifadelerinin kullanılmayacağını iddia edecektir. JavaScript gurusu Kyle Simpson neden böyle olmayacağına inandığı hakkında çok ayrıntılı bir makale yazdı .

Ancak bugün kesinlikle durum böyle değil. Aslında, letifadeyi kullanmanın güvenli olup olmadığını kendimize sormalıyız . Bu sorunun cevabı ortamınıza bağlıdır:

  • Sunucu tarafı JavaScript kodu ( Node.js ) yazıyorsanız, letifadeyi güvenle kullanabilirsiniz .

  • İstemci tarafı JavaScript kodu yazıyorsanız ve tarayıcı tabanlı bir transpiler ( Traceur veya babel-bağımsız gibi ) kullanıyorsanız, letifadeyi güvenle kullanabilirsiniz , ancak kodunuz performans açısından en uygun şey olabilir.

  • İstemci tarafı JavaScript kodu yazıyorsanız ve Düğüm tabanlı bir transpiler ( traceur shell betiği veya Babel gibi ) kullanıyorsanız, letifadeyi güvenle kullanabilirsiniz . Ve tarayıcınız sadece aktarılan kodu bileceğinden, performans dezavantajları sınırlı olmalıdır.

  • İstemci tarafı JavaScript kodu yazıyorsanız ve bir aktarıcı kullanmıyorsanız tarayıcı desteğini göz önünde bulundurmanız gerekir.

    Hala hiç desteklemeyen bazı tarayıcılar var let:

resim açıklamasını buraya girin


Tarayıcı desteğini takip etme

letBu yanıtı okurken hangi tarayıcıların ifadeyi desteklediğine dair güncel bir genel bakış için bu Can I Usesayfaya bakın .


(*) Genel ve işlevsel kapsamdaki değişkenler, JavaScript değişkenleri kaldırıldığı için bildirilmeden önce başlatılabilir ve kullanılabilir . Bu, beyanların her zaman kapsamın en üstünde olduğu anlamına gelir.

(**) Blok kapsamındaki değişkenler kaldırılmamıştır


14
v4 cevabı ile ilgili: iFonksiyon bloğundaki her yerde biliniyor! undefinedSiz bir değer atayana kadar (kaldırma nedeniyle) olarak başlar ! ps: letayrıca (içerdiği bloğun üstüne) kaldırılır, ancak ReferenceErrorilk atamadan önce blokta referans verildiğinde bir zaman verir . (ps2: Ben noktalı virgül yanlısı bir adamım ama gerçekten bir bloktan sonra noktalı virgül kullanmanıza gerek yok). Bununla birlikte, destekle ilgili gerçeklik kontrolünü eklediğiniz için teşekkürler!
GitaarLAB

@GitaarLAB: Mozilla Geliştirici Ağı'na göre : "ECMAScript 2015'te, izinler Değişken Kaldırma'ya tabi değildir, bu da bildirimlerin geçerli yürütme bağlamının en üstüne taşınmamasına izin verir." - Her neyse, cevabımda, letve arasındaki kaldırma davranışındaki farkı açıklığa kavuşturacak birkaç iyileştirme yaptım var.
John Slegers

1
Cevabınız çok gelişti (iyice kontrol ettim). Yorumunuzda referans verdiğiniz aynı bağlantının da şunları söylediğini unutmayın: "(let) değişkeni, başlatma işlemine kadar bloğun başlangıcından itibaren" geçici ölü bölgede " . Bu, 'tanımlayıcının' ('bir şeyi' işaret etmek için 'ayrılmış' metin dizesi) zaten ilgili kapsamda ayrıldığı, aksi takdirde kök / ana bilgisayar / pencere kapsamının bir parçası olacağı anlamına gelir. Şahsen benim için 'kaldırma', beyan edilen 'tanımlayıcıları' ilgili kapsamlarına ayırmak / bağlamaktan başka bir şey ifade etmez; başlatma / atama / değiştirilebilirlik hariç!
GitaarLAB

Ve .. + 1. Bağladığınız Kyle Simpson makalesi mükemmel bir okuma, bunun için teşekkürler! “Zamansal ölü bölge”, yani “TDZ” hakkında da açıktır. Bir ilginç şey eklemek istiyorum: Ben MDN'yi okumak ettik letve constalındı aslında onların ek işlevler gerektiğinde tek kullanım için tavsiye , 'daha çalışmalarında sonuç (salt const gibi) bu ekstra özellikler / zorlama kontrol çünkü '(ve kapsam ağacındaki ek kapsam düğümleri) için (mevcut) motor (lar) ın zorlanması / kontrol edilmesi / doğrulanması / ayarlanması.
GitaarLAB

1
MDN, IE DOES izin doğru yorumlamak söyledi. Hangisi? developer.mozilla.org/tr-TR/docs/Web/JavaScript/Reference/…
Katinka Hesselink

146

İşte bazı örneklerle anahtar kelimenin açıklamasılet .

letçok benzer şekilde çalışır var. Temel fark, bir vardeğişkenin kapsamının tüm çevreleme işlevi olmasıdır

Wikipedia'daki bu tablo , hangi tarayıcıların Javascript 1.7'yi desteklediğini gösterir.

Yalnızca Mozilla ve Chrome tarayıcılarının desteklediğini unutmayın. IE, Safari ve potansiyel olarak diğerleri değil.


5
Bağlantılı belgedeki metnin anahtar biti, "izin çok var gibi çalışır. Ana fark, bir var değişkeninin kapsamının tüm kapatma işlevi olmasıdır" gibi görünüyor.
Michael Burr

50
IE'nin desteklemediğini söylemek teknik olarak doğru olsa da, bunun yalnızca mozilla uzantısı olduğunu söylemek daha doğru.
olliej

55
@olliej, aslında Mozilla oyunun hemen önündedir. Ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf
Tyler Crompton

@TylerCrompton, bu sadece yıllarca ayrılmış kelimeler kümesidir. Mozilla eklendiğinde, hiçbir ilgili spesifikasyonu olmayan tamamen bir mozilla uzantısı olmasına izin verin. ES6, let ifadelerine yönelik davranışı tanımlamalıdır, ancak mozilla sözdizimini tanıttıktan sonra ortaya çıktı. Moz'un ayrıca tamamen ölü ve sadece moz olan E4X'e sahip olduğunu unutmayın.
olliej


112

Kabul edilen cevapta bir nokta eksik:

{
  let a = 123;
};

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

19
Kabul edilen cevap, örneğinde bu hususu açıklamamaktadır. Kabul edilen cevap, sadece bir fordöngü başlatıcısında gösterdi ve sınırlamalarının uygulama kapsamını önemli ölçüde daralttı let. Upvoted.
Jon Davis

37
@ stimpy77 Açıkça "en yakın çevreleyen bloğa dahil edilsin"; tezahür eden her yolun dahil edilmesi gerekiyor mu?
Dave Newton

6
birçok örnek vardı ve hiçbiri konuyu doğru bir şekilde göstermedi .. Hem kabul edilen yanıtı hem de bu cevabı iptal etmiş olabilir miyim?
Jon Davis

5
Bu katkı bir "bloğun" basitçe parantez içine alınmış bir dizi çizgi olabileceğini göstermektedir; yani herhangi bir kontrol akışı, döngü, vb. ile ilişkilendirilmesine gerek yoktur
webelo

81

let

Blok kapsamı

letAnahtar kelime kullanılarak bildirilen değişkenler blok kapsamlıdır, yani yalnızca bildirildikleri blokta kullanılabilirler .

Üst seviyede (bir fonksiyonun dışında)

En üst düzeyde, kullanılarak bildirilen değişkenler letgenel nesne üzerinde özellik oluşturmaz.

var globalVariable = 42;
let blockScopedVariable = 43;

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

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

Bir fonksiyonun içinde

Bir işlevin içinde (ancak bir bloğun dışında), letile aynı kapsama sahiptir 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

Bir bloğun içinde

letBir bloğun içinde kullanıldığı bildirilen değişkenlere bu bloğun dışında erişilemez.

{
  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

Döngü içinde

letDöngülerde bildirilen değişkenlere yalnızca bu döngü içinde başvurulabilir.

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.

Kapaklı döngüler

Bir döngüde kullanmak letyerine, varher yinelemede yeni bir değişken elde edersiniz. Bu, bir döngü içinde güvenli bir şekilde bir kapak kullanabileceğiniz anlamına gelir.

// 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);
}

Geçici ölü bölge

Geçici ölü bölge nedeniyle, kullanılarak bildirilen değişkenlere, bildirilmeden letönce erişilemez. Bunu yapmaya çalışmak hata verir.

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

Yeniden beyan yok

Aynı değişkeni kullanarak birden çok kez bildiremezsiniz let. Ayrıca, kullanılarak letbildirilen başka bir değişkenle aynı tanımlayıcıyla bir değişkeni bildiremezsiniz 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

constoldukça benzer let-Bu blok-kapsamlı ve sahip TGB. Ancak farklı olan iki şey vardır.

Yeniden atama yok

Kullanılarak bildirilen değişken constyeniden atanamaz.

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

Değerin değişmez olduğu anlamına gelmediğini unutmayın. Özellikleri hala değiştirilebilir.

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

Değişmez bir nesneye sahip olmak istiyorsanız, kullanmalısınız Object.freeze().

Başlatıcı gerekli

Kullanarak bir değişken bildirirken her zaman bir değer belirtmelisiniz const.

const a; // SyntaxError: Missing initializer in const declaration

51

İkisi arasındaki fark için bir örnek (chrome için yeni başlayan destek):
resim açıklamasını buraya girin

Gördüğünüz gibi, var jdeğişken hala for döngüsü kapsamının (Blok Kapsamı) dışında bir değere sahiptir, ancak let ideğişken for döngüsü kapsamının dışında tanımlanmamıştır.

"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);


2
Burada hangi araca bakıyorum?
Barton

20
Chrome devtools
vlio20

Cinnamon için masaüstü uygulamalarının geliştiricisi olarak böyle parlak araçlara maruz kalmadım.
Barton

48

Bazı ince farklılıklar vardır - letkapsam belirleme, az çok diğer dillerde değişken kapsam belirleme gibi davranır.

Örneğin, çevreleyen bloğu kapsamaktadır, Bildirilmeden önce mevcut değildirler, vb.

Ancak let, daha yeni Javascript uygulamalarının sadece bir parçası olduğunu ve değişen derecelerde tarayıcı desteğine sahip olduğunu belirtmek gerekir .


11
Ayrıca ECMAScript'in standart olduğunu ve 6. baskı taslağınalet dahil olduğunu ve büyük olasılıkla nihai spesifikasyonda olacağını belirtmek gerekir.
Richard Ayotte

23
3 yıldaki fark bu: D
olliej

4
Sadece bu soru üzerinde durdu ve 2012 yılında hala sadece Mozilla tarayıcılarının desteklediği durum böyle let. Safari, IE ve Chome hepsi bilmiyor.
pseudosavant

2
Kazayla kısmi blok kapsamı oluşturma fikri, bloğunuzun üstünde lettanımlanmış bir değişken tarafından tanımlanan bir değişkeni kullanmak için dikkatli olun, dikkat edin, kaldırmayın let. Bir varsa ifdaha kod sadece birkaç satır daha deyimi, size o tanımlanır sonrasına kadar bu değişken kullanabilirsiniz olamayacağını unutabilir. BÜYÜK NOKTA !!!
Eric Bishard

2
@EricB: evet ve hayır: "In ECMAScript 2015 let kaldırırlar olacak bloğun üstüne değişkeni Ancak, değişken bildirimi sonuçlarında önce bloktaki değişkeni referans. ReferenceError (notumu: yerine iyi eski undefined). değişken, bloğun başlangıcından bildirim işlenene kadar bir 'geçici ölü bölgede' olur. " Aynı şey "sadece bir temel blok olduğu için ifadeleri değiştir" için de geçerlidir. Kaynak: developer.mozilla.org/tr-TR/docs/Web/JavaScript/Reference/…
GitaarLAB

27

Temel fark ise kapsam iken, fark let içeride sadece mevcut olabilir kapsamı , döngü gibi o duyurulan var mesela döngü dışında erişilebilir. MDN'deki belgelerden (ayrıca MDN'den örnekler):

let , kapsamı ile sınırlı olan değişkenleri, kullanıldığı blok, ifade veya ifade ile bildirmenize izin verir. Bu, blok kapsamından bağımsız olarak bir değişkeni global olarak veya yerel olarak tüm bir işleve tanımlayan var anahtar sözcüğünden farklıdır .

Değişkenler tarafından ilan let kendi kapsamı gibi blok hangi tanımlandıkları gibi herhangi içerdiği alt bloklar halinde olan var. Bu şekilde, let çok gibi çalışır var . Ana fark, kapsamı olduğunu var değişken tüm parça işlevi:

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
}`

Program ve fonksiyonları üst düzeyde, izin aksine, var , küresel nesne üzerinde bir özellik oluşturmaz. Örneğin:

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

Bir bloğun içinde kullanıldığında, değişkenin kapsamını bu bloğa sınırlar. Kapsamı bildirildiği işlevin içinde olan var arasındaki farka dikkat edin.

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

Ayrıca ECMA6 özelliğini de unutmayın, bu yüzden henüz tam olarak desteklenmemektedir, bu yüzden babel web sitesini ziyaret ederek daha fazla bilgi için her zaman Babel vb.


24
  • Değişken Kaldırma

    letolacak değil vinç onlar görünür bloğunun tüm kapsamıyla. Buna karşılık, varaşağıdaki gibi kaldırırlar başladı.

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

    Aslında Per @Bergi, Hem varve letkaldırılır .

  • Çöp toplama

    Blok kapsamı, lethafızayı geri kazanmak için kapaklar ve çöp toplama ile ilgilidir. Düşünmek,

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

    clickİşleyici geri arama ihtiyacı yoktur hugeDatahiç değişkeni. Teorik olarak, çalışmalardan sonra process(..), büyük veri yapısı hugeDataçöp toplanabilir. Bununla birlikte, bazı JS motorunun hala bu büyük yapıyı korumak zorunda kalması mümkündür, çünkü clickişlev tüm kapsam üzerinde bir kapanışa sahiptir.

    Ancak, blok kapsamı bu büyük veri yapısını toplanan çöp haline getirebilir.

    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 döngüler

    letdöngüde, onu döngüdeki her yinelemeye yeniden bağlayabilir ve önceki döngü yinelemesinin sonundaki değeri yeniden atadığınızdan emin olun. Düşünmek,

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

    Ancak, yerine varilelet

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

    Çünkü let)), her bir yineleme Başlatıcı ekspresyon b bir için bu isimler ile yeni bir sözcük ortam yaratmak (previosly artış ifade) değerlendirmek için, daha fazla bilgi vardır burada .


4
Evet, kaldırıldılar, ancak (davul rulosu) Geçici Ölü Bölge nedeniyle kaldırılmamış gibi davranıyorlar - bir tanımlayıcıya dek ilan edilene kadar erişilemeyen çok dramatik bir isim :-)
Drenai

Yani izin verilsin, ama yok mu? Bu 'kaldırılmamış' durumdan nasıl farklıdır?
N-yedi

Umarım Brian ya da Bergi buna cevap vermek için geri gelir. İzin beyanı kaldırıldı, ödev değil mi? Teşekkürler!
N-yedik

1
@ N-yedik, İşte Bergi'nin bir yayını , belki de cevabı bulabilirsiniz.
zangw

İlginç olduğunda izin vermek için kaldırma denir bile. Ayrıştırma motorunun teknik olarak önceden yakalandığını anlıyorum, ancak tüm niyet ve amaçlar için bir programcı varmış gibi davranmalıdır. Diğer taraftan var'ın kaldırılması bir programcıya etki eder.
N-yedik

19

İşte başkalarının yazdıklarına eklemek için bir örnek. adderFunctionsHer işlevin tek bir Sayı bağımsız değişkeni aldığı ve bağımsız değişken ile dizideki işlevin dizininin toplamını döndürdüğü bir dizi işlev yapmak istediğinizi varsayalım . Anahtar kelimeyi adderFunctionskullanarak bir döngü oluşturmaya varçalışmak, birinin naif bir şekilde beklediği gibi çalışmaz:

// 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

Yukarıdaki işlem istenen işlev dizisini oluşturmaz çünkü ikapsamı forher işlevin oluşturulduğu bloğun yinelemesinin ötesine uzanır . Bunun yerine, döngünün sonunda, iher bir işlevin kapanışı i, içindeki her anonim işlev için döngünün sonunda (1000) değeri ifade eder adderFunctions. İstediğimiz bu değil: şimdi bellekte tam olarak aynı davranışa sahip 1000 farklı fonksiyon dizimiz var. Ve daha sonra değerini güncellersek i, mutasyon tümünü etkileyecektir adderFunctions.

Ancak, şu letanahtar kelimeyi kullanarak tekrar deneyebiliriz :

// 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

Bu kez, döngünün iher yinelemesinde geri tepme olur for. Artık her bir işlev i, işlevin oluşturulması sırasında değerini korur ve adderFunctionsbeklendiği gibi davranır.

Şimdi, iki davranışı karıştıran resim ve muhtemelen aynı komut dosyasında daha yeni letve constdaha eski olanlarla karıştırmanın neden önerilmediğini göreceksiniz var. Bunu yapmak bazı şaşırtıcı kafa karıştırıcı kod olabilir.

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

Bunun olmasına izin verme. Bir linter kullanın.

NOT: Bu, döngülerdeki var/ letdavranışı ve ayrıca anlaşılması kolay olan işlev kapanışlarıyla / davranışını göstermeyi amaçlayan bir öğretme örneğidir . Bu sayı eklemenin korkunç bir yolu olurdu. Ancak, anonim işlev kapanışlarında veri yakalamanın genel tekniğine, gerçek bağlamda diğer bağlamlarda rastlanabilir. YMMV.


2
@aborz: İkinci örnekte de çok güzel anonim işlev sözdizimi. Sadece C # 'a alışkınım. Bugün bir şey öğrendim.
Barton

Düzeltme: Teknik olarak, burada açıklanan Ok işlevi sözdizimi => developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Barton

3
Aslında ihtiyacınız yok let value = i;. forİfadesi bir sözcük bloğu oluşturur.
Diş fırçası

17

Fark, her biri ile bildirilen değişkenlerin kapsamındadır .

Uygulamada, kapsam farkının birkaç yararlı sonucu vardır:

  1. letdeğişkenler yalnızca en yakın çevreleme bloklarında ( { ... }) görünür .
  2. letdeğişkenler yalnızca değişken bildirildikten sonra ortaya çıkan kod satırlarında kullanılabilir ( kaldırılsa bile !).
  3. letdeğişkenler bir sonraki varveya tarafından yeniden bildirilemez let.
  4. Global letdeğişkenler global windownesneye eklenmez .
  5. letdeğişkenlerin kapaklarla kullanımı kolaydır ( yarış koşullarına neden olmazlar ).

Dayattığı kısıtlamalar letdeğişkenlerin görünürlüğünü azaltmak ve beklenmedik adı çarpışmalar erken bulunabilir ihtimalini artırır. Bu, değişkenlerin erişilebilirliği de dahil olmak üzere izlenmesini ve nedenini kolaylaştırır (kullanılmayan belleği geri kazanmaya yardımcı olur).

Sonuç olarak, letbüyük programlarda kullanıldığında veya bağımsız olarak geliştirilen çerçeveler yeni ve beklenmedik şekillerde birleştirildiğinde değişkenlerin sorun yaratma olasılığı daha düşüktür.

varbir döngüde (# 5) bir kapatma kullanırken veya kodunuzda (# 4) harici olarak görülebilir global değişkenleri bildirirken tek bağlayıcı efekti istediğinizden eminseniz yine de yararlı olabilir. Transpiler alanından ve ana dile göç varederse, ihracat için kullanımı desteklenebilir export.

Örnekler

1. En yakın çevreleme bloğunun dışında kullanım yok: Bu kod bloğu bir referans hatası verir çünkü ikinci kullanımı x, bildirildiği blok dışında gerçekleşir let:

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

Aksine, aynı örnek varçalışır.

2. Beyan etmeden önce faydasız:
Bu kod bloğu, kod ReferenceErrorçalıştırılmadan önce a atar , çünkü xbildirilmeden önce kullanılır:

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

Aksine, aynı örnek varistisna atmadan ayrıştırılır ve çalışır.

3. Yeniden bildirim yok: Aşağıdaki kod, bildirilen bir değişkenin letdaha sonra yeniden bildirilemeyebileceğini gösterir :

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

4. Bağlı olmayan globaller 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. Kapaklar ile kolay kullanım: Bildirilen değişkenler, vardöngülerin içindeki kapaklarla iyi çalışmaz. Değişkenin izaman içinde farklı noktalarda sahip olduğu değer dizisini çıktılayan basit bir döngü :

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

Özellikle, bu çıktı:

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

JavaScript'te değişkenleri genellikle oluşturulduklarından çok daha geç bir zamanda kullanırız. Bunu, çıktıyı bir kapakla geciktirerek gösterdiğimizde setTimeout:

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

... yapıştığımız sürece çıktı değişmeden kalır let. Aksine, biz var ionun yerine kullansaydık :

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

... döngü beklenmedik şekilde beş kez "i 5" olur:

i is 5
i is 5
i is 5
i is 5
i is 5

5
# 5 bir yarış koşulundan kaynaklanmaz. Bunun varyerine let, kod şuna eşittir: var i = 0; while (i < 5) { doSomethingLater(); i++; } ikapanışın dışındadır ve doSomethingLater()yürütülen zamana göre izaten 5 kat artırılmıştır, dolayısıyla çıktı i is 5beş kat daha fazladır. Kullanarak let, değişken ikapanış içindedir, bu nedenle her eşzamansız çağrı, ioluşturulmuş 'global' kullanmak yerine kendi kopyasını alır var.
Daniel T.

@DanielT .: Değişken tanımını döngü başlatıcıdan kaldırmanın dönüşümünün bir şeyi açıkladığını sanmıyorum. Bu sadece anlambilimin normal tanımıdır for. Daha doğru bir dönüşüm, daha karmaşık olsa da, klasik for (var i = 0; i < 5; i++) { (function(j) { setTimeout(_ => console.log(i $ {j} ' dır ve ), 125/*ms*/); })(i); }bu da her bir değerini fonksiyonun iadıyla kaydetmek için bir "fonksiyon aktivasyon kaydı" sunar j.
mormegil

14

Aşağıdaki iki işlev farkı gösterebilir:

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
}

13

let ilginç, çünkü böyle bir şey yapmamıza izin veriyor:

(() => {
    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++);
            }
        }
    }
})();

Bu da saymaya neden olur [0, 7].

Buna karşılık

(() => {
    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++);
            }
        }
    }
})();

Sadece [0, 1] sayılır.


2
Bu, herkesin ilk kez değişken gölgeleme gibi davrandığını gördüm. Hayır, izin verme amacı gölgelendirmeyi etkinleştirmemek
John Haugeland

1
Amaç? bu bir yapı, bunu kullanabilirsiniz, ancak lütfen, ilginç yollardan biri böyle.
Dmitry

13

Fonksiyon VS blok kapsamı:

Arasındaki temel fark varve letbu değişkenler ile deklare olduğu varedilmektedir işlevi kapsamlı . Fonksiyonlar ile beyan Oysa letolan blok kapsamlı . Örneğin:

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 

değişkenler var:

İlk işlev testVarbildirildiğinde foo değişkeni olarak adlandırıldığında var, ififadenin dışında da erişilebilir . Bu değişken fonksiyon kapsamında her yerdefoo kullanılabilir .testVar

değişkenler let:

İkinci işleve testLetbildirilen değişken çubuğu çağrıldığında let, yalnızca ifdeyim içinde erişilebilir . Değişkenler ile bildirilen için letolan blok kapsamlı (blok yuvarlak parantezler arasında kodudur örneğin if{}, for{}, function{}).

let değişkenler kaldırılmaz:

varVe letile arasındaki bir diğer fark , beyan edilen değişkenlerle let kaldırılmaz . Bir örnek, bu davranışı göstermenin en iyi yoludur:

ile değişkenler let yok hoisted olsun:

console.log(letVar);

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

ile değişkenler var do olsun Çekilen:

console.log(varVar);

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

Global aşağıdakilere leteklenmez window:

Genel letkapsamda bildirilen bir değişken (işlevde olmayan koddur) genel windownesneye özellik olarak eklenmez . Örneğin (bu kod global kapsamdadır):

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


Ne zaman letkullanılmalıdır var?

Kullanım letüzerinde varbunu basitçe daha spesifik kapsama aldığı çünkü her. Bu, çok sayıda değişkenle uğraşırken oluşabilecek potansiyel adlandırma çakışmalarını azaltır. varbir global değişkenin windownesnede açıkça olmasını istediğinizde kullanılabilir (bu gerçekten gerekliyse her zaman dikkatlice düşünün).


9

Ayrıca, en azından Visual Studio 2015'te, TypeScript 1.5'te "var" öğesinin, bir blokta aynı değişken adının birden çok bildirilmesine izin verdiği ve "let" öğesinin izin vermediği görülmektedir.

Bu bir derleme hatası oluşturmaz:

var x = 1;
var x = 2;

Bu irade:

let x = 1;
let x = 2;

9

var küresel kapsam (kaldırma kabiliyeti olan) değişkendir.

letve constblok kapsamıdır.

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


8

Kullanırken let

letAnahtar kelime ne olursa olsun bloğun (genellikle kapsamına değişken bildiriminde verdiği { .. }o içerdiği oluyor çifti). Başka bir deyişle, letörtük olarak değişken beyanı için herhangi bloğun kapsamını hijacks.

letwindowküresel olarak erişilemediğinden , nesnede değişkenlere erişilemez.

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

Kullanırken var

var ve ES5'teki değişkenlerin fonksiyonlarda kapsamları vardır, bu da değişkenlerin fonksiyon içinde geçerli olduğu ve fonksiyonun dışında olmadığı anlamına gelir.

vardeğişkenlere, genel olarak erişilemedikleri için windownesnede erişilebilir.

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

Eğer daha fazlasını öğrenmek istiyorsanız, aşağıdaki okumaya devam edin

kapsamına en ünlü görüşme sorulardan biri de tam kullanımını yeterli olabilir letve varaşağıdaki gibi;

Kullanırken let

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

Bunun nedeni let, her döngü yinelemesi için değişkenin kapsamı ve kendi kopyasına sahip olmasıdır.

Kullanırken var

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

Bunun nedeni var, her döngü yinelemesi için değişkenin kapsamlandırılması ve kopyasının paylaşılmış olmasıdır.


7

Spesifikasyonları doğru let okursam , o zaman şükürler olsun ki , sadece özel üyelere benzetmek için kullanılan kendini çağıran işlevlerden kaçınmak için kullanılabilir - kod okunabilirliğini azaltan, hata ayıklamayı zorlaştıran, gerçek kod koruması veya başka bir fayda sağlamayan popüler bir tasarım deseni - belki birinin tatmin edici olması dışında anlambilim arzusu, bu yüzden kullanmayı bırakın. / rant

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

Bkz. ' Özel arayüzleri taklit etme '


Hemen Başlatılan İşlev İfadelerinin “kod koruması” sağlamadığı ve nasıl sağladığı konusunda ayrıntılı bilgi verebilir letmisiniz? (Sanırım “kendini çağırma işlevi” ile IIFE demek istiyorsun.)
Robert Siemer

Ve neden kurucuya hiddenPropertykoydunuz? hiddenProperty"Sınıfınızdaki" tüm örnekler için yalnızca bir tane vardır .
Robert Siemer

7

En temel terimlerle,

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

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

⚡️ Oynamak için sandbox ↓

Düzenle let vs var


4

Bazı hackler 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"

Alıcı ve ayarlayıcı 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)

lütfen bu ne anlama geliyor let { type, name, value } = node;? 3 özellik türü / adı / değeri olan yeni bir nesne oluşturup bunları düğümdeki özellik değerleriyle başlatır mısınız?
AlainIb

Örnek 3'te, istisna oluşturan düğümü yeniden bildiriyorsunuz. Tüm bu örnekler de mükemmel şekilde çalışır var.
Rehan Haider

4

let vs var. Her şey kapsamla ilgili .

var değişkenleri geneldir ve temelde her yerde erişilebilirken, değişkenler genel değildir ve yalnızca bir kapanış parantezi onları öldürene kadar var olur.

Aşağıdaki örneğime bakın ve lion (let) değişkeninin iki console.logs içinde nasıl farklı davrandığını not edin; 2nd console.log dosyasında kapsam dışı olur.

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.

4

ES6 var yerine alternatif olarak iki yeni anahtar kelime ( let ve const ) tanıttı .

Bir blok düzeyinde yavaşlamaya ihtiyacınız olduğunda var yerine let ve const ile gidebilirsiniz.

Aşağıdaki tablo var, let ve const arasındaki farkı özetler

resim açıklamasını buraya girin


3

let es6'nın bir parçası. Bu işlevler farkı kolay bir şekilde açıklayacaktır.

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
}

3

Aşağıda 'let' ve 'var' öğelerinin kapsamda nasıl farklı oldukları gösterilmiştir:

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

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

gfooTarafından tanımlanan letbaşlangıçta olduğu küresel kapsam ve biz bildirirken gfooiçeride tekrar if clauseonun kapsamı değişti ve yeni bir değer olduğunu kapsam içine değişkene atandığında o etkilemez küresel kapsamı.

Bununla birlikte hfoo, tarafından tanımlanmış varbaşlangıçta küresel kapsamdadır , ancak yine içinde ilan if clauseettiğimizde, var olanı beyan etmek için tekrar kullanılmasına rağmen, küresel kapsam hfoo'yu göz önünde bulundurur. Ve değerini yeniden atadığımızda, küresel kapsam hfoo'nun da etkilendiğini görüyoruz. Bu birincil farktır.


2

Yukarıda da belirtildiği gibi:

Fark kapsamıdır. varEn yakın için kapsamlı fonksiyon bloğu ve letodaklanan yakın parça blok bir fonksiyon blok daha küçük olabilir. Herhangi bir bloğun dışındaysa her ikisi de globaldir.

Örnek 1:

Her iki örneğimde de bir fonksiyonum var myfunc. 10'a eşit myfuncbir değişken içerir myvar. İlk myvarörneğimde 10 ( myvar==10) olup olmadığını kontrol ediyorum . Eğer evet ise, ben acian anahtar kelimeyi myvarkullanarak bir değişken (şimdi iki myvar değişkenim var) beyan varve yeni bir değer atar (20). Bir sonraki satırda değerini konsoluma yazdırıyorum. Koşullu bloktan sonra myvarkonsolumun değerini tekrar yazdırıyorum . Eğer çıkışında bakarsak myfunc, myvardeğer 20'ye eşittir vardır.

izin anahtar kelime

Örnek 2:var Koşullu blokta anahtar kelime kullanmak yerine ikinci örneğimde anahtar kelime myvarkullandığımı beyan ederim let. Şimdi aradığımda myfunc iki farklı çıkış elde ediyorum: myvar=20ve myvar=10.

Yani fark çok basit yani kapsamı.


3
Lütfen kod resimlerini yayınlamayın, gelecekteki kullanıcılar (ve erişilebilirlik endişeleri) için aranamayacağı için SO'da kötü uygulama olarak kabul edilir. Ayrıca, bu cevap diğer yanıtların daha önce ele almadığı hiçbir şey eklememektedir.
inostia

2

Yürütme Bağlamı tüm bunlar için önemlidir, çünkü bu anahtar kelimeleri Yürütme Bağlam bağlamak istiyorum. Yürütme Bağlamının iki aşaması vardır: Bir Oluşturma Safhası ve Yürütme Safhası. Ayrıca, her Yürütme Bağlamında Değişken Ortam ve Dış Ortam (Lexical Environment) vardır.

Bir Yürütme Bağlamının Oluşturma Aşaması sırasında, var, let ve const değişkenleri bellekte, belirli Yürütme Bağlamının Değişken Ortamında tanımlanmamış bir değerle depolanır. Fark Yürütme Aşamasındadır. Bir değer atanmadan önce var ile tanımlanan bir değişkeni başvuru kullanırsanız, yalnızca tanımsız olur. Herhangi bir istisna yapılmayacaktır.

Ancak, bildirilene kadar let veya const ile bildirilen değişkene başvuramazsınız. Bildirilmeden önce kullanmaya çalışırsanız, Yürütme Bağlamının Yürütme Aşaması sırasında bir istisna ortaya çıkar. Şimdi, değişken Yürütme Bağlamının Oluşturma Aşamasının izniyle hala bellekte olacaktır, ancak Motor bunu kullanmanıza izin vermeyecektir:

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

Var ile tanımlanan bir değişkenle, Motor değişkeni geçerli Yürütme Bağlamının Değişken Ortamında bulamazsa, kapsam zincirini (Dış Ortam) yukarı çıkar ve değişken için Dış Ortamın Değişken Ortamını kontrol eder. Orada bulamazsa, Kapsam Zincirini aramaya devam eder. Let ve const için durum böyle değil.

Let'in ikinci özelliği blok kapsamını tanıtmasıdır. Bloklar kıvırcık parantezlerle tanımlanır. Örnekler arasında fonksiyon blokları, bloklar, bloklar, vb. Sayılabilir. Bir bloğun içine izin verilen bir değişken bildirdiğinizde, değişken sadece bloğun içinde kullanılabilir. Aslında, blok bir for döngüsü içinde her çalıştırıldığında, bellekte yeni bir değişken oluşturur.

ES6 ayrıca değişkenleri bildirmek için const anahtar sözcüğünü sunar. const ayrıca blok kapsamlıdır. Let ve const arasındaki fark, const değişkenlerinin bir başlatıcı kullanarak bildirilmesi gerektiğidir, yoksa bir hata oluşturur.

Son olarak, Yürütme Bağlamı söz konusu olduğunda, var ile tanımlanan değişkenler 'this' nesnesine eklenir. Genel Yürütme Bağlamında, bu tarayıcılardaki pencere nesnesi olacaktır. İzin ya da inşa için durum böyle değil.


2

Ben terimler ve örneklerin çoğu biraz ezici olduğunu düşünüyorum, ben fark ile şahsen vardı ana konu bir "Blok" ne olduğunu anlamak. Bir noktada fark ettim, bir blok IFifade dışında herhangi bir süslü parantez olacaktır . bir {fonksiyonun veya halkanın açılış braketi yeni bir blok tanımlayacaktır, letiçinde tanımlanmış herhangi bir şey }, aynı şeyin (fonksiyon veya döngü) kapanış braketinden sonra kullanılamayacaktır ; Bunu akılda tutarak, anlamak daha kolaydı:

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);


1

Şimdi ben kullanarak bir deyimler bloğuna değişkenler daha iyi kapsamı düşünüyorum 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
}

Bence insanlar burada izin kullanmaya başlayacaklar, böylece JavaScript'te diğer diller, Java, C # vb.

JavaScript'te kapsam belirleme konusunda net bir anlayışa sahip olmayanlar, hatayı daha önce yapmıştır.

Kaldırma kullanımı ile desteklenmez let.

Bu yaklaşımla JavaScript'te mevcut hatalar kaldırılıyor.

Ayrıntılı olarak ES6'ya bakın : daha iyi anlamak için izin verin ve kurun .


Üzerinde derinlemesine anlayış için bağlantıya bakın - davidwalsh.name/for-and-against-let
swaraj patil

1

Bu makale var, let ve const arasındaki farkı açıkça tanımlamaktadır.

const tanımlayıcının yeniden atanmayacağının bir işaretidir.

let, bir devredeki sayaç veya algoritmadaki değer değişimi gibi değişkenin yeniden atanabileceğinin bir işaretidir. Ayrıca, değişkenin yalnızca tanımlandığı blokta kullanılacağına işaret eder, bu da her zaman tüm işlevini içermez.

varartık JavaScript'te bir değişken tanımladığınızda mevcut olan en zayıf sinyaldir. Değişken yeniden atanabilir veya atanmayabilir ve değişken tüm bir işlev için veya yalnızca bir blok veya döngü amacıyla kullanılabilir veya kullanılmayabilir.

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.