Это моя заметка, когда я узнал о различиях между var, let и const. Дайте мне знать, если это неправильно…
Проще говоря, различия ниже:
var
Переназначить → ○
Повторно объявить → ○
Область действия → Глобально/блокировать
Поднять → ○
разрешить
Переназначить → ○
Повторно объявить → ✗
Область действия → Блокировать
Поднять → ✗
const
Переназначить → ✗
Повторно объявить → ✗
Область действия → Блокировать
Поднять → ✗
вар
Самая большая особенность «var» — это подъем, который всегда меня смущает.
По данным MDN, это поясняется ниже.
Поскольку объявления переменных (и объявления в целом) обрабатываются до выполнения любого кода, объявление переменной в любом месте кода эквивалентно объявлению ее вверху. Это также означает, что переменная может казаться используемой до того, как она будет объявлена. Такое поведение называется «поднятием», так как кажется, что объявление переменной перемещается в начало функции или глобального кода.
Короче говоря, когда вы используете «var», он выполняется первым, что означает переход к началу ваших кодов. Если он объявлен глобально, он перемещается в начало глобального кода, если он находится в функции, он перемещается в начало области видимости функции.
Берем образец фрагмента из MDN.
function do_something() { console.log(bar); // undefined var bar = 111; console.log(bar); // 111 }
do_something();
В этом случае первый bar
не определен, потому что он поднят и перемещен в начало кода без присвоенного значения.
Второй bar
возвращает 111
, потому что он ссылается на назначенную переменную, которая находится сразу после первой консоли.
Если вы запустите этот код с помощью let или const, вы получите сообщение об ошибке Uncaught ReferenceError: Cannot access 'bar' before initialization
. Ошибка произошла при первом console.log(bar)
, так как при запуске ничего не назначалось, тогда как 'var' всегда автоматически перемещается наверх с undefined
.
Давайте взглянем на другой пример из MDN.
myName = 'Chris';
function logName() { console.log(myName); }
logName();
var myName;
Точно так же это работает нормально, потому что var myName
сначала идет в начало кода, а затем Chris
присваивается myName
. После этого вызывается logName()
и выводится Chris
.
Если это будет написано с помощью let
или const
... вы знаете, что произойдет, верно?
Допустим, если мы объявим var
, как показано ниже, что произойдет?
console.log(bar); // print 2: undefined
function do_something() { console.log(bar); // print 3: undefined var bar = 111; console.log(bar); // print 4: 111 }
var bar = "aaa"; console.log(bar); // print 2: aaa
do_something()
В этом случае первая консоль печатает undefined
, когда var bar = "aaa"
идет вверх, а вторая консоль чуть ниже var bar = "aaa"
печатает aaa
. Затем запустите do_something
, как мы видели ранее.
Важно то, что этого не произойдет с let
и const
.
Говоря о let
, говорят, что let
ведет себя почти так же, как var
, но есть, конечно, и исключения. Один из них — подъем, а другой — передекларация.
Давайте посмотрим на пример.
function varTest() { var x = 1; { var x = 2; // same variable! console.log(x); // 2 } console.log(x); // 2 // This is referring to the overwritten value }
function letTest() { let x = 1; { let x = 2; // different variable console.log(x); // 2 } console.log(x); // 1 // This is referring to the value in the scope }
function run() { var foo = "Foo"; let bar = "Bar";
console.log(foo, bar); // Foo Bar
{ var moo = "Mooo" let baz = "Bazz"; console.log(moo, baz); // Mooo Bazz }
console.log(moo); // Mooo console.log(baz); // ReferenceError }
run();
varTest
содержит блок внутри, а var
переопределяется как 2
. Если вы напечатаете переменную x
, она напечатает 2
, которая была повторно объявлена внутри блока.
Однако letTest
возвращает ошибку, если вы пытаетесь получить доступ к переменной x
, расположенной вне блока. Это потому, что на let
можно ссылаться только в блоке. Таким образом, вы можете получить доступ к let x = 2
и печатать, если вы используете консоль внутри блока. То же самое касается run()
.
Короче говоря, var
- поднимается в глобальную/блочную область
- может быть переобъявлен независимо от области действия
Из-за этих особенностей мы почти не используем var
в настоящее время, чтобы избежать изменения данных и путаницы.
пусть против константы
Теперь мы знаем, как ведет себя var
, но в чем разница между let
и const
?
Прежде чем рассматривать разницу, нам нужно сначала узнать особенность let
. Как упоминалось ранее, let
нельзя повторно объявить.
Но что, если мы просто используем переменную для изменения (переназначения) нового значения?
// Redeclaration let myName = 'Chris'; let myName = 'Bob'; // Throws the error
// Reassignment let myName = 'Chris'; myName = 'Bob'; console.log(myName); // Bob
Как видите, переназначение работает для let
.
И в этом отличие от const
. Если вы замените let
на const
, вы получите сообщение об ошибке Uncaught TypeError: Assignment to constant variable
.
Так просто, не так ли?
Однако здесь возникает путаница. const
нельзя переназначить какое-либо новое значение, но если вы запустите приведенный ниже код, он все равно будет работать нормально.
const array = []; array.foo = "bar";
console.log(array); // Print [foo: "bar"]
Почему он все еще работает?
Ну, это потому, что [array.foo](<https://array.foo>)
пытается добавить новое значение вместо переназначения. Поэтому в массив были добавлены ключ: foo и значение: 'bar'.
Вы могли видеть следующий пример.
const array2 = []; array2.push("bar2");
console.log(array2); // ["bar2"]
array2.pop(); console.log(array2); // []
В этом случае, хотя const
не допускает повторного назначения, вы все равно можете изменить содержимое const
, потому что вы просто изменяете содержимое.
Ок, const
нельзя переназначить а модифицировать, то если запустить ниже, все равно работает?
const array2 = {};
array2 = {foo: "bar"}; // error
В этом случае вы получаете ошибку, так как это считается переназначением. Если вы манипулируете им, вы можете сделать вот так.
const array2 = {};
array2.foo = "bar";
console.log(array2) // {"foo": "bar"}
Ссылка: Почему я могу изменить значение константы в javascript
Резюме
В современной веб-разработке var
больше не является стандартом, но почему-то эта тема все еще часто задается во время интервью по кодированию, особенно о подъеме и блокировании.
Кроме того, меня спросили об особенностях const
, которые мы видели в этом посте. Я думал, что const
является абсолютной переменной после ее объявления, но на самом деле это не так.
Надеюсь, это поможет кому-то хорошо понять переменные…
Удачного кодирования~!