Чи є причина використовувати ключове слово "var" в ES6?


260

Посібник Бабеля по ES6 говорить:

letє новим var.

Очевидно, єдина відмінність полягає в тому, що varвін привласнюється до поточної функції , в той час як letотримує масштаб до поточного блоку . У цій відповіді є кілька хороших прикладів .

Я не бачу причин використовувати varв коді ES6. Навіть якщо ви хочете прив’язати дану змінну до всієї функції, ви можете це зробити let, поставивши декларацію у верхній частині функціонального блоку, що саме ви повинні робити з тим, varщоб у будь-якому випадку вказати фактичну область застосування. І якщо ви хочете обміняти щось більш точне в forблоці чи щось таке, то можете зробити і це.

Тож мій інстинкт - varвзагалі припинити використання під час написання коду ES6.

Моє запитання: чи я помиляюся в цьому? Чи є законний випадок, де varбуло б кращим let?


3
Я ще не пробував цього (оскільки я ще не пишу код ES6), але здається, що використання varв якості свідомого індикатора того, що ця змінна призначена для визначення всієї функції, може бути корисною умовою "самодокументування ". .
jfriend00

10
Якщо ви ставите letзаяву прямо у верхній частині функції, я думаю, це так само очевидно, що ви мали намір застосувати її до всієї функції. Я не думаю, що використання varробить це більш зрозумілим, ніж просто розміщення його у верхній частині.
callum

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

2
@RayToal Я погоджуюся з 97% того, що говорить Кайл Сімпсон, але його причини продовжувати використовувати varмені здаються тонкими, і недостатньо, щоб гарантувати наявність третього типу змінної, яка стрибає навколо. Ви можете охопити letцілу функцію просто, розмістивши її у верхній частині функції, що набагато чіткіше за наміром, ніж писати varв блок (для того, щоб вона була виведена з цього блоку, щоб потім ви могли використовувати її поза блоком - дивно). Він попереджає, що якщо ви застосуєте функцію letдо функції, то "це просто позиція, яка сигналізує про різницю, а не синтаксис", але я думаю, що це добре.
callum

2
@RayToal Я теж прочитав цю статтю (безпосередньо перед читанням цієї дискусії), і я був дуже розчарований через його дуже слабкий випадок var. приклади, які він подає для зберігання, varздаються надуманими - і базуються на серйозних помилках кодування. Набагато краще зіткнутися з помилкою і змусити виправляти такі помилки, ніж використовувати мовні функції, які дозволяють людині піти з нею! Що далі, радимо загорнути все в спробу / ловити, щоб запобігти збоям? Решта цього посилання хороша, але я зовсім не згоден з цією частиною.
Mörre

Відповіді:


217

Даг Крокфорд обговорює letна цьому етапі у своїй розмові " Кращі частини ".

Справа в тому, щоб letуникнути джерела непорозумінь, особливо. для програмістів з очікуванням, встановленими мовами з блоком дії. varМає функцію сфери (він оголошує змінний , яку видно по всій функції) , навіть якщо вона виглядає , як це має блок сфери .

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

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

Реально ваше враження правильне для ES6: Прийняти letта const. Перестаньте використовувати var.

іншому виконанні "Кращих частин" Дуг говорить, чому ===додано, а не виправляти проблеми== . ==Дає певні "дивовижні" результати, тому просто прийняти ===.)


Приклад розкриття

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
Він дає ту саму відповідь щодо прийняття === замість ==. Останнє порушено, але комітет з питань європейських стандартів не хотів його змінювати, тому вони додали === Не зовсім впевнений, що це означає. ==зовсім не порушена. Його можна просто визначити як equality comparison using coersionCheck out 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] ]
Джеррі101

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, наприклад, коли вам потрібна змінна temp, яка буде доступною в межах блоку всередині функції, інакше перевага letнад var допоможе розробникам у конфліктуванні імен. Якщо говорити легше, то час, який ES6 представив let.


3
Температура varв блоці доступна всередині всієї функції, а не блокована. Це оманлива особливість.
Джеррі101

1

Я схильний погоджуватися, що в es6 слід використовувати лише "нехай". AFIK, переназначаючи "дозволити", генерує помилку (що добре), тоді як з "var" ви просто перекреслюєте цінність (хоча "суворий режим" в es5 теж переймається цим).


-4

letозначає "нехай змінна дорівнює". Це декларація, іншими словами, ініціалізація та призначення.

Він існує на відміну від того, constщо, звичайно, означає "константа" - що є протилежною змінній.

Деякі інші мови використовують префікс фактичного об'єкта замість об'єкта, коли оголошують його (наприклад def, це скорочення для "визначити функцію" - повністю пропущено пункт того, що "def".

Let додає цю семантичну непослідовність у Javascript.

За логікою, ви також можете дозволити постійній рівному чомусь, оскільки завдання ключового слова "нехай" - це присвоєння пам'яті.

Проблема виникає тому, що varключове слово, яке було введено раніше, constпідтримувалося, тому зворотність сумісності диктує, що varне потрібно означати змінну. (Це також може бути використане для призначення постійного значення.)

Отже, введення letв неправильне положення. Щоб переконатися, що ми пам’ятаємо, що лексично це неправильно, вони також вирішили змінити лексичну сферу letvs var, тому непослідовність є головним у нашій свідомості при налагодженні.

Іншими словами, letіснує тому, що люди (маючи на увазі мовні мовці) вважали, що Javascript занадто послідовний, оволодівши всіма своїми ідіомами та ідіосинкразіями, прагнуть більше.

Бічна примітка, varне працює в "стрілочних" блоках, якщо ви хочете трактувати ці блоки як закриття (тому що це varбуло введено до обробки блоків як зачинок), але letтак.


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

fijiaaron просто жартує з нами тут.
Джеррі101

Я співчуваю вашій неприязні до лексичної форми, letоскільки вона суперечить тону інших ключових слів тієї ж категорії в JavaScript. Все ж це не дає відповіді на питання і не особливо добре поставлене. Downvoted
Алуа Хаддад

3
letце не просто розробники, які бажають більшої складності. Це насправді інтуїтивно зрозуміліше, тому що, коли ви замикаєтесь і закриваєтесь на vars, закриття підтримує останнє значення var, але коли ви робите те саме над let, кожне закриття в циклі має своє значення для let, a la приклад @ Jerry101 вище
TKoL
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.