В чем разница между использованием "let" и "var" для объявления переменной в JavaScript?

ECMAScript 6 введен на let сообщении. Я слышал, что он описывается как "локальная" переменная, но я все еще не совсем уверен, как она ведет себя иначе, чем var ключевое слово.

В чем разница? Когда let использоваться по var?

27 ответов


разница в области. var действует до ближайшего функционального блока и let действует до ближайшего вшита блок, который может быть меньше функционального блока. Оба являются глобальными, если за пределами любого блока.

кроме того, переменные, объявленные с let недоступны до того, как они будут объявлены в их заключительном блоке. Как видно из демонстрации, это вызовет исключение ReferenceError.

демо:

var html = '';

write('#### global ####\n');
write('globalVar: ' + globalVar); //undefined, but visible

try {
  write('globalLet: ' + globalLet); //undefined, *not* visible
} catch (exception) {
  write('globalLet: exception');
}

write('\nset variables');

var globalVar = 'globalVar';
let globalLet = 'globalLet';

write('\nglobalVar: ' + globalVar);
write('globalLet: ' + globalLet);

function functionScoped() {
  write('\n#### function ####');
  write('\nfunctionVar: ' + functionVar); //undefined, but visible

  try {
    write('functionLet: ' + functionLet); //undefined, *not* visible
  } catch (exception) {
    write('functionLet: exception');
  }

  write('\nset variables');

  var functionVar = 'functionVar';
  let functionLet = 'functionLet';

  write('\nfunctionVar: ' + functionVar);
  write('functionLet: ' + functionLet);
}

function blockScoped() {
  write('\n#### block ####');
  write('\nblockVar: ' + blockVar); //undefined, but visible

  try {
    write('blockLet: ' + blockLet); //undefined, *not* visible
  } catch (exception) {
    write('blockLet: exception');
  }

  for (var blockVar = 'blockVar', blockIndex = 0; blockIndex < 1; blockIndex++) {
    write('\nblockVar: ' + blockVar); // visible here and whole function
  };

  for (let blockLet = 'blockLet', letIndex = 0; letIndex < 1; letIndex++) {
    write('blockLet: ' + blockLet); // visible only here
  };

  write('\nblockVar: ' + blockVar);

  try {
    write('blockLet: ' + blockLet); //undefined, *not* visible
  } catch (exception) {
    write('blockLet: exception');
  }
}

function write(line) {
  html += (line ? line : '') + '<br />';
}

functionScoped();
blockScoped();

document.getElementById('results').innerHTML = html;
<pre id="results"></pre>

общие:

они очень похожи при использовании как это вне функционального блока.

let me = 'go';  // globally scoped
var i = 'able'; // globally scoped

однако глобальные переменные определяются с помощью let не будут добавлены в качестве свойств на глобальном window объект, как те, которые определены с var.

console.log(window.me); // undefined
console.log(window.i); // 'able'

функция:

они идентичны при использовании в функции блок.

function ingWithinEstablishedParameters() {
    let terOfRecommendation = 'awesome worker!'; //function block scoped
    var sityCheerleading = 'go!'; //function block scoped
}

блок:

вот разница. let виден только в for() петли и var виден для всей функции.

function allyIlliterate() {
    //tuce is *not* visible out here

    for( let tuce = 0; tuce < 5; tuce++ ) {
        //tuce is only visible in here (and in the for() parentheses)
        //and there is a separate tuce variable for each iteration of the loop
    }

    //tuce is *not* visible out here
}

function byE40() {
    //nish *is* visible out here

    for( var nish = 0; nish < 5; nish++ ) {
        //nish is visible to the whole function
    }

    //nish *is* visible out here
}

Redeclaration:

предполагая строгого режима, var позволит вам повторно объявить ту же переменную в той же области. С другой стороны,--9--> не будет:

'use strict';
let me = 'foo';
let me = 'bar'; // SyntaxError: Identifier 'me' has already been declared
'use strict';
var me = 'foo';
var me = 'bar'; // No problem, `me` is replaced.

let можно также использовать для избежания проблем с закрытиями. Он связывает новое значение, а не сохраняет старую ссылку, как показано в примерах ниже.

демо

for(var i = 1; i < 6; i++) {
  document.getElementById('my-element' + i)
    .addEventListener('click', function() { alert(i) })
}

код выше демонстрирует классическую проблему закрытия JavaScript. Ссылка на i переменная хранится в закрытии обработчика щелчка, а не фактическое значение i.

каждый обработчик щелчка будет ссылаться на один и тот же объект потому что есть только один встречный объект, который содержит 6, поэтому вы получаете шесть на каждый клик.

общий обходной путь-обернуть это в анонимную функцию и передать i в качестве аргумента. Таких проблем также можно избежать, используя let вместо var как показано в ниже код.

демо (протестировано в Chrome и Firefox 50)

'use strict';

for(let i = 1; i < 6; i++) {
  document.getElementById('my-element' + i)
    .addEventListener('click', function() { alert(i) })
}

здесь объяснение let ключевое слово С некоторыми примерами.

let работает очень похоже на var. Основное отличие заключается в том, что область переменной var-это вся заключающая функция

в этой таблице в Википедии показано, какие браузеры поддерживают Javascript 1.7.

обратите внимание, что его поддерживают только браузеры Mozilla и Chrome. То есть, Safari, и потенциально другие не делают.


в чем разница между let и var?

  • переменная, определенная с помощью var заявление известно во всем функции он определяется в, с самого начала функции. (*)
  • переменная, определенная с помощью let оператор известен только в блок он определяется в, с момента его определения и далее. (**)

чтобы понять разницу, рассмотрим следующий код:

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

здесь мы видим, что наша переменная j известно только в первом цикле, но не до и после. Еще, наши переменной i известно во всей функции.

кроме того, учтите, что переменные области блока не известны до их объявления, потому что они не поднимаются. Вы также не можете повторно объявить тот же блок, область действия переменная в пределах одного блока. Это делает переменные области блока менее подверженными ошибкам, чем глобально или функционально переменные области, которые поднимаются и которые не производят ошибок в случае нескольких объявлений.


безопасно ли использовать let сегодня?

некоторые люди будут утверждать, что в будущем мы будем использовать только операторы let и что операторы var станут устаревшими. Гуру в JavaScript Кайл Симпсон написал очень продуманная статья о том, почему это не так.

сегодня, однако, это определенно не тот случай. На самом деле нам нужно спросить себя, безопасно ли использовать let заявление. Ответ на этот вопрос зависит от вашего окружения:

  • если вы пишете серверный код JavaScript (узел.js), вы можете смело использовать let заявление.

  • если вы пишете клиентский код JavaScript и используете транспилер (например,Трейсер), вы можете смело использовать let оператор, однако ваш код, вероятно, будет чем угодно, но не оптимальным по производительности.

  • если вы пишете клиентский JavaScript-код и не используете транспилер, вам необходимо рассмотреть поддержку браузера.

Сегодня, 8 Июня 2018, есть еще некоторые браузеры, которые не поддерживают let!

enter image description here


как отслеживать поддержку браузера

для обновленного обзора того, какие браузеры поддерживают let заявление во время чтения этого ответа см. этой Can I Use страница.


(*) глобальные и функциональные переменные могут быть инициализированы и использованы до их заявил, что переменные JavaScript подняли. это означает, что объявления всегда находятся в верхней части области.

(**) переменные области блока не поднимаются


в принятом ответе отсутствует точка:

{
  let a = 123;
};

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

есть некоторые тонкие различия -- let scoping ведет себя больше как переменная scoping делает в более или менее любых других языках.

например, он распространяется на заключительный блок, они не существуют до их объявления и т. д.

однако стоит отметить, что let является только частью новых реализаций Javascript и имеет различную степень поддержка браузеров.


вот пример разницы между ними (поддержка только что началась для chrome): enter image description here

Как видите,var j переменная по-прежнему имеет значение вне области цикла for (область блока), но let i переменная не определена вне области цикла.

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

let

блок рамки

переменные, объявленные с помощью let ключевое слово блочная область видимости, что означает, что они доступны только в блок, в котором они были объявлены.

на верхнем уровне (вне функции)

на верхнем уровне, переменные, объявленные с помощью let не создавайте свойства для глобального объекта.

var globalVariable = 42;
let blockScopedVariable = 43;

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

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

внутри функции

внутри funciton (но за пределами квартала),let имеет тот же объем, что и 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

внутри блока

переменные, объявленные с помощью let внутри блока невозможно получить доступ за пределами этого блока.

{
  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

внутри цикла

переменные, объявленные с let в циклах можно ссылаться только внутри этого цикла.

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.

петли с замыканиями

если вы используете let вместо var в цикле, с каждым итерация вы получаете новую переменную. Это означает, что вы можете безопасно использовать закрытие внутри петли.

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

временная мертвая зона

из-за временная мертвая зона переменные объявляются с помощью let невозможно получить доступ до их объявления. Попытка сделать это вызывает ошибку.

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

нет повторного объявления

вы не можете объявить ту же переменную несколько раз, используя let. Вы также не можете объявить переменную используя let С тем же идентификатором, что и другая переменная, которая была объявлена с помощью 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

const очень похоже на let - это блок-область и имеет TDZ. Однако есть две вещи, которые отличаются друг от друга.

нет повторного назначения

переменная, объявленная с помощью const не может быть повторно назначен.

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

обратите внимание, что это не значит, что значение является неизменяемым. Свои свойства все еще могут быть изменен.

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

если вы хотите иметь неизменный объект, вы должны использовать Object.freeze().

инициализатор требуется

вы всегда должны указать значение при объявлении переменной с помощью const.

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

  • Переменная Не Поднимать

    let будет не Тали для всего объема блока, в котором они появляются. Напротив,var мог поднять, как показано ниже.

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

    На Самом Деле, Per @Bergi,и var и let поднял.

  • Вывоз Мусора

    объем блока let полезно относится к закрытиям и сбору мусора для восстановления памяти. Подумай,

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

    на click обработчик не нужен hugeData переменная вообще. Теоретически, после process(..) работает, огромная структура данных hugeData может быть собран "мусор". Тем не менее, возможно, что какой-то двигатель JS все равно должен будет сохранить эту огромную структуру, так как click функция имеет закрытие по всей области.

    однако, объем блока может сделать эти огромные данные структура для мусора.

    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 петли

    let в цикле can повторно связывает его для каждой итерации цикла, убедитесь, что повторно присвоить ему значение из конца предыдущей итерации цикла. Подумай,

    // print '5' 5 times
    for (var i = 0; i < 5; ++i) {
        setTimeout(function () {
            console.log(i);
        }, 1000);  
    }
    
    заменить var С let
    // print 1, 2, 3, 4, 5. now
    for (let i = 0; i < 5; ++i) {
        setTimeout(function () {
            console.log(i);
        }, 1000);  
    }
    

    , потому что let создайте новую лексическую среду с этими именами для A) инициализатора выражение b) каждая итерация (предварительно для оценки выражения приращения), более подробная информация здесь.


главным образом разница область разница, в то время как пусть может быть доступен только внутри объявленной области, как в for loop,var можно получить доступ за пределами цикла, например. Из документации в MDN (примеры также из MDN):

пусть позволяет объявлять переменные, ограниченные по области действия блоком, инструкцией или выражением, в которых они используются. Это не похоже на var ключевое слово, которое определяет переменную глобально, или локально для целой функции независимо от объема блока.

переменные, объявленные пусть имеют в качестве своей области блок, в котором они определены, а также в любых содержащихся подблоках. Таким образом, пусть работает очень похоже на var. Основное отличие заключается в том, что объем a var переменная всю вшита функция:

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

на верхнем уровне программ и функций, пусть в отличие от var, не создает свойство глобального объекта. Например:

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

при использовании внутри блока пусть ограничивает область переменной этим блоком. Обратите внимание на разницу между var объем которого внутри функции, где она объявлена.

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

также не забудьте это особенность ECMA6, так что это пока не полностью поддерживается, так что лучше всегда transpiles его ECMA5 используя Бабеля и т. д... для получения дополнительной информации о визите веб-сайт babel


вот пример, чтобы добавить к тому, что другие уже написали. Предположим, вы хотите создать массив функций, adderFunctions, где каждая функция принимает один числовой аргумент и возвращает сумму аргумента и индекса функции в массиве. Попытка создать adderFunctions С помощью цикла с помощью var ключевое слово не работает так, как кто-то может наивно ожидать:

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

процесс выше не генерирует желаемый массив функций, потому что iсферы деятельности выходит за рамки итерации for блок, в котором каждая функция была создана. Вместо этого, в конце цикла i в каждой функции закрытие относится к iзначение в конце цикла (1000) для каждой анонимной функции в adderFunctions. Это совсем не то, что мы хотели: теперь у нас есть массив из 1000 различных функций в памяти с точно таким же поведением. И если мы впоследствии обновим значение i, мутация повлияет на все adderFunctions.

тем не менее, мы можем попробовать еще раз, используя let ключевые слова:

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

в этот раз i отскок на каждой итерации for петли. Каждая функция теперь сохраняет значение i во время создания функции и adderFunctions ведет себя так, как ожидалось.

теперь изображение смешивает два поведения, и вы, вероятно, увидите, почему не рекомендуется смешивать новые let и const старые var в том же сценарии. Делающий так может получиться какой-то эффектно запутанный код.

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

не позволяйте этому случиться с вами. Используйте Линтер.

Примечание: это обучающий пример, предназначенный для демонстрации var/let поведение в циклах и с замыканиями функций, которые также было бы легко понять. Это был бы ужасный способ сложения чисел. Но общий метод захвата данных в анонимных замыканиях функций может встретиться в реальном мире в других контекстах. YMMV.


разницу в область переменных, объявленных с каждым.

на практике существует ряд полезных последствий разницы в объеме:

  1. let переменные видны только в их ближайшего объемлющего блока ({ ... }).
  2. let переменные можно использовать только в строках кода, которые происходят после переменная объявлена (хотя они лапы!).
  3. let переменные не могут быть повторно объявлены последующим var или let.
  4. глобальные let переменные не добавляются в глобальный

могут следующие две функции показать разницу:

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
}

let интересно, потому что это позволяет нам делать что-то вроде этого:

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

что приводит к подсчету [0, 7].

, тогда как

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

только [0, 1].


также кажется, что, по крайней мере, в Visual Studio 2015, TypeScript 1.5, "var" допускает несколько объявлений одного и того же имени переменной в блоке, а "let" - нет.

это не приведет к ошибке компиляции:

var x = 1;
var x = 2;

Это:

let x = 1;
let x = 2;

var глобальная переменная объема (подъем-способная).

let и const объем блока.


Если я прочитаю спецификации прямо тогда let к счастью также можно использовать, чтобы избежать самостоятельного вызова функций, используемых для имитации только частных членов -популярный шаблон дизайна, который уменьшает читаемость кода, усложняет отладку, не добавляет никакой реальной защиты кода или другого преимущества - за исключением, возможно, удовлетворения чьего-то желания семантики, поэтому прекратите его использовать. / 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

посмотретьэмуляция приватных интерфейсов'


некоторые хаки с 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"

геттер и сеттер с 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)

При Использовании let

на let ключевое слово присоединяет объявление переменной к области любого блока (обычно { .. } пара) он содержится внутри. Другими словами,let неявно захватывает область действия любого блока для его объявления переменной.

let переменные не могут быть доступны в window объект, потому что они не могут быть глобально доступны.

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

При Использовании var

var и переменные в ES5 имеют области в функциях, что означает, что переменные действительны внутри функции, а не вне самой функции.

var переменные могут быть доступны в window объект, потому что они не могут быть глобально доступны.

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

если вы хотите узнать больше, продолжайте читать ниже

один из самых известных вопросов интервью на объеме также может быть достаточным точное использование из let и var как ниже;

при использовании let

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

это потому, что при использовании let, для каждой итерации цикла переменная имеет область видимости и собственную копию.

при использовании var

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

это потому, что при использовании var, для каждой итерации цикла переменная имеет область видимости и общую копию.


let является частью es6. Эти функции легко объяснят разницу.

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
}

функция против области блока:

основное различие между var и let это переменные, объявленные с var are


ранее в JavaScript было только две области, т. е. функциональная и глобальная. С 'let' ключевое слово JavaScript теперь введено block-level переменные.

чтобы иметь полное представление о ключевом слове "let", ES6: ключевое слово " let " для объявления переменной в JavaScript поможет.


Теперь я думаю, что лучше область переменных для блока операторов с использованием 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
}

Я думаю, что люди начнут использовать let здесь после того, как они будут иметь аналогичную область в JavaScript, как и другие языки, Java, C# и т. д.

люди с неясным пониманием области в JavaScript, используемые для совершения ошибки ранее.

подъем не поддерживается с помощью let.

при таком подходе ошибки присутствуют в JavaScript удаляются.

смотрите ES6 в глубину: пусть и const чтобы понять это лучше.


эта статья четко определяет разницу между var, let и const

const - Это сигнал о том, что идентификатор не будет переназначен.

let, является сигналом о том, что переменная может быть переназначена, например счетчик в цикле или своп значений в алгоритме. Он также сигналов что переменная будет использоваться только в блоке, в котором она определена, который не всегда является всей содержащей функцией.

var сейчас самый слабый сигнал, доступный при определении переменной в JavaScript. Переменная может быть или не может быть переназначена, и переменная может использоваться или не использоваться для всей функции или только для назначение блока или петли.

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


как было сказано выше:

разница в области. var область видимости до ближайшего


ECMAScript 6 добавлено еще одно ключевое слово для объявления переменных, отличных от" Let".

основная цель введения "let" и "const" над " var " состоит в том, чтобы иметь блочный охват вместо традиционного лексического. эта статья очень кратко объясняет разницу между "var" и "let", а также охватывает обсуждение "const".


проверьте эту ссылку в MDN

let x = 1;

if (x === 1) {
let x = 2;

console.log(x);
// expected output: 2
}

console.log(x);
// expected output: 1