Перевод статьи A f*cking rant about f*cking const
vs f*cking let
с сайта https://jamie.build/ для css-live.ru, автор — Джеймс Кайл
Не хотел я быть автором этой заметки, но Крис меня вынудил, так что этот хмырь и есть главный виновник. А я просто попал под раздачу.
Но вы все изрядно перебираете с const
в своем JavaScript-коде, и меня это хоть самую чуточку, но бесит.
1. const
ни хрена не работает, и мы все это знаем
Для начала давайте признаем, что толку от const
ноль целых хрен десятых, и смысл ему мы просто выдумываем…
const ЭТО_НЕ_МЕНЯЕТСЯ = { верно: "?" } ЭТО_НЕ_МЕНЯЕТСЯ.верно = "а вот фиг"; ЭТО_НЕ_МЕНЯЕТСЯ.нафиг = "живите теперь с этим";
const
не предполагает какой-либо неизменности самого значения, оно лишь подразумевает неизменность привязки.
Которая… Ну, круто.
2. Линтеры вам тоже не помогут
Давайте заодно выкинем и идею, будто можно статически гарантировать, что значения const неизменяемы, с помощью линтера.
Как бы, ясное дело, в простом случае оно-то можно:
const FOO = { prop: true }; FOO.prop = false; // ОШИБКА ЛИНТИНГА >XD
Но тут, как бы… есть побочные эффекты, и какая-нибудь фигня вас обязательно настигнет.
export function mutatesProp(obj) { obj.prop = false; } import { mutatesProp } from './mutatesProp'; const FOO = { prop: true }; mutatesProp(FOO); // никакой ошибки линтинга :(
И да, системы типов вроде Flow и ЭйАТыПробовалTypeScriptНепременноПопробуйTypeScriptЯПишуНаТайпСкриптИЯБлинНевыносимСунуБашкуВМикроволновкуИБудуОратьTypeScript™ могли бы с этим помочь, но вот только… ни черта они не помогут… так чтооо…
3. Нет, от него нет толку для компиляторов
Вы можете подумать: «Но оно всё равно бывает полезно для оптимизации кода или еще чего-то».
Вы будете правы, думая, что из-за компиляторных оптимизаций оно стало бы интересным вариантом. Но…
Вы ошибаетесь, думая, что от const
есть хоть какой-либо толк для оптимизации компиляторов.
Определить привязку и выяснить, действительно ли она никогда не переприсваивается, и так уже проще простого. Все соответствующие оптимизации возможны и без всяких там const
.
Кроме того, V8 со товарищи делают эти оптимизации без const
уже давным-давно. Бенедикт, Франциска или еще кто-нибудь поправят, если я вру, но Babel точно уже такую фигню умеет.
4. Так что же нам делать?
Ну, для начала… ничего делать не нужно. Нет причин, по которым вам когда-либо пришлось бы использовать const
, и везде, где бы мы его ни использовали, с тем же успехом можно использовать и let
, на нашем коде это никак не скажется.
По правде, если вы бросите читать на этом месте и больше никогда не станете использовать const
и вообще задумываться об этом, вы сэкономите буквально целые… несколько минут жизни.
Но, типа… раз const
есть, то для чего-то же оно может пригодиться, правда? Оно вроде как может пригодиться для коммуникации между разработчиками.
Конечно.
5. Но то, что мы повадились сообщать с его помощью, пипец как раздражает
Итак, многие (ладно, не ты, особенный ты у нас засранец этакий) делают такую… штуку, когда просто меняют все let
-переменные, которые никогда не переприсваиваются, на const
.
let ответ = 42; никогдаНеМенятьОтвет(ответ); дальшеДелатьСЭтимЗначениемЕщеЧтоТо(ответ);
Увидят они вышеприведенный код и скажут: «на месте этого let
должен быть const
, чтобы читатель уже при объявлении переменной ответ
знал, что она никогда не изменится».
И многие из них настроят в своих линтерах это правило как обязательное при каждом объявлении переменной, иногда даже «исправляя» их автоматически.
const ответ = 42; никогдаНеМенятьОтвет(ответ); дальшеДелатьСЭтимЗначениемЕщеЧтоТо(ответ);
«Так-то лучше».
Но… лучше ли?
Действительно ли вы хотели сообщить, что ответ
никогда не должен меняться, или просто так совпало, что вы нигде его не меняли?
Что, если потом вы вернетесь к этому коду и решите, что менять ответ можно? Ведь теперь это const
и мы не знаем, не обломает ли это чьих-либо ожиданий от переменной ответ
, если мы ее поменяем.
Бывает множество привязок, которые нам ни разу не доводится изменять, но против изменения которых мы ничуть не возражаем. На деле, пожалуй, это справедливо для большинства ссылочных переменных. Это не главное, что обычно заботит ваш код.
Но автоматически навязывая это правило для каждой привязки, независимо от того, что на самом деле имел в виду автор, мы по сути выбрасываем на помойку возможность сообщить что-то полезное.
6. Так для чего на самом деле нам использовать const
?
Дать понять, что вы действительно задумали что-то неизменным — пожалуй, всё-таки здравая мысль.
Но чтобы оно передавало эту мысль, использовать его надо лишь там, где уместно.
const Я_ВООБЩЕ_ОХРЕНЕЮ_ЕСЛИ_ЭТО_ИЗМЕНИТСЯ = 42;
Если хотите несколько полезных правил, то вот лучшее, что у меня вышло:
1. Используйте const
только в самой верхней области видимости
const ЗДЕСЬ = "прекрасно"; function nested() { const НЕ_ЗДЕСЬ = "ума не приложу, зачем"; }
За всю жизнь не припомню случая, чтобы привязка, созданная внутри функции, расстроилась от своего изменения. Никогда не использую const во вложенных областях видимости и не собираюсь. Почему? Потому что мама меня воспитала как надо (взгляните, как я расставляю точки с запятой), вот почему.
2. Старайтесь не использовать let
в самой верхней области видимости
С другой стороны, если вам понадобился let
в самой верхней области видимости, это знак, что у вас что-то типа глобального синглтон-состояния, от которого могут быть проблемы.
let globalState = "эммм..."; function fn() { globalState = "так хрупко на вид, что и проверять страшно..."; }
И как бы… в общем, это и всё.
И ради всего на свете кроме распоследней фигни, умоляю, не навязывайте это с помощью линтера. Дайте людям сообщать то, что они хотят сообщить. А то вы все меня уже задолбали этой хренью.
А теперь отвалите.
P.S. Это тоже может быть интересно: