What's the difference between using "let" and "var" to declare a variable in JavaScript?
962134 просмотра
30 ответа
ECMAScript 6 introduced the let
statement. I've heard it described as a "local" variable, but I'm still not quite sure how it behaves differently than the var
keyword.
What are the differences? When should let
be used over var
?
Ответы (30)
5112 плюса
The difference is scoping. var
is scoped to the nearest function block and let
is scoped to the nearest enclosing block, which can be smaller than a function block. Both are global if outside any block.
Кроме того, переменные, объявленные с помощью 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
вы сможете повторно объявить одну и ту же переменную в той же области видимости. С другой стороны, let
не будет
'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.
Автор: ThinkingStiff
Размещён: 12.07.2012 02:53
507 плюса
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) })
}
Автор: Gurpreet Singh
Размещён: 27.05.2015 10:16
138 плюса
Вот объяснение let
ключевого слова с некоторыми примерами.
пусть работает очень похоже на вар. Основное различие заключается в том, что область действия переменной var - это вся включающая функция
Эта таблица в Википедии показывает, какие браузеры поддерживают Javascript 1.7.
Обратите внимание, что только браузеры Mozilla и Chrome поддерживают его. IE, Safari и, возможно, другие нет.
Автор: Ben S Размещён: 17.04.2009 08:11135 плюса
Какая разница между 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 ), вы можете безопасно использовать это
let
утверждение, однако ваш код, вероятно, будет не оптимальным с точки зрения производительности.Если вы пишете код JavaScript на стороне клиента и не используете транспортер, вам следует подумать о поддержке браузера.
Сегодня, 8 июня 2018 года, все еще есть некоторые браузеры, которые не поддерживают let
!
Как отслеживать поддержку браузера
Актуальный обзор того, какие браузеры поддерживают let
оператор на момент прочтения этого ответа, см. На этой Can I Use
странице .
(*) Глобальные и функциональные переменные могут быть инициализированы и использованы до того, как объявлены, потому что переменные JavaScript подняты . Это означает, что объявления всегда находятся на вершине области видимости.
(**) Переменные области видимости не подняты
Автор: John Slegers Размещён: 23.02.2016 06:35104 плюса
В принятом ответе отсутствует точка:
{
let a = 123;
};
console.log(a); // ReferenceError: a is not defined
Автор: Lcf.vs
Размещён: 02.06.2015 08:59
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
блок-область и имеет 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
Автор: Michał Perłakowski
Размещён: 23.11.2016 10:52
42 плюса
Есть некоторые тонкие различия - область let
видимости ведет себя больше как переменная область видимости в более или менее любых других языках.
Например, он распространяется на вмещающий блок, они не существуют до их объявления и т. д.
Однако стоит отметить, что let
это только часть более новых реализаций Javascript и имеет различную степень поддержки браузера .
42 плюса
Вот пример различия между этими двумя (поддержка только началась для 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);
20 плюса
Переменная не поднимается 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) каждой итерации (прежде всего для вычисления выражения приращения), здесь есть больше деталей .
18 плюса
Основным отличием является различие в области видимости , в то время как let может быть доступен только внутри объявленной области видимости , как, например, в цикле for, к var можно получить доступ, например, вне цикла. Из документации в MDN (примеры также из MDN):
пусть позволяет объявлять переменные, которые ограничены в объеме на блок, заявления или выражения , на котором она используется. Это отличается от ключевого слова 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
Автор: Alireza Размещён: 22.03.2017 02:3914 плюса
Вот пример, чтобы добавить к тому, что уже написали другие. Предположим, вы хотите создать массив функций, 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
The process above doesn't generate the desired array of functions because i
's scope extends beyond the iteration of the for
block in which each function was created. Instead, at the end of the loop, the i
in each function's closure refers to i
's value at the end of the loop (1000) for every anonymous function in adderFunctions
. This isn't what we wanted at all: we now have an array of 1000 different functions in memory with exactly the same behavior. And if we subsequently update the value of i
, the mutation will affect all the adderFunctions
.
However, we can try again using the let
keyword:
// 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
This time, i
is rebound on each iteration of the for
loop. Each function now keeps the value of i
at the time of the function's creation, and adderFunctions
behaves as expected.
Now, image mixing the two behaviors and you'll probably see why it's not recommended to mix the newer let
and const
with the older var
in the same script. Doing so can result is some spectacularly confusing code.
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
Don't let this happen to you. Use a linter.
Автор: abroz Размещён: 18.08.2014 12:58NOTE: This is a teaching example intended to demonstrate the
var
/let
behavior in loops and with function closures that would also be easy to understand. This would be a terrible way to add numbers. But the general technique of capturing data in anonymous function closures might be encountered in the real world in other contexts. YMMV.
11 плюса
The difference is in the scope of the variables declared with each.
In practice, there are a number of useful consequences of the difference in scope:
let
variables are only visible in their nearest enclosing block ({ ... }
).let
variables are only usable in lines of code that occur after the variable is declared (even though they are hoisted!).let
variables may not be redeclared by a subsequentvar
orlet
.- Global
let
variables are not added to the globalwindow
object. let
variables are easy to use with closures (they do not cause race conditions).
The restrictions imposed by let
reduce the visibility of the variables and increase the likelihood that unexpected name collisions will be found early. This makes it easier to track and reason about variables, including their reachability(helping with reclaiming unused memory).
Consequently, let
variables are less likely to cause problems when used in large programs or when independently-developed frameworks are combined in new and unexpected ways.
var
may still be useful if you are sure you want the single-binding effect when using a closure in a loop (#5) or for declaring externally-visible global variables in your code (#4). Use of var
for exports may be supplanted if export
migrates out of transpiler space and into the core language.
Examples
1. No use outside nearest enclosing block:
This block of code will throw a reference error because the second use of x
occurs outside of the block where it is declared with let
:
{
let x = 1;
}
console.log(`x is ${x}`); // ReferenceError during parsing: "x is not defined".
In contrast, the same example with var
works.
2. No use before declaration:
This block of code will throw a ReferenceError
before the code can be run because x
is used before it is declared:
{
x = x + 1; // ReferenceError during parsing: "x is not defined".
let x;
console.log(`x is ${x}`); // Never runs.
}
In contrast, the same example with var
parses and runs without throwing any exceptions.
3. No redeclaration:
The following code demonstrates that a variable declared with let
may not be redeclared later:
let x = 1;
let x = 2; // SyntaxError: Identifier 'x' has already been declared
4. Globals not attached to 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. Easy use with closures:
Variables declared with var
do not work well with closures inside loops. Here is a simple loop that outputs the sequence of values that the variable i
has at different points in time:
for (let i = 0; i < 5; i++) {
console.log(`i is ${i}`), 125/*ms*/);
}
Specifically, this outputs:
i is 0
i is 1
i is 2
i is 3
i is 4
In JavaScript we often use variables at a significantly later time than when they are created. When we demonstrate this by delaying the output with a closure passed to setTimeout
:
for (let i = 0; i < 5; i++) {
setTimeout(_ => console.log(`i is ${i}`), 125/*ms*/);
}
... the output remains unchanged as long as we stick with let
. In contrast, if we had used var i
instead:
for (var i = 0; i < 5; i++) {
setTimeout(_ => console.log(`i is ${i}`), 125/*ms*/);
}
... the loop unexpectedly outputs "i is 5" five times:
i is 5
i is 5
i is 5
i is 5
i is 5
Автор: mormegil
Размещён: 22.05.2017 01:09
10 плюса
May the following two functions show the difference:
function varTest() {
var x = 31;
if (true) {
var x = 71; // Same variable!
console.log(x); // 71
}
console.log(x); // 71
}
function letTest() {
let x = 31;
if (true) {
let x = 71; // Different variable
console.log(x); // 71
}
console.log(x); // 31
}
Автор: Abdennour TOUMI
Размещён: 17.12.2015 03:22
10 плюса
let
is interesting, because it allows us to do something like this:
(() => {
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++);
}
}
}
})();
Which results in counting [0, 7].
Whereas
(() => {
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++);
}
}
}
})();
Only counts [0, 1].
Автор: Dmitry Размещён: 08.07.2016 12:218 плюса
Function VS block scope:
The main difference between var
and let
is that variables declared with var
are function scoped. Whereas functions declared with let
are block scoped. For example:
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
variables with var
:
When the first function testVar
gets called the variable foo, declared with var
, is still accessible outside the if
statement. This variable foo
would be available everywhere within the scope of the testVar
function.
variables with let
:
When the second function testLet
gets called the variable bar, declared with let
, is only accessible inside the if
statement. Because variables declared with let
are block scoped (where a block is the code between curly brackets e.g if{}
, for{}
, function{}
).
let
variables don't get hoisted:
Another difference between var
and let
is variables with declared with let
don't get hoisted. An example is the best way to illustrate this behavior:
variables with let
don't get hoisted:
console.log(letVar);
let letVar = 10;
// referenceError, the variable doesn't get hoisted
variables with var
do get hoisted:
console.log(varVar);
var varVar = 10;
// logs undefined, the variable gets hoisted
Global let
doesn't get attached to window
:
A variable declared with let
in the global scope (which is code that is not in a function) doesn't get added as a property on the global window
object. For example (this code is in global scope):
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
When should
let
be used overvar
?
Use let
over var
whenever you can because it is simply scoped more specific. This reduces potential naming conflicts which can occur when dealing with a large number of variables. var
can be used when you want a global variable explicitly to be on the window
object (always consider carefully if this is really necessary).
6 плюса
It also appears that, at least in Visual Studio 2015, TypeScript 1.5, "var" allows multiple declarations of the same variable name in a block, and "let" doesn't.
This won't generate a compile error:
var x = 1;
var x = 2;
This will:
let x = 1;
let x = 2;
Автор: RDoc
Размещён: 11.08.2015 12:35
5 плюса
var
is global scope (hoist-able) variable.
let
and const
is block scope.
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 плюса
When Using let
The let
keyword attaches the variable declaration to the scope of whatever block (commonly a { .. }
pair) it's contained in. In other words,let
implicitly hijacks any block's scope for its variable declaration.
let
variables cannot be accessed in the window
object because they cannot be globally accessed.
function a(){
{ // this is the Max Scope for let variable
let x = 12;
}
console.log(x);
}
a(); // Uncaught ReferenceError: x is not defined
When Using var
var
and variables in ES5 has scopes in functions meaning the variables are valid within the function and not outside the function itself.
var
variables can be accessed in the window
object because they cannot be globally accessed.
function a(){ // this is the Max Scope for var variable
{
var x = 12;
}
console.log(x);
}
a(); // 12
If you want to know more continue reading below
one of the most famous interview questions on scope also can suffice the exact use of let
and var
as below;
When using let
for (let i = 0; i < 10 ; i++) {
setTimeout(
function a() {
console.log(i); //print 0 to 9, that is literally AWW!!!
},
100 * i);
}
This is because when using let
, for every loop iteration the variable is scoped and has its own copy.
When using var
for (var i = 0; i < 10 ; i++) {
setTimeout(
function a() {
console.log(i); //print 10 times 10
},
100 * i);
}
This is because when using var
, for every loop iteration the variable is scoped and has shared copy.
4 плюса
If I read the specs right then let
thankfully can also be leveraged to avoid self invoking functions used to simulate private only members - a popular design pattern that decreases code readability, complicates debugging, that adds no real code protection or other benefit - except maybe satisfying someone's desire for semantics, so stop using it. /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
See 'Emulating private interfaces'
Автор: Daniel Sokolowski Размещён: 14.10.2016 05:013 плюса
Some hacks with 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 and setter with let
:
let jar = {
numberOfCookies: 10,
get cookies() {
return this.numberOfCookies;
},
set cookies(value) {
this.numberOfCookies = value;
}
};
console.log(jar.cookies)
jar.cookies = 7;
console.log(jar.cookies)
Автор: zloctb
Размещён: 21.07.2016 05:42
2 плюса
let is a part of es6. These functions will explain the difference in easy way.
function varTest() {
var x = 1;
if (true) {
var x = 2; // same variable!
console.log(x); // 2
}
console.log(x); // 2
}
function letTest() {
let x = 1;
if (true) {
let x = 2; // different variable
console.log(x); // 2
}
console.log(x); // 1
}
Автор: vipul jain
Размещён: 17.12.2017 10:47
1 плюс
Previously there were only two scopes in JavaScript, i.e. functional and global. With 'let
' keyword JavaScript has now introduced block-level
variables.
To have a complete understanding of the 'let' keyword, ES6: ‘let’ keyword to declare variable in JavaScript will help.
Автор: Hitesh Garg Размещён: 08.02.2016 03:031 плюс
Now I think there is better scoping of variables to a block of statements using 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
}
I think people will start using let here after so that they will have similar scoping in JavaScript like other languages, Java, C#, etc.
People with not a clear understanding about scoping in JavaScript used to make the mistake earlier.
Hoisting is not supported using let
.
With this approach errors present in JavaScript are getting removed.
Refer to ES6 In Depth: let and const to understand it better.
Автор: swaraj patil Размещён: 01.07.2016 08:221 плюс
This article clearly defines the difference between var, let and const
const
is a signal that the identifier won’t be reassigned.
let
, is a signal that the variable may be reassigned, such as a counter in a loop, or a value swap in an algorithm. It also signals that the variable will be used only in the block it’s defined in, which is not always the entire containing function.
var
is now the weakest signal available when you define a variable in JavaScript. The variable may or may not be reassigned, and the variable may or may not be used for an entire function, or just for the purpose of a block or loop.
https://medium.com/javascript-scene/javascript-es6-var-let-or-const-ba58b8dcde75#.esmkpbg9b
Автор: anandharshan Размещён: 27.12.2016 09:441 плюс
As mentioned above:
The difference is scoping.
var
is scoped to the nearest function block andlet
is scoped to the nearest enclosing block, which can be smaller than a function block. Both are global if outside any block.Lets see an example:
Example1:
In my both examples I have a function myfunc
. myfunc
contains a variable myvar
equals to 10.
In my first example I check if myvar
equals to 10 (myvar==10
) . If yes, I agian declare a variable myvar
(now I have two myvar variables)using var
keyword and assign it a new value (20). In next line I print its value on my console. After the conditional block I again print the value of myvar
on my console. If you look at the output of myfunc
, myvar
has value equals to 20.
Example2:
In my second example instead of using var
keyword in my conditional block I declare myvar
using let
keyword . Now when I call myfunc
I get two different outputs: myvar=20
and myvar=10
.
So the difference is very simple i.e its scope.
Автор: N Randhawa Размещён: 07.08.2018 10:250 плюса
Посмотрите на это изображение, я создал один очень простой пример для демонстрации const
и let
переменных. Как вы можете видеть, когда вы пытаетесь изменить const
переменную, вы получите ошибку ( Попытка переопределить «имя», которая является константой ), но посмотрите на let
переменную ...
Сначала мы объявляем let age = 33
, а затем присваиваем какое-то другое значение age = 34;
, что нормально, у нас нет никаких ошибок, когда мы пытаемся изменить let
переменную
0 плюса
Поскольку в настоящее время я пытаюсь получить глубокое понимание 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(var z = 0; z < 69; z++) {
//todo
}
//z is not defined :(
}
Автор: Lucian Nut
Размещён: 11.03.2019 04:52
-1 плюса
ECMAScript 6 добавил еще одно ключевое слово для объявления переменных, отличных от «const», кроме «let».
Основная цель введения «let» и «const» вместо «var» состоит в том, чтобы иметь блок-область видимости вместо традиционной лексической области видимости. Эта статья очень кратко объясняет разницу между «var» и «let», а также обсуждает «const» .
Автор: Gurucharan M K Размещён: 19.05.2016 11:41-1 плюса
Проверить эту ссылку в MDN
let x = 1;
if (x === 1) {
let x = 2;
console.log(x);
// expected output: 2
}
console.log(x);
// expected output: 1
Автор: Nurlan
Размещён: 18.05.2018 07:27
-1 плюса
Я хочу связать эти ключевые слова с контекстом выполнения, потому что контекст выполнения важен во всем этом. Контекст выполнения имеет две фазы: фаза создания и фаза выполнения. Кроме того, каждый контекст выполнения имеет переменную среду и внешнюю среду (свою лексическую среду).
На этапе создания контекста выполнения var, let и const будут по-прежнему сохранять свою переменную в памяти с неопределенным значением в среде переменных данного контекста выполнения. Разница заключается в фазе исполнения. Если вы используете ссылку на переменную, определенную с помощью var, прежде чем ей будет присвоено значение, она будет просто неопределенной. Никаких исключений не будет.
Однако вы не можете ссылаться на объявленную переменную с помощью let или const, пока она не будет объявлена. Если вы попытаетесь использовать его до того, как он будет объявлен, тогда будет возникать исключительная ситуация на этапе выполнения контекста выполнения. Теперь переменная по-прежнему будет в памяти, благодаря фазе создания контекста выполнения, но механизм не позволит вам использовать ее:
function a(){
b;
let b;
}
a();
> Uncaught ReferenceError: b is not defined
Если переменная определена с помощью var, Engine не сможет найти переменную в переменной среде текущего контекста выполнения, то он пойдет вверх по цепочке областей действия (внешняя среда) и проверит переменную среду внешней среды. Если он не может найти его там, он продолжит поиск в Scope Chain. Это не относится к let и const.
Вторая особенность let - это ввод области блока. Блоки определяются фигурными скобками. Примеры включают функциональные блоки, блоки if, для блоков и т. Д. Когда вы объявляете переменную с помощью let inside блока, переменная доступна только внутри блока. Фактически, каждый раз, когда блок запускается, например, в цикле for, он создает новую переменную в памяти.
ES6 также вводит ключевое слово const для объявления переменных. const также является областью действия блока. Разница между let и const заключается в том, что переменные const должны быть объявлены с использованием инициализатора, иначе это вызовет ошибку.
И, наконец, когда дело доходит до контекста выполнения, переменные, определенные с помощью var, будут присоединены к объекту 'this'. В глобальном контексте выполнения это будет объект окна в браузерах. Это не относится к let или const.
Автор: Donato Размещён: 13.02.2019 04:07Вопросы из категории :
- javascript Как определить, какой из указанных шрифтов был использован на веб-странице?
- javascript Валидация клиентской стороны ASP.Net
- javascript Длина объекта JavaScript
- javascript Получение текста из выпадающего списка
- scope Почему переменные не объявлены в «try» в области «catch» или «finally»?
- scope Как работают закрытия JavaScript?
- scope Область видимости переменной Bash
- scope Краткое описание правил оглавления?
- ecmascript-6 What's the difference between using "let" and "var" to declare a variable in JavaScript?
- ecmascript-6 Конечно, у ES6 + должен быть способ объединить два объекта javascript вместе, что это?
- ecmascript-6 Расширяющий класс JavaScript
- ecmascript-6 Что делают фигурные скобки в выражениях `var {...} = ...`?
- var Use of var keyword in C#
- var Какова область видимости переменных в JavaScript?
- var Почему ReSharper хочет использовать «var» для всего?
- let Есть ли в Python эквивалент Haskell 'let'
- let Смущена разница между let и let * в схеме
- let Операторы let позволяют создавать свойства на глобальном объекте?