Заблуждения о языке Javascript · Xam React CoE
Разоблачение распространенных заблуждений, ошибочных убеждений и неправильного использования языка NodeJS/Javascript/Typescript.
📢 Целевая аудитория
Инженеры-программисты NodeJS/Javascript/Typescript и разработчики js/ts утилит и плагинов для линтинга.
ℹ️ Введение
Слишком часто я вижу неправильное использование языка js/ts, основанное на одном или нескольких из:
- Непонимание языка.
- Введено в заблуждение чрезмерно самоуверенными разработчиками, которые неправильно понимают язык.
- Плохо обоснованные стандарты кодирования или настройки библиотеки linting по умолчанию (обычно предназначены для людей с минимальным пониманием языка).
Этот документ направлен на развенчание таких заблуждений для всех, кто хочет учиться.
🤔 Обоснование
Причины понимать язык и правильно его использовать включают в себя:
- Основная причина заключается в оптимизации эффективности разработчика, минимизации
- нажатий клавиш
- времени, затрачиваемом на рефакторинг
- времени, потраченном на проверку кода
- исправлении ошибок и других доработки или итерации кода.
— Время на проверку справочного руководства — путем культивирования хорошего понимания языка. - Оптимизировать нагрузку и задержку синтаксического анализатора и компилятора за счет
— сокращения количества символов без снижения читаемости кода
– использования оптимальных стратегий производительности ресурсов - Оптимизировать потребление ресурсов за счет
– сокращения объема кода
– уменьшения пропускной способности при передаче данных
– использования стратегий оптимальной производительности ресурсов во время выполнения. - Используйте языковые функции надлежащим образом
❌ Заблуждения
👎 Двойная кавычка должна быть предпочтительнее, чем одинарная кавычка
Начнем с простого и очевидного.
В js/ts символы двойной кавычки “
и одинарной кавычки ‘
эквивалентны, поэтому можно использовать любой из них.
Есть 2 веских аргумента в пользу того, почему следует предпочесть одинарные кавычки:
- Эффективность:
для ввода одинарной кавычки требуется 1 нажатие клавиши, а для ввода двойной кавычки — 2 нажатия клавиши.
Символы кавычек часто вводятся в js/ts.
Использование одинарных кавычек значительно сокращает количество нажатий клавиш, которые потребуются в ходе вашей карьеры разработчика? - Удобство:
Двойные кавычки появляются в строках чаще, чем одиночные символы, и особенно в HTML (атрибутах), для рендеринга которых часто используется js/ts.
Таким образом, инкапсуляция строк в Одинарные кавычки предотвращают необходимость избегать двойных кавычек.
Итак, должен ли я строго применять только одинарные кавычки?
Нет, это отключает языковую функцию, потому что в случае, если строка содержит одинарные кавычки, вы захотите заключить ее в двойные кавычки.
По этой причине я рекомендую разрешить любой из них и предпочесть одиночный.
Как настроить это в eslintrc.js
quotes: ['error', 'single', {avoidEscape: true}]
👎 == никогда нельзя разрешать, используйте только ===
Нет, применение Tripple Equals (строгое равенство) только отключает замечательную языковую функцию.
В js/ts операторы равенства ==
и !=
проверяют, равны ли (или не равны) 2 значения в рамках определенного набора правил.
Точно так же операторы строгого равенства ===
и !==
применяют те же проверки, но дополнительно требуют, чтобы значения также удовлетворяли проверке типа.
Оба оператора являются очень удобными функциями языка. Поэтому, когда я вижу, как разработчик применяет оператор строгого равенства в каждом случае, становится ясно, что разработчик просто не понимает языка или, по крайней мере, оператора равенства.
👍Некоторые практические правила:
'this string'
не делает==
ничего, кроме'this string'
undefined
делает==
null
'42'
делает==
42- Чаще всего подходит Равенство
==
или Истина/Ложь (поясняется ниже).
Итак, где ==
полезен?
Если вы считаете null и undefined одинаковыми (ПРИМЕЧАНИЕ: вместо этого вам может понадобиться Falsy или Truthy):
const val: undefined|null = undefined; if (val == null) console.log('val is undefined or null');
Если вы работаете с числами, и значения могут храниться в виде строк, например. если вы загрузили их из ключей объекта, файла, JSON, вызова API или какого-либо анализа:
const num = 42; const strNum = '42'; if (num == strNum) console.log('num == strNum'); // you could do a type conversion and type check but its overkill if (num === +strNum) console.log('num === +strNum');
Если вы знаете, что одна из переменных является строкой:
const val: any = aVarOfUnknownTypeAndValue; // no need for type check as only 'Hi' is equal const isStrHi = val == 'Hi'; // no need for type check as only 'string' is equal const isStr = 'string' == typeof aVarOfUnknownTypeAndValue;
Если вы работаете со ссылками на объекты:
const objA = {a: 1}; const refA = objA; const objB = {...objA}; if (objA == refA) console.log('objA == refA'); if (objA != objB) console.log('objA != objB');
ПРИМЕЧАНИЕ: для глубокого сравнения значений объектов вам понадобится что-то вроде lodash.isEqual();
А где ===
пригодится?
Операторы строгого равенства ===
и !==
имеют гораздо меньше вариантов использования, и вы обнаружите, что вам редко нужно их использовать.
Тем не менее, у него, безусловно, есть свои приложения…
В редком и, возможно, плохо спроектированном или неудачном случае, когда вам важно, является ли значение неопределенным или нулевым:
const val: undefined|null = funcThatReturnsUndefinedOrNull(); if (val === null) console.log('val is null'); else console.log('val is undefined');
В случае, когда вы не хотите, чтобы строковый номер считался таким же, как число:
const num = 42; const strNum = '42'; if (num !== strNum) console.log('num !== strNum');
Следующее можно запомнить как краткое изложение того, когда использовать операторы строгого равенства:
- Переменные являются примитивными типами данных, и
- Значение и тип каждой переменной неизвестны, и
- Номера строк не должны считаться равными их эквивалентным числам (
‘42’
считается не равным42
), и undefined
следует считать не равнымnull
.
type Primitive = undefined|null|boolean|string|number|symbol; const left: Primitive = valueA; const right: Primitive = valueB; const same = left === right;
Сравнительная таблица
Как отключить принудительные проверки строгого равенства в eslintrc.js
eqeqeq: 0
👎 Truthy и Falsy не следует использовать для проверки состояния.
Это распространенное заблуждение, что все или определенные проверки условий должны оцениваться как логическое значение, и это еще один случай, когда замечательная функция языка отключается. Например:
if (thisMustBeABoolean) // X Wrong doSomething(); // and thisMustAlsoBeABoolean ? go() : stop(); // X Wrong
Truthy и Falsy — отличные возможности языка Javascript, если вы изучали язык и понимаете их.
На самом деле, в большинстве тестов условий Истинная/Ложная проверка будет более подходящей, чем проверки Равенства или Строгого Равенства.
👍Практические правила:
- Спросите себя: «Чего я пытаюсь достичь с помощью проверки состояния?»
- Спросите, какие значения может содержать переменная и как каждое из них может быть оценено.
Пример
Вот один из многих примеров, когда предпочтение отдается правде/лжи…
Случай: Вы хотите сообщить о сообщении, если у вас есть сообщение, о котором нужно сообщить:
const message: undefined|null|string = getError(); // WRONG: message may be null or '' if ('undefined' != typeof message) console.error(message); // WRONG: message may be '' if ('string' == typeof message) console.error(message); // WRONG: message may be null or '' if (message === undefined) console.error(message); // WRONG: message may be '' if (message == undefined) console.error(message); // OK but complete overkill when js provides truthy/falsy if ('string' == typeof message && message.length > 0) console.error(message); // CORRECT if (message) console.error(message);
Как убедиться, что Truthy/Falsy работает в .eslintrc.js
'@typescript-eslint/strict-boolean-expressions': 0
👎 Для отступов следует использовать пробелы, а не вкладки
Еще одно не продуманное представление.
Есть несколько веских аргументов в пользу того, почему отступы табуляции предпочтительнее пробелов:
- Эффективность разработчика:
Таблица состоит из одного символа, отступ пробела — 2, 4 или 8.
Таким образом, набор текста или перемещение (с помощью клавиш со стрелками) отступа пробела — это дополнительные нажатия клавиш. - Дисковое пространство:
Размер файла (предварительная минимизация) больше, он содержит в 2, 4 или 8 раз больше символов отступа. - Загрузка процессора.
В вашей среде IDE, компиляторе Typescript и синтаксическом анализаторе javascript приходится обрабатывать больше символов и, следовательно, больше нагрузки.
Вы можете возразить, что ваша IDE позаботится об отступах. Вы нажимаете Tab, и он рисует для вас 2, 4 или 8 пробелов (в зависимости от ваших настроек). И если вы никогда не редактируете код вне настроенной вами IDE, и вас не смущает дополнительная нагрузка на вашу IDE или компьютер, то это не имеет значения, верно? Я согласен, если вы нажмете вкладку и получите 2/4/8 пробелов, то это действительно не имеет значения, так что вы можете просто нарисовать вкладку и, таким образом, уменьшить размер файла и нагрузку на процессор в вашей среде IDE, компиляторе ts, и парсер js. Если это не имеет значения, то зачем без необходимости преобразовывать вкладки в пробелы?
Я обнаруживаю, что пишу и/или перемещаюсь по коду вне моего редактора в нескольких сценариях:
- В отчетах об ошибках/логах
- Онлайн-редакторы как песочницы
- Я часто подключаюсь к серверу по ssh для отладки кода с помощью nano или vim.
- Иногда я делюсь кодом в MS Teams, Skype или других средствах совместной работы.
Как сделать отступ табуляции в eslintrc.js
indent: ['error', 'tab']
👎 Всегда требуйте фигурные скобки вокруг блоков
В Javascript, если условие содержит однострочный код, фигурные скобки можно опустить, например:
if (logged) route('/home'); else route('/login'); // and for (let val of vals) doSomething(val);
Во многих современных js/ts-приложениях это отключено. Предположительно, потому что это менее читабельно.
Я полагаю, что разработчики Python — например — не согласятся.
Мне бы хотелось увидеть опрос, в котором спрашивали, кому труднее читать вышеизложенное, чем:
if (logged) { route('/home'); } else { route('/login'); } // and for (let val of vals) { doSomething(val); }
Это сложно в Javascript, потому что красивее не позволяет отключить правило.
Поэтому, когда используется красивее, я рекомендую согласиться с тем, что блоки требуют фигурных скобок.
Зачем разрешать опускать фигурные скобки там, где это применимо?
- Меньше нажатий клавиш
- Меньше ненужных символов и размера файла
- Лучшая читабельность (в зависимости от того, кого вы спросите)
Как отключить использование фигурных скобок в eslintrc.js
'prettier/prettier': 0, curly: 0,
👎 Всегда строго применяйте правила синтаксиса/линтинга для разработчиков
Все это поднимает вопрос: должен ли я применять к разработчикам строгие и самоуверенные синтаксические правила или нет?
Как я могу это сказать?
- eslint, tslint и большинство современных утилит проверки линтера или синтаксиса поддерживают:
- автоматическое форматирование кода
- форматирование кода для каждого дистрибутива или среды
Таким образом, в настоящее время нет необходимости применять правила форматирования во время разработки, их можно добавить позже или в любое время, во время сборки, во время развертывания, перед доставкой клиенту или когда угодно. - Каждый проект js/ts, как правило, имеет свой собственный строгий набор правил синтаксиса/линтинга, обычно основанный исключительно на личном мнении/предпочтении того, кто создавал кодовую базу.
Итак, каждый раз, когда разработчики перемещаются между проектами, нам нужно учиться и адаптироваться к новым предпочтениям.
Это замедляет работу, и мы часто тратим слишком много времени на рефакторинг кода, чтобы удовлетворить линтер. - Разработчики работают быстрее и удобнее всего в предпочитаемых нами средах и с использованием наиболее часто используемого синтаксиса.
И в большинстве проектов каждый разработчик работает над разными функциями поставки и, следовательно, над разными разделами кодовой базы.
Вся причина все линтинговые войны ведутся из-за того, что у разработчиков есть свои личные предпочтения и мнения.
Если вы уберете принудительное применение одного предпочтения разработчиков ко всем разработчикам и просто позволите им работать предпочитаемым ими способом, то у вас будут более счастливые и более эффективные разработчики. - Когда вы ослабите правила линтинга, у вас будет меньше споров (извините, споров) по поводу синтаксиса в PR-обзорах. Поскольку, когда каждый член команды понимает, что каждый работает в соответствии со своими собственными предпочтениями синтаксиса, а код будет переформатирован позже, нет необходимости выбирать стили синтаксиса.
Это дает больше времени для выявления потенциальных проблем, а также культивирование культуры принятия различий друг друга.
Итак, на что это похоже?
Существует несколько способов определения и управления правилами линтинга для каждой сборки или среды. Есть даже пакеты. Однако в самой простой форме вы можете:
- Настройте свой проект
.eslintrc.*
с минимальными ограничениями.
Например, вы можете разрешить отступ табуляции или пробела для каждого файла. - Создайте второй eslintrc, например,
release.eslint.js
с полными/строгими правилами форматирования в соответствии с предпочтениями клиента или владельца продукта. - Тогда ваши сценарии package.json будут выглядеть примерно так:
"scripts": { // ... other commands here "lint": "eslint --ext .ts,.tsx ./src", "lint:format": "eslint --fix --ext .ts,.tsx ./src", "lint:format-release": "eslint -c ./release.eslint.js --fix --ext .ts,.tsx ./src" },
Теперь просто извлеките ветку и запустите npm run lint:format-release
, если вы хотите развернуть выпуск кодовой базы для своего клиента.
Не существует универсального решения, однако, если у вас все прошло хорошо, теперь все довольны, а разработчики работают эффективнее, чем когда-либо 🙂
👏 Престижность
Следующие люди и организации пожертвовали своим временем и ресурсами, чтобы внести свой вклад в эту публикацию:
- Ксам Консалтинг Австралия
- Центр передового опыта Xam React
- Юджин Кернер · Ведущий консультант · Xam Consulting