Есть ли причина использовать ключевое слово «var» в ES6?


261

Руководство Бабеля по ES6 гласит:

letэто новый var.

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

Я не вижу никакой причины для использования varв коде ES6. Даже если вы хотите охватить данную переменную для всей функции, вы можете сделать это let, поместив объявление в верхнюю часть функционального блока, что и должно быть в varлюбом случае, чтобы указать фактическую область действия. И если вы хотите поместить что-то более точное в forблок или что-то еще, то вы можете сделать это тоже.

Так что мой инстинкт - varвообще прекратить использовать при написании кода ES6.

У меня вопрос, я не прав? Есть ли законный случай, когда varпредпочтительнее let?


3
Я еще не пробовал это (поскольку я еще не пишу код ES6), но кажется, что использование varв качестве сознательного индикатора того, что эта переменная предназначена для охвата всей функции, может быть полезным соглашением о «самодокументировании» ,
Jfriend00

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

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

2
@RayToal Я согласен с 97% того, что говорит Кайл Симпсон, но его причины продолжать использовать varкажутся мне неясными , и их недостаточно для того, чтобы иметь в виду переменную третьего типа, которая прыгает вокруг. Вы можете охватить letцелую функцию a, просто поместив ее в верхнюю часть функции, что гораздо понятнее по замыслу, чем запись varв блоке (чтобы вывести ее из этого блока, чтобы затем использовать ее вне блока - странно) Он предупреждает, что если вы добавляете a letк функции, то «это просто позиция, которая сигнализирует о разнице, а не о синтаксисе», но я думаю, что это хорошо.
Каллум

2
@RayToal Я тоже прочитал эту статью (как раз перед чтением этой дискуссии), и я был очень разочарован его очень слабым аргументом в пользу var. примеры, которые он представляет для хранения, varкажутся надуманными и основаны на серьезных ошибках кодирования. Гораздо лучше столкнуться с ошибкой и быть вынужденной исправлять такие ошибки, чем использовать языковые функции, которые позволяют сойти с рук! Что дальше, посоветуйте обернуть все в try / catch, чтобы предотвратить сбои? Остальная часть этой ссылки хороша, но я совсем не согласен с этой конкретной частью.
Мёрре

Ответы:


217

Дуг Крокфорд обсуждает letна этом этапе своего выступления « Лучшие детали ».

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

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

( constтакже является новым и имеет область видимости блока. После let x = {'hi': 'SE'}того, как вы можете переназначить на x, а после const y = xвы не можете переназначить y. Это часто предпочтительнее, так как предотвращает случайное изменение чего-либо из-под вас. Но, чтобы быть понятным, вы все равно можете изменить объект, y.hi = 'SO'если только заморозить это.)

Реально, ваше впечатление на ES6 правильно: принять letи const. Прекратите использовать var.

другом выступлении «The Better Parts» Даг говорит, что ===было добавлено, а не исправлено проблем== . ==Дает некоторые «удивительные» результаты, так что просто примите ===.)


Показательный пример

Mozilla Developer Network приводит пример, где varработает не так, как задумано. Их пример является реалистичным, который устанавливает onclickобработчики на веб-странице. Вот небольшой тестовый пример:

var a = [];
(function () {
   'use strict';
   for (let i = 0; i < 5; ++i) { // *** `let` works as expected ***
     a.push( function() {return i;} );
   }
} ());
console.log(a.map( function(f) {return f();} ));
// prints [0, 1, 2, 3, 4]

// Start over, but change `let` to `var`.
// prints [5, 5, 5, 5, 5]

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


6
Он дает тот же ответ о принятии === вместо ==. Последний не работает, но комитет по стандартам ES не хотел его менять, поэтому они добавили === Не совсем уверены, что это значит. ==не сломан вообще. Его можно просто определить как equality comparison using coersionПроверить github.com/getify/You-Dont-Know-JS/blob/master/…
AmmarCSE

13
@AmmarCSE - это замечательный 39-страничный документ по неявным принуждениям. Кто может иметь в виду все это при программировании? Короче говоря, Даг имел в виду «неработающий», как резюмировано в stackoverflow.com/a/359509/1682419 , его легко получить, когда типы значений отличаются больше, чем мы предполагали. Можете ли вы предсказать все это? [ '1.0' == 1.0, [1.0] == 1.0, [1.0] == '1.0', ['1.0'] == 1.0, [null] == '', [null] == 'null', '00' == false, [] == [], [] == 0, [] == '', [] == false, [] == true, [010] - [4] == ' 4.0 ', !![0], !![1], [0] == true, [1] == true, 1 == [[1]], 0 == [[0]], '1' == [1] ]
Jerry101

2
Да, большинство из этих примеров включает в себя операнд массива. Результат легко понять, если взглянуть на toString и узнать, как он реализован для объектов . Однако, если это то, что подразумевается под сломанным, тогда я полностью понимаю, откуда это исходит. :-)
AmmarCSE

3
почему бы не использовать const, когда он не изменчив - просто спрашивать? Я имею в виду, реальный выбор это не между letи varа между let, varиconst
shabunc

4
varработает как задумано, но не так, как многие ожидают. Это ошибка юзабилити, а не ошибка реализации.
Jerry101

12

Если вы писали правильный код, вы, вероятно, сможете превратить все varоператоры в letоператоры без каких-либо семантических изменений.

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

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


5

Я не обязательно думаю, что вы ошибаетесь, но есть предостережения относительно использования var. По сути, letдолжно помочь разработчикам обойти глупость JavaScript, особенно с конфликтами имен. varКажется, он имеет большую область видимости, поскольку хочет перейти к области действия закрывающей функции. Будут времена, когда вам понадобится var, например, когда вам потребуется временная переменная, которая будет доступна в пределах блока внутри функции, в противном случае предпочтение letнад var поможет разработчикам в конфликтах имен. Проще говоря, пора ES6 представить let.


3
Температура varв блоке доступна внутри всей функции, а не в пределах блока. Это вводящая в заблуждение особенность.
Jerry101

1

Я склонен согласиться с тем, что в es6 следует использовать только «let». AFIK, переопределение «let» генерирует ошибку (что хорошо), в то время как с «var» вы просто переопределяете значение (хотя «строгий режим» в es5 тоже об этом позаботится).


-4

letозначает «пусть переменная равна». Это декларация, другими словами, инициализация и присваивание.

Он существует в отличие от того, constчто, конечно, означает «постоянный» - противоположность переменной.

Некоторые другие языки используют префикс к реальному объекту вместо объекта при объявлении его (например, defсокращение для «определения функции» - полностью отсутствует точка «def»).

Let добавляет это семантическое несоответствие в Javascript.

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

Проблема возникает из-за того, что varключевое слово было введено до того, как оно constбыло поддержано, поэтому обратная совместимость диктует, что varнеобязательно означает переменную. (Это также может быть использовано для назначения постоянного значения.)

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

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

Примечание: varне работает в блоках «стрелка», если вы хотите обрабатывать упомянутые блоки как замыкания (потому что varбыло введено до обработки блоков как замыкания), но letработает.


6
-1: педантичный, бесполезный и в первую очередь основанный на мнении.
Джоэл Мюллер

Фиджиарон просто шутит с нами здесь.
Jerry101

Я сочувствую вашей неприязни к лексической форме, letпотому что она не соответствует тону других ключевых слов в той же категории в JavaScript. Тем не менее, это не отвечает на вопрос, и не особенно хорошо поставлено. Проголосовано
Алуан Хаддад

3
letэто не просто разработчики, желающие больше сложности. Это на самом деле интуитивно понятнее, потому что когда вы зацикливаете и закрываете переменные, замыкание сохраняет последнее значение переменной var, но когда вы делаете то же самое над let, каждое замыкание в цикле имеет свое собственное значение для let, a ля примера от @ Jerry101 выше
TKoL
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.