Использует ли использование 'let' over 'var' какое-либо реальное влияние на использование памяти [duplicate]

Как изменение разрешений символической ссылки в системе Linux не изменяет разрешения ссылки, а вместо этого указывает файл (в Ubuntu как минимум). Я думаю, что самым безопасным способом для этого было бы удалить ссылку и воссоздать ее с требуемой umask, чтобы получить желаемый результат.

Другую связанную запись можно найти , изменяя разрешения symlink в системе Linux

3270
задан 30 March 2018 в 09:31

18 ответов

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

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

ПРИМЕЧАНИЕ. Это пример обучения, предназначенный для демонстрации поведения var / let в циклах и закрытия функций, которые также будут легко понятны. Это был бы ужасный способ добавить числа. Но общая техника захвата данных при закрытии анонимных функций может встречаться в реальном мире в других контекстах. YMMV.
12
ответ дан 15 August 2018 в 16:15
  • 1
    @aborz: Также очень классный анонимный синтаксис функции во втором примере. Это то, к чему я привык в C #. Сегодня я чему-то научился. – Barton 20 February 2015 в 12:59
  • 2
    Исправление: Технически, синтаксис функции Arrow, описанный здесь = & gt; [D0] developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/&hellip – Barton 16 March 2015 в 10:58
  • 3
    На самом деле вам не нужно let value = i;. Оператор for создает лексический блок. – Toothbrush 23 October 2015 в 01:38

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

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

объяснение ключевого слова let в Википедии показывает, какие браузеры поддерживают Javascript 1.7.

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

131
ответ дан 15 August 2018 в 16:15
  • 1
    Ключевой бит текста из связанного документа, кажется, «позволяет работать очень похоже на var. Основное различие заключается в том, что область действия переменной var является всей охватывающей функцией ". – Michael Burr 18 April 2009 в 01:25
  • 2
    Хотя технически правильно сказать, что IE не поддерживает его, правильнее сказать, что это только расширение mozilla. – olliej 18 April 2009 в 03:56
  • 3
    @olliej, на самом деле Mozilla просто впереди игры. См. Стр. 19 из ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf – Tyler Crompton 19 June 2012 в 01:16
  • 4
    @TylerCrompton, это всего лишь набор слов, которые были зарезервированы годами. Когда добавлена ​​Mozilla, это было просто расширение mozilla, без соответствующей спецификации. ES6 должен определять поведение для операторов let, но это произошло после того, как Mozilla представила синтаксис. Помните, что у moz также есть E4X, который полностью мертв и только moz. – olliej 11 July 2012 в 23:49
  • 5
    IE11 добавила поддержку для let msdn.microsoft.com/en-us/library/ie/dn342892%28v=vs.85%29.aspx – eloyesp 24 December 2013 в 18:59

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

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

var x = 'global';
let y = 'global';
console.log(this.x); // "global"
console.log(this.y); // undefined
При использовании внутри блока, ограничивает область переменной это блок. Обратите внимание на разницу между let , область видимости которой находится внутри функции, где она объявлена.
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

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

16
ответ дан 15 August 2018 в 16:15

При использовании 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

Когда Использование let

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

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

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

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

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

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

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

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

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

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

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

3
ответ дан 15 August 2018 в 16:15
Переменная неподнимая 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) каждая итерация (предшествующая оценке выражения инкремента), больше подробности здесь.
38
ответ дан 15 August 2018 в 16:15
  • 1
  • 2
    Ип они поднимаются, но ведут себя так, как будто не поднимаются из-за (барабанного рулона) Temporal Dead Zone - очень драматичное имя для идентификатора, недоступного до его объявления :-) – Drenai 31 December 2016 в 19:42
  • 3
    Итак, пусть поднят, но недоступен? Как это иначе, чем «не поднято»? – N-ate 22 November 2017 в 01:46
  • 4
    Надеюсь, Брайан или Берги вернутся, чтобы ответить на этот вопрос. Является ли декларация о разрешении, но не заданием? Благодаря! – N-ate 22 November 2017 в 20:18
  • 5
    @ N-ate, Вот один пост Берги, может быть, вы можете найти в нем ответ. – zangw 23 November 2017 в 07:46

Если я прочитал спецификации прямо, то 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

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

3
ответ дан 15 August 2018 в 16:15

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

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

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

1
ответ дан 15 August 2018 в 16:15

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

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

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

40
ответ дан 15 August 2018 в 16:15
  • 1
    Также стоит отметить, что ECMAScript является стандартом, а let включен в проект 6-го издания и, скорее всего, будет в окончательной спецификации. – Richard Ayotte 31 March 2012 в 20:09
  • 2
    Вот в чем разница 3 года: D – olliej 13 April 2012 в 08:28
  • 3
    Просто остановился на этом вопросе, и в 2012 году все еще остается, что только браузеры Mozilla поддерживают let. Safari, IE и Chome - нет. – pseudosavant 13 July 2012 в 22:38
  • 4
    Идея случайного создания частичного объема блока при аварии является хорошей точкой, остерегайтесь, let не поднимается, чтобы использовать переменную, определенную в let, определенную в верхней части вашего блока. Если у вас есть оператор if, который больше, чем несколько строк кода, вы можете забыть, что вы не можете использовать эту переменную до тех пор, пока она не будет определена. БОЛЬШАЯ ТОЧКА !!! – Eric Bishard 7 May 2015 в 17:01
  • 5
    @EricB: yes и no: & quot; В ECMAScript 2015, let будет поднимать переменную до вершины блока. Однако ссылка на переменную в блоке перед объявлением переменной приводит к ReferenceError (моя заметка: вместо старого старого undefined). Переменная находится в «временной мертвой зоне» от начала блока до тех пор, пока декларация не будет обработана. & Quot; То же самое относится и к операторам switch, потому что есть только один базовый блок ". Источник: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… – GitaarLAB 21 May 2016 в 07:15

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

Это выиграло 'генерирует ошибку компиляции:

var x = 1;
var x = 2;

Это будет:

let x = 1;
let x = 2;
118
ответ дан 15 August 2018 в 16:15
  • 1
    относительно ответа v4: i Известно всюду в функциональном блоке! Он начинается с undefined (из-за подъема), пока вы не назначите значение! ps: let также поднимается (вверху блока, содержащего его), но будет давать ReferenceError при ссылке в блоке перед первым назначением. (ps2: Я про-полуколонный парень, но вам не нужна точка с запятой после блока). Это, как говорится, спасибо за добавление проверки реальности относительно поддержки! – GitaarLAB 21 May 2016 в 07:41
  • 2
    @GitaarLAB: Согласно Mozilla Developer Network : «В ECMAScript 2015 пусть привязки не подпадают под переменное подхват, а это означает, что объявления не перемещаются в верхнюю часть текущего контекста выполнения. ; - В любом случае, я сделал несколько улучшений в своем ответе, которые должны прояснить разницу в подъемном поведении между let и var! – John Slegers 27 February 2018 в 03:37
  • 3
    Ваш ответ значительно улучшился (я тщательно проверил). Обратите внимание, что в той же ссылке, на которую вы ссылались в своем комментарии, также говорится: «Переменная (let) находится в« временной мертвой зоне ». от начала блока до тех пор, пока не будет обработана инициализация. & quot; Это означает, что «идентификатор» (текстовая строка «зарезервирован» для указания «что-то») уже зарезервирован в соответствующей области, иначе он станет частью области root / host / window , Для меня лично «подъем» означает не что иное, как резервирование / связывание объявленных «идентификаторов» с их соответствующим объемом; исключая их инициализацию / назначение / модификацию! – GitaarLAB 1 March 2018 в 22:16
  • 4
    И .. + 1. Эта статья Кайла Симпсона, которую вы связали, является отличным чтением, спасибо за это! Также ясно, что временная мертвая зона " aka "TDZ". Одна интересная вещь, которую я хотел бы добавить: я прочитал в MDN, что let и const были рекомендованы, чтобы использовать их только тогда, когда вам действительно нужна их дополнительная функциональность , поскольку принудительное выполнение / проверка этих дополнительных функции (например, write-only const) приводят к «большей работе» (и дополнительным узлам-узлам в дереве областей) для (текущего) движка (-ов) для обеспечения / проверки / проверки / настройки. – GitaarLAB 1 March 2018 в 22:17

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

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

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 работает.

1. Без использования внешнего ближайшего закрывающего блока: Этот блок кода выдает 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

3. Нет повторной записи:

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

In 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 is 5» пять раз:

i is 5
i is 5
i is 5
i is 5
i is 5
11
ответ дан 15 August 2018 в 16:15
  • 1
    # 5 не вызвано состоянием гонки. Используя var вместо let, код эквивалентен: var i = 0; while (i < 5) { doSomethingLater(); i++; } i находится за закрытием, а к тому времени, когда doSomethingLater() выполняется, i уже увеличивается 5 раз, следовательно выход будет i is 5 пять раз. Используя let, переменная i находится внутри замыкания, поэтому каждый асинхронный вызов получает свою собственную копию i вместо использования «глобальной», созданной с помощью var. – Daniel T. 2 June 2017 в 04:12
  • 2
    @ DanielT: Я не думаю, что преобразование отмены определения переменной из инициализатора цикла объясняет что-либо. Это просто нормальное определение семантики for. Более точная трансформация, хотя и более сложная, является классической for (var i = 0; i < 5; i++) { (function(j) { setTimeout(_ => console.log( i, является $ {j} ), 125/*ms*/); })(i); }, которая вводит "запись активации функции" для сохранения каждого значения i с именем j внутри функции. – mormegil 25 July 2017 в 10:13

var - глобальная переменная с возможностью перемещения (hoist-able).

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

5
ответ дан 15 August 2018 в 16:15

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

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

Example1:

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

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

Таким образом, различие очень просто в его области.

1
ответ дан 15 August 2018 в 16:15

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

let x = 1;

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

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

console.log(x);
// expected output: 1
-2
ответ дан 15 August 2018 в 16:15
  • 1
    Это также поможет объяснить словами, что делает let, хотя это сделает его дубликатом другого ответа здесь – pushkin 31 May 2018 в 22:47

В ECMAScript 6 добавлено еще одно ключевое слово, чтобы объявить переменные, другие «const», кроме «let».

Основная цель введения «let» и «const» над «var» состоит в том, чтобы иметь вместо облачного лексического охвата. ECMAScript 6 .

10
ответ дан 15 August 2018 в 16:15
  • 1
    Еще один интересный момент: jsfiddle.net/6rk8wpso – Lcf.vs 8 February 2016 в 05:29
  • 2
    Для глубокого понимания на нем ссылайтесь на ссылку - davidwalsh.name/for-and-against-let – swaraj patil 1 July 2016 в 11:27
  • 3
    это первый раз, когда я когда-либо видел, что кто-то действует, как переменная затенение. нет, цель let - не включать затенение – John Haugeland 24 November 2016 в 04:37
  • 4
    цель? это конструкция, вы можете использовать ее, как вам угодно, один из интересных способов. – Dmitry 24 November 2016 в 04:39
  • 5
    Последняя часть первого предложения не понятна. Ты можешь починить это? – Peter Mortensen 26 November 2016 в 20:31
  • 6
    пожалуйста, что это значит let { type, name, value } = node;? вы создаете новый объект с 3 свойствами type / name / value и инициализируете их значениями свойств из узла? – AlainIb 15 June 2017 в 10:55

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

DEMO

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

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

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

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

DEMO (проверено в Chrome и Firefox 50)

'use strict';

for(let i = 1; i < 6; i++) {
  document.getElementById('my-element' + i)
    .addEventListener('click', function() { alert(i) })
}
452
ответ дан 15 August 2018 в 16:15
  • 1
    Это действительно здорово. Я ожидал бы "i & quot; который должен быть определен вне тела цикла, содержится в скобках и НЕ формировать «замыкание». вокруг "i". Конечно, ваш пример доказывает обратное. Я думаю, что это немного запутанно с точки зрения синтаксиса, но этот сценарий настолько распространен, что имеет смысл поддерживать его таким образом. Большое спасибо за это. – Karol Kolenda 27 July 2015 в 15:49
  • 2
    IE 11 поддерживает let, но он предупреждает «6». для всех кнопок. У вас есть источник, говорящий о том, как let должен вести себя? – Jim Hunziker 22 October 2015 в 16:29
  • 3
    Похоже, ваш ответ - правильное поведение: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… – Jim Hunziker 22 October 2015 в 16:32
  • 4
    На самом деле это общая ошибка в Javascript, и теперь я вижу, почему let будет действительно полезен. Установка прослушивателей событий в цикле больше не требует непосредственного вызова функции для локального определения области i на каждой итерации. – Adrian Moisa 21 February 2016 в 12:12
  • 5
    Использование & quot; let & quot; просто откладывает эту проблему. Таким образом, каждая итерация создает частную независимую область блока, но «i» переменная все еще может быть повреждена последующими изменениями внутри блока (при условии, что переменная итератора не является , обычно изменена внутри блока, но другие объявленные допустимые переменные внутри блока вполне могут быть) и любая функция, объявленная в пределах блок может, при вызове, исказить значение "i" для других функций, объявленных в блоке, потому что они делают совместно используют одну и ту же область частного блока, следовательно, такую ​​же ссылку на «i». – gary 8 September 2016 в 02:10

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
ответ дан 15 August 2018 в 16:15

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

Как вы можете видеть, переменная 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);

39
ответ дан 15 August 2018 в 16:15
  • 1
    На каком инструменте я смотрю здесь? – Barton 25 March 2015 в 01:43
  • 2
    Chrome devtools – vlio20 25 March 2015 в 01:44
  • 3
    Как разработчик настольных апплетов для Cinnamon, я не подвергался воздействию таких блестящих инструментов. – Barton 26 October 2017 в 07:20

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

{
  let a = 123;
};

console.log(a); // ReferenceError: a is not defined
98
ответ дан 15 August 2018 в 16:15
  • 1
    Принятый ответ объясняет этот момент. – TM. 4 June 2015 в 23:24
  • 2
    Принятый ответ НЕ объясняет этот момент в своем примере. Принятый ответ продемонстрировал это только в инициализаторе цикла for, резко сужая область применения ограничений let. Upvoted. – Jon Davis 22 September 2015 в 09:55
  • 3
    @ stimpy77 Он явно заявляет, что «разрешен до ближайшего охватывающего блока»; должен ли каждый способ, который проявляется, быть включенным? – Dave Newton 1 April 2016 в 00:32
  • 4
    было много примеров, и никто из них не продемонстрировал этого. Возможно, я мог бы поддержать как принятый ответ, так и этот? – Jon Davis 1 April 2016 в 00:38
  • 5
    Этот вклад демонстрирует, что "блок" может быть просто набором строк, заключенных в скобки; то есть его не нужно связывать с каким-либо управляющим потоком, контуром и т. д. – webelo 22 November 2017 в 18:37

Другие вопросы по тегам:

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