Какая разница между использованием "let" и "var"?

ECMAScript 6 представил оператор let.

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

Какие есть отличия? Когда следует let использовать над var?

+3903
17 апр. '09 в 20:09
источник поделиться
36 ответов
  • 1
  • 2

Разница в том, 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
}

переопределение:

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

'use strict';
var me = 'foo';
var me = 'bar'; // No problem, 'me' is replaced.

С другой стороны, let не будут

'use strict';
let me = 'foo';
let me = 'bar'; // SyntaxError: Identifier 'me' has already been declared
+5314
12 июл. '12 в 2:53
источник

Связанные вопросы


Похожие вопросы

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) })
}
+529
27 мая '15 в 10:16
источник

Какая разница между 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 известна только в первом цикле for, но не до и после. Тем не менее, наша переменная i известна во всей функции.

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


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

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

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

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

  • Если вы пишете код JavaScript на стороне клиента и используете браузер (например, Traceur или babel-standalone), вы можете смело использовать оператор let, однако ваш код, вероятно, будет не оптимальным с точки зрения производительности.

  • Если вы пишете код JavaScript на стороне клиента и используете транспортер на основе Node (например, скрипт оболочки traceur или Babel), вы можете смело использовать оператор let. А поскольку ваш браузер будет знать только о переданном коде, недостатки производительности должны быть ограничены.

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

    Есть еще некоторые браузеры, которые вообще не поддерживают let:

Support table


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

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


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

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

+144
23 февр. '16 в 18:35
источник

Вот объяснение ключевого слова let с некоторыми примерами.

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

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

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

+139
17 апр. '09 в 20:11
источник

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

{
  let a = 123;
};

console.log(a); // ReferenceError: a is not defined
+105
02 июн. '15 в 20:59
источник

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

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

Внутри функции (но вне блока) 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 in, могут ссылаться только внутри этого цикла.

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 -it в блочном пространстве и имеет 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
+63
23 нояб. '16 в 22:52
источник

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

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

"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);
+44
06 мар. '15 в 10:41
источник

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

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

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

+44
17 апр. '09 в 21:38
источник

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

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

Переменные, объявленные с помощью let, имеют в качестве области действия блок, в котором они определены, а также в любых вложенных субблоках. Таким образом, пусть работает очень похоже на var. Основное отличие состоит в том, что область видимости переменной 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

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

+21
22 мар. '17 в 14:39
источник
  • Переменная не поднимается

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

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

+21
17 янв. '16 в 15:11
источник

Вот пример, чтобы добавить к тому, что уже написаны другие. Предположим, вы хотите создать массив функций adderFunctions, где каждая функция принимает один аргумент Number и возвращает сумму аргумента и индекс функции в массиве. Попытка сгенерировать 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 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 scope doesn't extend outside the for loop.
console.log(i); // => ReferenceError: i is not defined

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

Теперь изображение смешивает два поведения, и вы, вероятно, увидите, почему не рекомендуется смешивать новые let и const со старыми var в том же script. Это может привести к некоторому эффектно запутанному коду.

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

Не позволяйте этому случиться с вами. Используйте linter.

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

+15
18 авг. '14 в 0:58
источник

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

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

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

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

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

var может по-прежнему быть полезным, если вы уверены, что хотите использовать односвязную функцию при использовании замыкания в цикле (# 5) или для объявления внешне видимых глобальных переменных в вашем коде (# 4). Использование var для экспорта может быть вытеснено, если export мигрирует из пространства транспилера и на основной язык.

Примеры

1. Не использовать внешний ближайший закрывающий блок: Этот блок кода выдает опорную ошибку, потому что второе использование x происходит за пределами блока, где объявлено с помощью let:

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

Напротив, работает тот же пример с var.

2. Не использовать до объявления:
Этот блок кода выдаст ReferenceError до того, как код будет запущен, поскольку x используется до его объявления:

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

В отличие от этого, тот же пример с var анализирует и работает без каких-либо исключений.

3. Нет переоформления: Следующий код демонстрирует, что переменная, объявленная с помощью let, не может быть повторно описана позже:

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

4. Глобалы, не привязанные к 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. Простое использование с затворами: Переменные, объявленные с помощью var, не работают хорошо с замыканиями внутри циклов. Вот простой цикл, который выводит последовательность значений, которые переменная i имеет в разные моменты времени:

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

В частности, это выдает:

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

В JavaScript мы часто используем переменные значительно позже, чем когда они созданы. Когда мы это продемонстрируем, задерживая выход с замыканием, переданным на setTimeout:

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

... выход остается неизменным, пока мы придерживаемся let. Напротив, если бы мы использовали var i:

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

... цикл неожиданно выводит "i 5" пять раз:

i is 5
i is 5
i is 5
i is 5
i is 5
+13
22 мая '17 в 1:09
источник

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].

+11
08 июл. '16 в 0:21
источник

Область действия VS-блока:

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

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 

переменные с var :

Когда первая функция testVar получает testVar переменную foo, объявленную с помощью var, все еще доступна вне оператора if. Эта переменная foo будет доступна везде в рамках функции testVar.

переменные с let :

Когда вторая функция testLet переменная bar, объявленная с let, доступна только внутри оператора if. Поскольку переменные, объявленные с let являются блочными (где блок является кодом между фигурными скобками, например if{}, for{}, function{}).

let переменные не поднимаются:

Другое различие между var и let - переменные с объявленными, и let их не поднимают. Пример - лучший способ проиллюстрировать это поведение:

переменные с let not let hoisted:

console.log(letVar);

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

переменные с var do get hoist:

console.log(varVar);

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

Global let не привязывается к window:

Переменная, объявленная с let в глобальной области (которая является кодом, который не находится в функции), не добавляется как свойство в глобальном объекте window. Например (этот код находится в глобальной области):

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


Когда следует let использовать над var?

Используйте let over var всякий раз, когда вы можете, потому что он просто ограничен более конкретным. Это уменьшает потенциальные конфликты именования, которые могут возникать при работе с большим количеством переменных. var можно использовать, если вы хотите, чтобы глобальная переменная явно была на объекте window (всегда внимательно изучите, если это действительно необходимо).

+11
09 сент. '18 в 13:08
источник

Могут отображаться следующие две функции:

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
}
+11
17 дек. '15 в 3:22
источник

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

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

var x = 1;
var x = 2;

Это будет:

let x = 1;
let x = 2;
+7
11 авг. '15 в 0:35
источник

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

Ключевое слово let присоединяет объявление переменной к какому-либо блоку (обычно a { .. }), в котором он содержится. Другими словами, 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 для каждой итерации цикла переменная имеет область действия и имеет общую копию.

+6
22 мая '18 в 13:12
источник

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

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

Смотрите " Эмуляция частных интерфейсов ".

+6
14 окт. '16 в 5:01
источник

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

let и const - область действия блока.

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
+6
28 окт. '17 в 12:42
источник

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

Я знаю, что не тот ответ, который вы искали, но это, вероятно, самое важное. Если у вас ограниченное развертывание, где вы знаете, что каждый получает 1,7, то вы счастливый парень.

+5
04 июн. '18 в 9:16

пусть против вар. Все дело в сфере.

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

Посмотрите мой пример ниже и обратите внимание, как переменная lion (let) действует по-разному в двух console.logs; это выходит из области видимости во втором console.log.

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.
+3
18 апр. '19 в 0:49
источник

Некоторые хаки с 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 и setter с 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)
+3
21 июл. '16 в 17:42
источник

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
}
+2
17 дек. '17 в 10:47
источник

Я думаю, что термины и большинство примеров немного ошеломляют. Основная проблема, с которой я столкнулся лично, - это понимание, что такое "Блок". В какой-то момент я понял, что блоком будут любые фигурные скобки, кроме оператора IF. открывающая скобка { функции или цикла определит новый блок, все, что определено с помощью let внутри него, не будет доступно после закрывающей скобки } того же самого элемента (функции или цикла); Имея это в виду, было легче понять:

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
28 апр. '19 в 2:21
источник

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

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

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

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

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

+1
27 дек. '16 в 9:44
источник

enter image description here

Посмотрите на это изображение, я создал один очень простой пример для демонстрации переменных const и let. Как вы можете видеть, когда вы пытаетесь изменить переменную const, вы получите ошибку (Попытка переопределить "имя", которая является константой), но посмотрите на переменную let...

Сначала мы объявляем let age = 33, а затем присваиваем какое-то другое значение age = 34; , что нормально, у нас нет никаких ошибок, когда мы пытаемся изменить переменную let

+1
16 февр. '19 в 17:17
источник

Теперь я думаю, что лучше использовать область видимости переменных для блока операторов с помощью 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 here after, чтобы они имели аналогичную область видимости в JavaScript, как и другие языки, Java, С# и т.д.

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

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

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

Обратитесь к ES6 In Depth: let и const, чтобы лучше понять его.

+1
01 июл. '16 в 8:22
источник

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

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

+1
08 февр. '16 в 15:03
источник

Как уже упоминалось выше:

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

Example1:

В обоих моих примерах у меня есть функция myfunc. myfunc содержит переменную myvar 10. В моем первом примере я проверяю, равен ли myvar 10 (myvar==10). Если да, я agian объявляю переменную myvar (теперь у меня есть две переменные myvar), используя ключевое слово var и присваиваю ему новое значение (20). В следующей строке я напечатаю его значение на моей консоли. После условного блока я снова распечатываю значение myvar на моей консоли. Если вы посмотрите на выход myfunc, myvar имеет значение равное 20.

let keyword

Пример2: В моем втором примере вместо использования ключевого слова var в моем условном блоке объявляю myvar используя ключевое слово let. Теперь, когда я вызываю myfunc я получаю два разных выхода: myvar=20 и myvar=10.

Таким образом, разница очень проста, т.е. ее объем.

+1
07 авг. '18 в 10:25
источник

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

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

Давайте рассмотрим следующие случаи:

(function timer() {
    for(var i = 0; i <= 5; i++) {
        setTimeout(function notime() { console.log(i); }, i * 1000);
    }
})();


   Stack            VariableEnvironment //one VariablEnvironment for timer();
                                       // when the timer is out - the value will be the same value for each call
5. [setTimeout, i]  [i=5] 
4. [setTimeout, i]  
3. [setTimeout, i]
2. [setTimeout, i]
1. [setTimeout, i]
0. [setTimeout, i]

####################    

(function timer() {
    for (let i = 0; i <= 5; i++) {
        setTimeout(function notime() { console.log(i); }, i * 1000);
    }
})();

   Stack           LexicalEnvironment - each iteration has a new lexical environment
5. [setTimeout, i]  [i=5]       
                      LexicalEnvironment 
4. [setTimeout, i]    [i=4]     
                        LexicalEnvironment 
3. [setTimeout, i]      [i=3]       
                         LexicalEnvironment 
2. [setTimeout, i]       [i=2]
                           LexicalEnvironment 
1. [setTimeout, i]         [i=1]
                             LexicalEnvironment 
0. [setTimeout, i]           [i=0]

когда timer() вызывается, создается ExecutionContext, который будет содержать как VariableEnvironment, так и все LexicalEnvironments, соответствующие каждой итерации.

И более простой пример

Область действия функции

function test() {
    for(var z = 0; z < 69; z++) {
        //todo
    }
    //z is visible outside the loop
}

Блок Сфера

function test() {
    for(let z = 0; z < 69; z++) {
        //todo
    }
    //z is not defined :(
}
+1
11 мар. '19 в 16:52
источник
  • 1
  • 2

Посмотрите другие вопросы по меткам или Задайте вопрос