CSS-live.ru

Как меня задолбало противопоставление хренова const чертову let

Перевод статьи 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. Это тоже может быть интересно:

16 комментариев

  1. Похоже это похлеще холивара tabs vs spaces. Автор истеричка :) Мне const именно в контексте «статичная привязка» помогал облагораживать алгоритмы/что-угодно. Дисциплинирует не гадить в коде. Впрочем «А теперь отвалите» — ок, отваливаем :) За огнетушителем…

  2. Забавная статья и классный перевод. Как по мне, тема философская, использовать const, аль нет и когда. Интересно было бы взглянуть на этот же вопрос после того, как выпустят вот это предложение (дополнение ?) к ES — https://github.com/keithamus/proposal-object-freeze-seal-syntax (если вообще выпустят). Вот тогда можно будет создавать реальные константы с объектами в более-менее удобном синтаксисе.

    1. > тогда можно будет создавать реальные константы

      const сейчас и так создаёт реальные константы, привязка значения константная, а то, что значение может меняться внутри, так это уже другая тема. Для меня как-то дико, что у коллег столько проблем с пониманием этого.

      1. Обычно под константной понимается некая величина, у которой не меняется именно содержимое, а не привязка к этому содержимому. Я не знаю примеров из других языков, где поведение было бы такое же, как и в JS, но интуитивно по слову «константа» сложно понять, что содержимое может меняться, а привязка нет. Если бы выбрали иное слово, то и проблем с пониманием было бы меньше. ИМХО.

        1. Не знаю почему, но для меня именно текущее поведение было и остаётся наиболее ожидаемым. Видимо на 12-м году регулярной работы с javascript в мозгу человека происходят уже необратимые изменения :).

        2. const foo = {bar: ‘baz’}
          foo.bar = ‘qwe’
          Константа foo хранит ССЫЛКУ на объект, а не сам объект. Когда меняем значение объекта, ссылка в константе не меняется. Автору статьи нужно начать изучение javascript с азов.

  3. На мой взгляд автор не правильно понимает когда нужно использовать const. Мой поинт: const нужно использовать при написании кода в функциональном стиле,  для того чтобы не было изменяемого состояния, и приходилось думать в другом ключе. Поправьте, если фигню сморозил.

      1. И в чём они вредные? Автор как раз за минимизацию использования const в не функциональном коде (прямо он о стиле не говорит, так что речь явно про обычный js, без всяких каррирований, иммутабельности и прочей функциональщины). Предлагает использовать их только на верхнем уровне модулей, что в общем-то действительно полезно. Проблема сейчас в том, что очень много не особо сильных специалистов повёрнутых на хайпе, они совершенно бездумно хватаются за всё новое, ведь это стильно-модно-молодёжно, а зачем это реально было создано они не хотят задумываться. Здесь может толком и не объясняется где это реально нужно, зато неплохо показано почему этому не место там, куда такие спецы бездумно это лепят. К слову, однажды попав в проект где как раз по максимуму пытались использовать const, я довольно быстро пришёл почти идеально к тем же выводам и доводам, что и в статье, а вот убедить в этом остальную команду оказалось совсем не просто, теперь можно просто давать ссылку.

  4. Тут ведь еще что. Из-за этой идеи-фикс ты по идее должен при объявлении каждой чертовой переменной думать — будет ли она меняться или нет? Нужно представить, что ты с ней будешь делать, все варианты, все сценарии спрогнозировать — вырви мозг.

  5. Ну, все эти проблемы от того, что сам язык убогий как бэ. Вложенные константы, отсутствие интерфейсов, классов (да-да в ес6 их тоже нет, это лишь синтаксический сахар над прототипным наследованием), отсутствие области видимости (приват, протектед), нет импорта (да-да в ес6 хоть и есть попыька его описать, но на практике браузеры не поддерживают импорт), слабая типизация и ещё целый вагон всего… Отсюда и 100500 новых фреймворков, которые по сути являются жалкими велосипедами, которые пытаются заткнуть эти дыры языка.

    Порой очень жалею, что actionscript ушел в небытие. Писать на js и as например это как жопу с пальцем сравнить.

    Отсюда и все проблемы на фронте.

    Хотя, мне ума хватило и я ушел на си и забыл этот весь адовый ваш фронт как страшный сон. Надоело вариться в этом дерьме, когда есть нормальные языки, где можно писать логику приложения, а не изобретать велосипеды

     

    1. Единственная действительно значимая проблема — отсутствие типизации (сюда входит в тч. отсутствие интерфейсов), и она успешно решается typescript-ом. На actionscript много писал, значимой разницы с typescript-ом не вижу. Typescript существует уже несколько лет, а фреймворки продолжают появляться (в тч. на нём). Так может не в языке проблема?

  6. Ну const и задумывалась так. Цель не ограничить изменяемость объекта, который содержит переменная. Цель — именно запретить перезапись этой переменной. Не знаю кто использует ее иначе :\

Оставить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Получать новые комментарии по электронной почте. Вы можете подписаться без комментирования.