Pull to refresh

Comments 171

Динамическая типизация

Один из любимых доводов против JavaScript - отсутствие строгой типизации.

Динамическая/статическая типизация и слабая/строгая типизация - это две разные, независимые характеристики системы типов. Например, в Си - слабая статическая типизация, а в Питоне - строгая динамическая типизация.

Дабы не было путаницы - поправил, про строгую и слабую типизацию почитаю подробнее

Только она слегка обрезана

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

В презентации нашёл только.

Она тоже обрезанная, в оригинальном комиксе девочка возвращается)

спасибо за ориг, так правда смешнее)

Там «=» пропущено на 2-ой строчке

не пропущено

))) никто на js не использует "==" Это каждый js разработчик знает. )))

Аккуратность написания кода присуща каждому языку. В js надо быть более аккуратным чем в других языках возможно.

Это и минус и плюс. Само несовершенсво языка позволяет понять в процессе написания кода, какие конструкции лучше использовать, а какие нет.

Это не только в js. Например разработчики на C. Работа с памятью очень сложная, и если не выработать в себе определенные навыки, будешь стрелять себе в ногу через раз.

Вот поэтому js и "не любят". Потому что там есть вещи, которые выглядят, как надёжные, но работают мягко говоря не надежно, и которые, как оказывается, "никто не использует", но они зачем-то есть. Обо что часто и спотыкаются новички. Ибо эти сакральные знания приходят с опытом.

В моей практике был легаси проект, пестрящий "==", там бек был написан так, что в возвращаемом json одна и таже величина могла быть, как числом, так и строкой, соответсвенно строгое равенство могло давать ложно-отрицательные результаты. Не помню, что за язык был на беке, но бек-ендеры ссылались на особенности языка, не позволяющие гарантировать тип...

JS - это язык с автоматической конвертацией типов. Для таких языков это правильное поведение. В этом есть свои плюсы и минусы.

Привет. А вы случайно раньше не писали код для SAMP? А то я словил странный флешбек, и не очень понимаю почему...

Было дело)

пересеклись как-то на хабре бывшие юзеры форума SA-MP :)

Офигеть, ZiGGi, тот самый ZiGGi. Как много ты привнес в сообщество SA-MP, 14 лет назад все твои статьи перечитал, юзал твои плагины, скрипты, инклюды. Моё почтение! Аж прослезился

Спасибо)

Правильное поведение - это когда тип конвертируется всегда одинаково. Но в примере выше что-то пошло не так) И это далеко не правильное поведение.

017 - это 15, так как с префиксом 0 записываются числа в восьмеричной системе.
Number("017") - это 17, так как по правилам приведения типов, 0 в начале строки не учитывается.
018 - это 18, так как такая запись не может быть восьмеричной, Number("018") - так же 18, по правилам приведения типов.

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

Достаточно просто ознакомиться с синтаксисом и правилами приведения типов.

A leading 0 digit does not cause the number to become an octal literal (or get rejected in strict mode).

Или включить строгий режим и не использовать устаревшие конструкции.

Ага – сначала строгий режим, потом линтер, а там и до TypeScript дойдёте... Сколько боли у меня ушло после перехода на TS – трудно даже представить.

['1', '2', '10'].map(parseInt) // [1, NaN, 2]

И что тут такого? Смотрите спецификацию parseInt, она может принимать два аргумента - строку и основание системы счисления. Соответственно map передаёт первым аргументом значение элемента, вторым - его индекс. Получаются вызовы

parseInt('1', 0) // 1, поскольку 0 означает автоматическое определение основания, 
                 // а 1 при любом основании 1
parseInt('2', 1) // NaN, поскольку системы счисления с основанием 1 не существует
parseInt('10', 2) // 2

Хотите получить другое поведение, опишите аргументы явно:

['1', '2', '10'].map((x) => parseInt(x)); // Array(3) [ 1, 2, 10 ]

Такое поведение не является "интуитивно-понятным". Но это, конечно, цветочки по сравнению с тем, что "x == y" и "y == x" могут дать разный результат.

Угу, вот только:

  • в других языках программирования map принимает передаёт в отображающую функцию лишь один аргумент - текущий элемент.

  • в Javascript недостаточное количество аргументов при вызове не вызывает ошибку, а докидывает undefined.

Зачем это сделано и как это помогает разработчику - вопрос открытый

  • в Javascript недостаточное количество аргументов при вызове не вызывает ошибку, а докидывает undefined.

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

// было
function fn(a, b, c) {}

// стало
function fn(a, b, c, d = 0, e = true) {}

// старый код вызывает новую функцию
const q = fn(a, b, c);

Нет, зачем нужны аргументы со значениями по умолчанию - понятно, это много где есть. Зачем докидывать undefined, если аргументов недостаточно - неясно. Недостаточное количество аргументов при вызове - это ошибка на вызывающей стороне, а поведение JavaScript способствует тому, чтобы эти ошибки обнаруживались позже, чем надо.

Недостаточное количество аргументов при вызове

Подобное поведение вполне возможно для legacy-кода. Вот вы, например, сделали библиотеку, которая стала популярной. И множество людей её использует. А потом вы решили улучшить ваш код, в результате чего кол-во аргументов в вашей функции увеличилось. Нужно ли заставлять всех, кто использовал вашу библиотеку, заставлять переделывать их вызывающий код, если они хотят использовать новую версию вашей библиотеки?

Полагаю, что такое поведение JS как раз и является одной из причин его популярности.

А потом вы решили улучшить ваш код, в результате чего кол-во аргументов в вашей функции увеличилось.

Достаточно явно задать для новых аргументов значения по умолчанию.

Можете считать, что отсутствие у аргумента значения по умолчанию это синтаксический сахар для = undefined.

И что тут не так? parseInt принимает значение и систему счисления, а map вызывает функцию со значением, индексом и массивом, поэтому результат выполнения правильный. Да, в JS можно отстрелить ногу, но делать это не обязательно.

В этом нет ничего особенного, если не пытаться писать на JS как на каком-нибудь другом языке, в котором нельзя опускать неиспользуемые аргументы функций.

Иногда натыкаюсь на этот прикол, т.к. js редко пользуюсь, забываю, и для меня каждый раз становится откровением, что привычный по многим языкам map внезапно передаёт больше одного параметра в функцию. Самый большой минус js - неинтуитивность, помноженная на максимальное отложенное проявление ошибок в коде.

Ой, я бы не стал разбрасываться термином "неинтуитивность".

Конкатенация строк с помощью "+", как по мне, куда интуитивнее "."

Кому интересно, вот простое объяснение: 0 интерпретируется как цифра в восьмеричной системе счисления, но затем идёт 8, поэтому JS начинает её интерпретировать в 10-чной системе счисления, чего не происходит при использовании цифры 7, которая по прежнему интерпретируется в 8-чной системе счисления

Объясните прикол? Я только начал изучать этот javascript, тут не понял, почему так.

Upd. О, увидел объяснение. Надо обновлять страницу перед написанием коммента...

a = 50

b = 50

a == b # True

a = 5000

b = 5000

a == b # False

Питон момент

Да? Ну хз, значит мой учебник по питону джаваскриптер писал

Типа четное= true, а нечётное= false?

Нет. Поскольку происходит нестрогое сравнение числа со строкой, то строка приводится к числу. При этом конвертация всегда производится в десятичной системе. Получаются числа 17₁₀ и 18₁₀.
Однако, числа в левых частях сравнений записаны с лидирующим нулём. В этом случае JS сначала пробует трактовать их как восьмеричные. Первое число, 017, является корректным восьмеричным значением, поэтому распознаётся как 17₈ = 15₁₀. Второе число, 018, не является восьмеричным, поэтому распознаётся как десятичное 18₁₀.
В результате получаем сравнения 15 == 17 и 18 == 18.

Эти баги существуют уже много лет и вероятнее всего уже никогда не будут исправлены. 

О, голос разума. Собственно, потому и пользуюсь по возможности Type Script.

По мне, так основная боль и причина большинства ошибок это истользование оператора "+" для конкатинации строк и сложения.

А вот, например в php, отдельный оператор для склеивания строк, а "математические символы" только для математики - это сразу разделяют разные задачи и приведения типов работает интуитивно.

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

Все остальное меня не сильно раздражает.

Мечтаю, чтобы вышла бы отдельная версия JS где бы подобные моменты были бы реализованы по другому.

 причина большинства ошибок это истользование оператора "+" для конкатинации строк и сложения.


дак это уже не проблема. Не проще написать

const data = `hello ${text1} ${text2} ${text3} world`

А если не уверены в типе, но уверены что число, почему не поставить parseInt(data, 10) + 5

Это как раз о чём я и писал "дополнительные ухищрения, чтобы к нужному типу привести".

Уверенность в типе – гораздо приятнее явных преобразований. Перейти на TypeScript и не бояться, что завтра коллега передаст в вашу функцию строку вместо числа (или наоборот, не добавит у своей функции новый аргумент, без которого вы получите баг в совершенно другом месте кода) – кайф и отдохновение души.

По мне, так основная боль и причина большинства ошибок это истользование оператора "+" для конкатинации строк и сложения.

Это следствие, а не причина.

Причина — недостаточная строгость динамической типизации. В языках со строгой динамической типизацией оператор «+» при малейших несовпадениях плюётся исключениями. В моём любимом строго-динамически-типизированном диалекте ES для конкатенации вообще сделан .format() с сишным синтаксисом.

Более глубокая причина — изначальная ориентация на непрофессиональное применение (вместо принципа «падать как можно раньше и заваливать тесты» используется принцип «в любой непонятной ситуации хромаем дальше, чтобы в итоге отстрелить ногу по-взрослому»).

Ещё более глубокая причина — в комитете по стандартизации сидят тормоза, еле-еле от var'а избавились, а superstrict добавят «лет через триста… когда подрастём».

С точки зрения математики, сложение и конкатенация это разные вещи. Сложение коммутативно, а конкатенация - нет.

1 + 2 == 2 + 1

"a" + "b" != "b" + "a"

Использование в языке одного и того же символола для обозначения разных по сути операций это однозначно фейл.

Если ссылаться на математику – то дойдём до того, что тут надо использовать оператор умножения (см. термины "полугруппа", "моноид").

А если всё делать так, чтобы разные сущности всегда обозначались разными символами – может не хватить символов, да и понять не всегда будет просто. Например, деление с остатком и деление floating point чисел (в паскале, к примеру, это действительно две разные операции с разными обозначениями).

А если всё делать так, чтобы разные сущности всегда обозначались разными символами – может не хватить символов

В программировании есть два греха: когда одинаковые по сути вещи называют разными именами, и когда разные называют одинаково.

Если серьезно - посмотрите на хаскель. Здесь любую бинарную функцию можно записать как инфиксный оператор.

(+) 1 2 можно записать как 1 + 2

Не хватает одного символа? Просто возьмите больше: два, три, .. - сколько надо. Здесь в этом смысле полный коммунизм - каждому по потребности: name <- read <$> getLine

тут надо использовать оператор умножения (см. термины "полугруппа", "моноид")

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

Угу. И в том же Хаскеле – переопределение операций (в смысле, compile-time полиморфизм, по типам аргументов) в полной мере (благо, строгая типизация гарантирует вызов именно нужной, максимально предсказуемо). Разве что принято следить, чтобы монады оставались монадами и т.п.

Т.е. там, допустим, конкатенация строк плюсом вообще не создаст проблем, потому что вы всегда видите, что складываете строки. Никаких неявных преобразований, какой тип задал – тот и есть

"Любую бинарную операцию можно назвать умножением" – и ведь правда можно :-). Сделать операцию аргументом функции, внутри будет *. Только, конечно, не любую, а ассоциативную и с нейтральным элементом, чтобы предсказуемо работало.

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

Если код тайпчекается это ещё не значит, что в нем нет ошибок. С точки зрения математики есть вполне конкретные ожидания, какие свойства должны выполняться для плюса. Если они не выполняются, то в этом месте возникают лишние трения. А так да, программирование лояльно относится к неймингу - "хоть горшком назови, только в печку не ставь".

Я как пример сравнения привёл PHP. Там такой боли нет. По моему, у него такая же строгость динамической типизации. Так что использование одного оператора для разного круга задачь это предпосылка для ошибок, в том числе и просто человеческих, когнитивных.

Как бэкендер пишущий в том числе и фронт не вижу ничего ужасного именно в js. Ужасное вижу в том как им пользуются. Точнее как не умеют им пользоваться.

Кажется, основную боль и не описали: бесконечные замыкания в ноунейм лямбдах с передачей в коллбеках. + всякие bind, apply и прочие игры с this, которые окончательно доламывают мозг при расследовании багов.


Грубо говоря - выполняется код, которого в непосредственно текстовом коде не было.

В результате типикал проблема, когда код крашится с ошибкой cannot read property 'field' of undefined с абсолютно бесполезным стектрейсом, из функций в которые откуда-то прилетел callback с замканием этого самого undefined. А как и где замкнули такую лямбду - фиг знает. И на дебаггере не встанешь нормально. Сиди, медитируй над кодом теперь.

Почему typeof null === 'object' назначен багом? В спеке написано, что null - это значение, которое представляет из себя отсутствие значения у объекта. То есть null задуман как отсутвующая ссылка на объект (в других языках null используется аналогично). Поэтому не баг, а фича.

Чутка поправлю, не отсутствующая ссылка, а пустой объект без свойств

Я больше описывал область его применения, а не то, чем он является.

Пустой объект это Object.create(null)

В этой статье исключительно догадки, а описание null как объекта появилось уже в первой спецификации языка.

Основная проблема в том, что есть тип Null, который имеет одно единственное значение null. Вот тут-то и встаёт вопрос согласованности типов, какого хрена null имеет тип Null и object. А так полностью с вами согласен, ничего дурного не вижу, что null это нулевой адрес для указателя/ссылки (т.е. для объекта).

Тут больше камень в огород не к типу null, а к оператору typeof. Этот оператор, как бы странно это не звучало, не возвращает тип данных. Это можно понять по тому, что код typeof (() => {}) вернёт function, а такого типа данных в JS не существует. Думаю, если бы оператор typeof назывался как whatis (к примеру), то подобные споры бы не возникали.

уже давно не так и JS успешно используется на сервере, в мобильных устройствах и даже в микроконтроллерах

На сервере ведёт себя не очень хорошо. NodeJS - ещё одна беда, со своими костылями. Сам Райан Дал, его создатель, считает, что допустил много косяков при его создании, после чего презентовал Deno, который все ещё не пользуется популярностью. Недавно анонсировали BunJS, чтобы сместить эти ноду и дэно. Интересно будет посмотреть, чем это всё в итоге закончится. Но одно очевидно точно: js вряд-ли сможешь тягаться в перформансе с шарпом/го из-за слишком большой высокоуровневости языка и необходимости сравнительно большого рантайма для него, а тем более с растом/си, если мы говорим о его использовании в микроконтроллерах, о котором вы упомянули

Ну и частенько бывает популярно брать технологию, на которой легко создавать что-то одно и использовать ее для всего остального. Особенно когда речь идёт о разработчиках, которые знают лишь один инструмент

если мы говорим о его использовании в микроконтроллера

У меня есть пара плат с Espurino. Это JavaScript для микроконтроллеров. Там где не важны задержки и плевать на энергоэффективность (а это львиная доля всей домашней автоматизации), писать логику на JS одно условие.

Удовольствие? ))

Удовольствие :)

Я понимаю что это survival bias и все такое но лично уже лет пять не видел чтобы кто-то всерьез писал на чистом JS. TS в энтерпрайзе, TS в хобби-проектах, TS по дефолту в популярных бойлерплейтах, TS в стартапах.

Ну - я тот чувак, кто использует JS в хобби проетах
Просто потому что поддержку они обычно не подразумевают, то, что кто-то кроме меня полезет в код - тоже
А запомнить что возвращает пара десятков функций (особенно с нормальным неймингом) в проете на пару выходних - не сильно сложнее, чем прописывать то явно

Но ведь в любой вменяемой IDE подстановка этих типов практически полностью автоматизирована и на маленьком хобби-проекте оверхед на составление правильных типов оклолонулевой. Для бойлерплейтов это нынче как правило просто дополнительный ключ при создании пустого проекта.

А полезный выхлоп - это не столько аннотации типов, сколько статическая проверка при компиляции, которая просто не пропустит кучу потенциальных проблем создаваемых динамической типизацией.

Мне кажется, тут ключевой момент – что товарищу не приходится взаимодействовать ни с коллегами, ни даже с "самим собой месяц назад". Для большинства зарабатывающих программированием ситуация отличается, поэтому нам трудно его понять.

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

Прямо как Баба Яга – одной ногой в Яви, другой в Нави :-)

А какого рода могут быть проблемы?

Мне приходится писать JS-код без сборки, прямо в какой-нибудь main.js в каком-нибудь битриксе. Конечно, я бы мог под каждый сайт сделать конфиг для vite, перенести имеющийся файл как есть, а новые функции писать на TS. Но merge request сразу на тест я из этого сделать не смогу, а значит, мне придётся самому собирать это у себя, класть на замену исходному файлу, а эти свои исходники хранить в отдельной ветке, которая не сможет обновляться, если бэкендер что-то поменяет в финальном JS-файле. А это битрикс, он там поменяет, потому что у него какие-то свои магические функции работы с формами через глобальную переменную BX. Правда, иногда, когда я продолжаю участвовать в проекте, а не просто отдаю вёрстку менеджеру, мы можем договориться с бэкендером и я сделаю обращение к API без всяких BX, через обычный fetch.

Ещё один минус: если я при сборке всё минифицирую, то он не сможет прицепить эти свои магические функции. У них там ещё и всё на jQuery, копипастят из проекта в проект. Я могу сделать вёрстку для нового сайта на чистом JS, а они при создании шаблонов битрикса из этой вёрстки добавят туда jQuery.

Мне кажется что справедливо будет отнести такие кейсы к legacy. В legacy всякие чудеса случаются даже в наше время. И PHP 4 и ASP 1.0 (вьетнамские флешбеки с работы в аутсорсе).

Вроде как да. С другой стороны, если полностью работать через API-вызовы, не завися от того, что работает на бэкенде, то отключится фича битрикса в виде редактирования данных прямо на сайте путём перехода в режим редактирования. Поэтому приходится встраивать шаблоны внутрь него и зависеть от его JS-кода. Заодно и поисковики контент видят.

Ну, я между ванилью и TS выберу ваниль.

Я знаю, здесь много фанатов TS, и вы меня сейчас, конечно, заминусуете, но TS это тупиковый путь. Типизация должна быть сделана на уровне рантайма, а не на уровне языка. Создатели TS рантайм не контролировали, и поэтому запилили транспиляцию. А транспиляция это всегда не только волшебный способ добиться совместимости, но и дополнительный гемор. При этом польза от статических проверок гораздо меньше, чем (могла бы быть) от рантайм-чекингов.

Я лучше подожду, пока в новый стандарт ES не добавят ещё один strict для проверки на type mismatch, а до тех пор попользуюсь старым.

К сожалению, любители TS обычно не имеют опыта программирования на языках типа TIS, и не понимают, о чём вообще речь.

P.S. И, кстати, «используется в энтерпрайзе» это, по-моему, не самый лучший аргумент. Когда я смотрю на некоторые популярные решения и подходы из энтепрайза, у меня возникает ощущение, что там специально усложняли процессы для повышения порога вхождения. Каждое дополнительное звено в development pipeline — это для меня всегда плохо, а компиляция это очень заметное звено.

Да зачем минусить, тоже мнение.

> Польза от статических проверок гораздо меньше, чем (могла бы быть) от рантайм-чекингов
Да, но гораздо больше чем от отсутствующих чеков вообще.

> Я лучше подожду, пока в новый стандарт ES не добавят ещё один strict

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

Да зачем минусить, тоже мнение.

Спасибо, что сохраняете вежливость. Мне вот это делать в разговорах о JS/TS удаётся не всегда. Например, чтобы понять, что подразумевается под «нативным рантаймом для TS», я решил сначала немного погуглить. И нагуглил вот такую статью. Процитирую:

Но вот мы делаем рефакторинг и решаем, что слово name плохо передает смысл названия фильма, а вот слово title — гораздо лучше. После изменения все продолжит работать и компилироваться на TS, ведь наша функция ожидает ANY на вход. И только где-то на UI мы увидим слово undefined. В поиске этого бага можно потратить много бесценных часов.

ААААААААААААААА!!!!! Я помню, как на заре юности работал в одном НИИ, где мы писали на COM (C++ и Delphi) ПО для промышленного моделирования. И кто-то внёс маленькую ошибку с адресной арифметикой в код фабрики. После чего фабрика, как в игре Portal, начала штамповать неправильные модули. Которые, к сожалению, тоже делали аллокации (уже неправильно). И только на третьем уровне это приводило к защите памяти и падению (выглядящему на таком уровне косвенности как абсолютно рандомное). Так вот представьте себе: у вас полный доступ к компьютерам юзеров, можно даже поставить на них любые отладчики, можно обложиться любыми проверками, у вас полный код, который вы сами же писали и понимаете, у вас есть отряд из программистов, которым намылили холку и расставили приоритеты и вы полгода ничего не можете сделать. А через полгода кто-то случайно находит странное место, исправляет его, и баг, кажется, перестаёт воспроизводиться. То есть, даже после того, как вы его пофиксили, вы не можете быть в этом уверены (что не помешает на радостях напиться). Вот это — действительно страшно, а причина сему — unmanaged-среда.

Когда после таких приключений я читаю, как «в поиске этого бага можно потратить много бесценных часов», во мне просыпается автор рассказа «Избалованным детям» («Пять километров в гору зимой»): «Бездельники! Managed-среда защищает вас от всех по-настоящему страшных ошибок! Да вы бы не выжили в 2001-м году и одного дня!».

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

Так вот, погуглив и не найдя имплементаций…

Я бы подождал нативного рантайма для TS, бо он прекрасен сам по себе

Я подумал, что речь идёт про гипотетическое решение, в результате которого получится… Скажем прямо: дотнет в браузере ))

Пятнадцать лет назад на одном сайте было голосование «Какой язык вы хотите видеть в браузере?». Тогда лично я голосовал за C#. А сейчас… Сейчас я бы проголосовал за строгий ES.

Первая причина. Я попользовался строгими динамическими языками и успел полюбить такую типизацию. Она реально не страшная, посоны! Когда речь идёт о примитивных типах, это как variant. Вы же не боитесь variant'а? Особенно, в хорошей реализации, например, в виде ATL-обёртки над OLE VARIANT. А когда речь идёт о сложных типах, то просто не надо юродствовать и собирать объект «если то — добавим поле, иначе — добавим другое поле». И даже в этом случае, если что-то пойдёт не так, вылетит исключение с номером строки, избавив вас от… ой, не могу… от необходимости потратить много бесценных часов! То есть, мало-мальские тесты, которые в любом случае нужны, полностью заменят компиляцию как способ проверки. При этом писать динамический код гораздо приятнее.

Вторая причина. Веб, как среда, уже давно и безнадёжно динамически типизирован. Я про AJAJ, хотя его теперь уже никто так не называет. Про джейсончик, в общем. Даже если разработчики будут контролировать не только язык, но и рантайм, что толку от самой-распресамой типизированной типизации на клиенте, если теперь выяснится, что никто не контролирует сервера? В общем, придётся весь Интернет переписать, а не только браузеры.

P.S. Хотя что бы я хотел увидеть в браузере, это все релевантные части стандартной библиотеки от дотнета. Майкрософт в этом гении.

С приведенной цитатой все просто - не надо использовать any. В линтерах есть эта настройка, в актуальных она включена по умолчанию. Presubmit check-и сразу бьют по рукам за любую попытку использовать any, большинство популярных библиотек либо сразу пишутся на ts, либо имеют корректные дефиниции типов (огромная работа, проделанная сообществом за последние 10 лет). Для редкой старой чисто javascript библиотеки всегда можно написать декларации самостоятельно.

A по поводу unmanaged среды и джсончиков - эта ведь не ts и не js эксклюзивная проблема. Ну и способы решения разные есть, я лично очень люблю grpc/протобаф и автоматическую генерацию стабов, сервера, клиента, моделей для сервера и клиента. Не панацея, конечно, но жизнь сильно упрощает.

То есть, даже после того, как вы его пофиксили, вы не можете быть в этом уверены (что не помешает на радостях напиться). Вот это — действительно страшно, а причина сему — unmanaged-среда.

JS в этом смысле managed с ног до головы, поэтому о таких вещах ни кто здесь даже не задумывается.

Я тоже когда-то писал COM/DCOM и могу сказать, что современные инструменты реально ушли далеко вперёд, в смысле количества разложенных граблей, на которые может случайно наступить разработчик.

Я, собственно, просто привёл пример, когда мне не удаётся сдержать смех (а это не слишком вежливо ;).

Если кто-то помнит, у Хайта была такая юмореска. Иностранный корреспондент в разгар дефицита обличает по телевизору из Нью-Йорка их нравы: «Чтобы купить такой костюм, как вы видите на мне, капиталистическому рабочему придётся проработать несколько тяжёлых, изнуряющих часов!» Вот и эти несколько тяжёлых, изнуряющих часов отладки… в managed-среде… где все ходы записаны… Такой же смех вызывают. Для полного счастья мне не хватает только повышенной строгости (BDSM, блин) со стороны среды, и я это счастье нашёл в языке TIS (вариация на тему JS).

Что в нём прекрасного? Как минимум приходится писать намного больше. В JS не нужны типы, это не Java.

Опять же, приведите, пожалуйста, пример ошибки, которую легко допустить при написании кода на JS, и от которой с хорошей долей вероятности защитит использование TS.

Типизация должна быть сделана на уровне рантайма, а не на уровне языка. Создатели TS рантайм не контролировали, и поэтому запилили транспиляцию.

Статическая типизация - это проверка типов на этапе компиляции. Ровно то, что реализовано в TS.

Проверка типов в рантайме это строгая типизация. Она несёт за собой дополнительные накладные расходы и тут всегда возникает tradeoff между строгостью и performance. Проверяйте входные данные, а в остальном можно жить и без этого.

Статическая типизация это как а Java, где всё удобно. Типизация в ts - это через одно место. Это не язык программирования, это язык описания интерфейсов, IDL

Мне структурные типы в TS кажутся выразительнее, чем номинальные как в Java. Плюс в нем более продвинутая алгебра типов, у которой понятно из каких разделов математической логики растут ноги. Но вполне допускаю, что это вкусовщина.

Статическая типизация - это проверка типов на этапе компиляции. Ровно то, что реализовано в TS. […] Проверка типов в рантайме это строгая типизация.

Я это понимаю, и сравниваю их между собой. Это не несравнимые вещи, если смотреть на общую пользу.

Она несёт за собой дополнительные накладные расходы и тут всегда возникает tradeoff между строгостью и performance.

Oh, come on. Зачем вообще нужна managed-среда, если не для этого.

Проверка типов в рантайме это строгая типизация.

Это динамическая типизация. Она может быть строгой, ну или как в JS).

Не буду минусовать :-), но уверенно скажу, что проверка в compile-time всегда происходит раньше проверки в run-time, и получить ошибку компиляции гораздо приятнее, чем крэш у юзера. Это не повод отказываться от проверок в run-time (там, где компилятор не может дать гарантий), но очень облегчает жизнь.

Я на чистом js пишу.

Нет никаких проблем.

TS неудобный и смысла в нем не так и много, как это пытаются преподнести.

TS лишает js главного плюса.
Его не надо собирать никакими бандлами, только если ради того, что бы уменьшить колличество файлов.

Перспективнее assemblyscript вставить.

Проблема TS в том, что он убивает производительность разработчика. Далеко не всегда для корректного кода на JS тип выводится автоматом. Приходится вместо разработки функционала еще тратить кучу нервов чтобы уговорить TS, что тут все нормально с типами.

Да, есть такие моменты, но. Я когда начинал js учить, писал код, который ломался при малейших неверных движений. Потом попал на проекты с ts. И уже долгие годы пишу на нем. Сейчас заметил, что ts под капотом дисциплинировал меня писать код с кучей проверок. Я пет проект на js чистом пишу и снова присутствуют все эти проверки. По моему это хорошо, что меня дисциплинировал ts, а не вечно падающий прод из-за моего плохого кода )

Тут согласен, TS хорошо бьет по рукам и сразу в лажу носом тыкает, так обучение идет быстрее. Но когда уже понимаешь, что делаешь, в ряде случаев он начинает мешать.

Разве нельзя писать аккуратный код с проверками не потому, что TS научил, и не потому, что иначе "прод падает", а просто на всякий случай? Я давно так делаю даже в пет проектах и не чувствую сильного дискомфорта.

Да ничего он не убивает. Просто это язык не для вкатышей в IT, которым надо все и сразу, и быстро. У него есть определенный высокий порог вхождения, но потом уже этого не замечаешь. Вас послушать, тогда и С# убивает производительность да? Там тоже типы, там тоже дженерики, там тоже надо сигнатуры функций правильно описывать. Я не сравниваю TS и Шарп, но принцип один. Это вы ещё на С+ не писали. Нервы у него видите ли...

Как раз для вкатышей он лучше подходит, потому что следит, чтобы несмышленыш себе ногу не отстрелил. Если разработчик понимает, что делает, это только мешает.
По поводу C# аргумент так себе, но вы это похоже и сами понимаете ))

Это какая должна быть память у разработчика, чтобы помнить где какой тип во всём проекте, и что происходит в эдж-кейсах. А что делать, если разработчиков несколько, и не все их них такие профессиональные как вы. Логичное решение это писать JSDoc-комментарии. TS является развитием этого решения (кстати, TS может проверять JSDoc). Если где-то приходится бороться с тайпскриптом, то можно энкапсулированно задействовать any.

Можно еще d.ts писать для внешних интерфейсов модулей, этого достаточно, чтобы не запутаться. Плюс тесты.

Конечно конечно, писать каждый раз проверки внутри функции, что входная переменная является числом вместо того, чтобы сразу типизировать аргумент безусловно быстрее и полезнее для разработчика. Это так весело в чистом JS писать instanceof и typeof. А аргумент по отстрел ноги просто великолепен! А для чего по вашему существуют типы в других языках? Ровно для этого, чтобы все вызывалось с нужными параметрами и не ломалось. Никто не пишет без нужды параметр как dynamic. А если аргументом является функция вы как проверяете ее сигнатуру, если не секрет? А если ее параметром будет сложный объект? Мне на TS потребуется ровно минута, а вам ?

А если ее параметром будет сложный объект? Мне на TS потребуется ровно минута, а вам ?

Это так не работает. Вот простой пример:

const arg = JSON.parse('{"a":"123", "b":123}')

function sum(arg: { a: number, b: number }): number {
    const { a, b } = arg
    return a + b;
}

console.log(sum(arg)) //"123123" 

Ссылка на песочницу

Вроде функция типизирована, но работает не так, как ожидает разработчик. Интересно - почему?))

Потому что JSON.parse за каким-то хреном возвращает any, хотя по-хорошему надо бы unknown

Первую строку можно заменить на const arg: any = {a:"123", b:123}; и уже не удивляться, почему TS не работает в выключенном состоянии.

Для проверки типов в рантайме существуют дополнительные нашлепки на основе json-schema.

Для проверки типов в рантайме существуют дополнительные нашлепки на основе json-schema.

Я как раз и показываю, что использование TS не исключает необходимости контроля типов в рантайм.

Но такие проверки надо ставить только на "границе" между входными данными и кодом, а это обычно совсем малый процент всего приложения.

Прежде всего лечим дурь с некоторыми функциями, и теперь TS не промолчит при попытке воткнуть распарсенное значение куда попало - то есть уже не будет того вопиющего кейса, который вы привели. Не получится забыть явно сделать проверку и привести к типу. Значение обзаводится типом и теперь спокойно путешествует по коду - больше не понадобится рантаймовых проверок.

Это как с профессиями. Всякие врачи/юристы/etc один раз получают документ об образовании и далее везде просто показывают его при трудоустройстве (в нашей аналогии, документ - это как бы их "типизация"), а программисты вынуждены на каждом собесе "разворачивать дерево".

Прежде всего лечим дурь с некоторыми функциями

Это не дурь, это легаси )). unknown появилось только в 3й версии TS, и базовые типы как JSON.parse уже было не исправить так, чтобы не поломать половину всей TS экосистемы. И это базовые типы, а как быть с огромным количеством JS либ, на которые типы натянуты кое-как? Тот же экспресс, не к ночи будь помянут, на котором много чего написано и до сих пор пишется...

Ваши минусы лишь доказывают, что вы не знаете и не умеете использовать TS. Из-за этого у вас возникает боль в том месте, на котором обычно люди сидят. Выше был дан ответ. Но я дополню - все эти ваши JSON.parse используются, как правило, в двух случаях. 1 - распарсить ответ с бека, 2 - распарсить считанные с диска данные. И в том и в другом случае нужна валидация входных данных. Наброс на вентилятор, конечно же, засчитан.

type TArg = {
  a: number;
  b: number;
};

function sum(arg: TArg): number {
    const { a, b } = arg
    return a + b;
}


const a = {
  a: 654,
  b: '123'
};

// Ой, ошибочка 
// Types of property 'b' are incompatible.
//    Type 'string' is not assignable to type 'number'.
const result = sum(a)

Интересно почему?

P.S. Единственное чему я рад, что мы работаем в разных компаниях

Так все таки в TS тоже нужна валидация! Ну надо же...Вы же писали, что TS сам проверяет сигнатуры.

Ахах, ну загляни хоть раз в жизни в документацию
https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#any

TypeScript also has a special type, any, that you can use whenever you don’t want a particular value to cause typechecking errors.

JSON.parse возвращает результат с типом any, тип any отключает все проверки типов. Какое ты ожидаешь поведение ? Что будет проверка ?

Вы писали:

... писать каждый раз проверки внутри функции, что входная переменная является числом вместо того, чтобы сразу типизировать аргумент безусловно быстрее и полезнее для разработчика. Это так весело в чистом JS писать instanceof и typeof.

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

Так если валидация и так и этак понадобится, зачем TS вообще? Для умственно неполноценных, которые не знают, что строки с числами нельзя складывать, или забывают дёргать parseInt?

Вы можете просто задизейблить ts для конкретного файла/строки

Можно, но это бывает порицаемо ))

Далеко не всегда для корректного кода на JS тип выводится автоматом.

Если вы пишите на Javascript код, для которого специально построенный для вывода типов инструмент не может вывести типы, то с чего вы считаете, что эти типы будут ясны человеку, который этот код считает?

Если не ясно какой тип будет, человек может написать тест, запустить отладчик, почитать доку...

const notNulls = [1, null, 2, 3].filter(i=>i!==null)
console.log(notNulls) // [1, 2, 3] 
const n:number = notNulls[0] //Type 'number | null' is not assignable to type 'number'.

Песочница

"One of the nuances that can easily be missed, though, is that Harris is mainly concerned about TypeScript in the context of library development. The switch to JSDoc is “less beneficial if you’re building an app because if you’re building an app, you’re going to have a build step anyway. You want to optimize your code, you want to minify it, you want to bundle everything up. If you’re building a library that is when I really strongly urge to use JSDoc instead.”"

"Harris added on Hacker News that “as a user of Svelte, this won’t affect your ability to use TypeScript with Svelte at all — functions exported from Svelte will still have all the same benefits of TypeScript that you’re used to (typechecking, intellisense, inline documentation etc). Our commitment to TypeScript is stronger than ever.”"

Я вижу смысл в его словах.

Однако давно не трогал jsdoc, возможно тулинг стал сильно лучше с тех пор, но если я правильно помню, нужна невероятная дисциплина чтобы мейнтейнить все типы в jsdoc. По крайней мере нужна была. В продуктовой разработке, когда давят сроки и даже на тесты не всегда остаётся время, это большая редкость.

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

Ощущение, будто смотришь кусок концерта Задорнова. Чего они все так смеются то?

Тогда его использовали примерно так.

Кавычки src не закрыты, должно выдавать ошибку. Зато зачем-то стоит точка с запятой.

Возможно предполагается, что браузер сам "закроет кавычку"
Это только предположение, сам я такую дичь никогда не писал :)

Ну, на сколько я читал в древних учебниках HTML, браузеры тех времён должны были пытаться сами закрывать теги и кавычки, если программист забыл это сделать. Сейчас они тоже, вроде, пытаются это делать

Браузеры в HTML-коде да, а JS нет. На картинке двойная кавычка атрибута закрыта, а вот одиночная кавычка JS-кода пропущена.

Мне кажется, что в примере есть ещё и историческое несоответствие с заявленным:

Подобное может быть верным лишь для только родившегося JS

В момент появления JavaScript, доступ к элементам был в силе "document.myForm.myInput", и это работало буквально лишь для нескольких типов (form, img и может ещё пары каких-то).

document.getElementById(), ровно как и весь DOM, это более позднее изобретение.

Код на слайде выглядит как лет на 10 позже. Т.е. JavaScript к тому времени не только родился, но уже и в школу пошёл.)

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

Некоторые любят JavaScript (браузерный) хотя бы за то, что он (как и VBA) позволяет программировать в условиях тотального запрета на установку ПО разработки и вообще любого дополнительного ПО на офисных местах (достаточно браузера и MS office - в случае VBA).

Встречаются иногда программы, где автор так и говорит: пишу на том, что доступно на типовой офисной машине, где "запрещено буквально всё":

https://xakep.ru/2012/11/03/excel-task-manager/

Странно, что VBA не были запрещены

Странно, что VBA не были запрещены

На примере крупного банка: несмотря на наличие всяких там АБС (ERP), CRM, модных хранилищ и конвейеров и т.п., если у всех отключить в Excel макросы - банк встанет (по крайней мене испытает шок).

Так и есть. Хочешь покодить - f12 и вперед, на любой машине где есть браузер.

Я очень удивлён, что никто не вспоминает WAT???

Классика. До сих пор показываю на работе.

Ах да, статью не одобряю. Так же как и яваскрипт.

Будь js хорошим языком, не было бы этих многих комментприев, объясняющих великие фичи сего языка

1 + "1" - 10
1

Пример динамической типизации

Всё же это не пример динамической типизации. Это пример слабой типизации.

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

Справедливости ради, ошибка будет на этапе выполнения, поскольку и питон, и жабаскрипт - скриптовые языки с их присущими недостатками.

Всегда воспринимал JavaScript как байт-код для браузера. Писать на нем теоретически можно, но лучше все-таки пользоваться более высокоуровневыми фреймворками.

Это какими?

Ну это не фреймворки, а языки.

Осталось проанализировать, почему они не популярны сейчас для компиляции в JS фронтенд приложений

Как минимум есть 3 подхода к абстракции JavaScript

  1. Полная трансляция кода, это то что на скинул выше. Что касается популярности - платформа 1С:Предприятие популярна? В ней при работе через веб-клиент выполняется трансляция языка 1С:Предприятие в JavaScript.

  2. Платформа генерирует основную часть клиентского кода, но при необходимости можно вставлять свои куски. Такой подход применяется, например, в Django и Odoo

  3. Фреймворки типа React или Angular, которые содержат готовые компоненты, которыми вы управляете на JavaScript

Возможно кто-то разрабатывает фронтенд на чистом JavaScript, но мне это кажется странным.

Если я не ошибаюсь, то фронтенд GitHub написан на чистом JavaScript, чем они гордятся. Вот ссылка, где они говорят о том, что больше не используют фронтенд-фреймворки (до этого у них был jQuery): https://github.blog/2018-09-06-removing-jquery-from-github-frontend/

Про то, используют ли они JS или TS пруф найти не смог, тут могу быть не прав

Это IT-компания и сайт их основной продукт. Ну и размер компании таков, что можно целое подразделение на поддержку этого сайта выделить

ну TypeScript сейчас очень популярен. Практически маст хэв

На чистом js вполне можно писать выразительный и лаконичный код, в том числе большие проекты со сложной структурой, тут сравнение с байт-кодом неуместно.

ну писать большие проекты на чистом js стало возможно только после появления ES6. Сравнение с байт-кодом делается в том смысле, что других универсальных возможностей для выполнения произвольного кода в браузере нет.

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

Но нужно помнить, что динамическая типизация несёт как большую власть, так и большую ответственность

Пример динамической типизации
Пример динамической типизации

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

Впервые об этой проблеме написал Ларри Уолл ещё где-то в 1992-1994 году (ЕМНИП).

Так вот, Ларри исследовал эту проблему и пришёл к тому, что она произрастает не из динамическости операндов операторов, а из того, что операторы выбраны неверно (перегружены функционалом).

В данном примере оператор "+" (плюс) используется в языке как математический оператор сложения и строковый оператор конкатенации одновременно. Эта ошибка сделана довольно во многих языках программирования, но есть языки, где работа над ошибками проведена.

Вот например язык от Ларри включает выделенный оператор конкатенации - точка, и двоякости между оператором "математический плюс" и оператором "конкатенации" не случается

Другой пример языка с оператором конкатенации - Lua.

И так далее.

Увы, в современное время принято ругать именно динамическую типизацию, приводя при этом примеры с "её недостатками", относящиеся отнюдь не к динамической типизации.

Надеюсь AI когда будет захватывать мир будет использовать Javascript. Тогда у нас будет хороший шанс.

Лично для меня обсуждать голый JavaScript, без Typescript это как обсуждение старой версии. Забудьте про JavaScript. Для эффективной работы нужно использовать TypeScript. Поэтому первая часть статьи не актуальна. Это из того же цикла, когда говорят, что C# только под Винду (уже 8 лет как нет).

Производительность: js не предназначен для объемных вычислений, он предназначен для эффективного описания логики с чем хорошо справляется. И он точно быстрее конкурентов того же класса (сравните с python). А если нужна большая производительность, то узкие места можно написать на другом языке и вызывать из js.

Прототипное наследование: данный тип наследования мощнее чем классическое наследование от одного класса как в java и c#. Более того уже давно есть классические классы (даже в js без ts, в ts добавили области видимости). Я не знаю как было у автора, но у меня свойства в прототипе случайно не менялись.

Вот чего мне не хватает так это extension-методов из c#. Да, можно расширить прототип, но есть нюансы с null/undefined и tree shaking.

Наличие двух состояний отсутствия значения (null и undefined), тоже проблема.

Главныа проблема js, это слабое развитие библиотек для ML, DS и так далее. Да и notebooks слабо развиты. А python модный, хотя js круче питона, но отсутствие библиотек заставляет использовать python. Все остальное уже решено (в какой-то степени).

P.S. Давайте все похороним js и будем использовать typescript, так ещё bun под windows, когда-нибудь выйдет и заживём.

Так бан под винду уже вышел же ж.

Нет, они врут в документации. По факту bun под windows это wsl. Но можно скачать альфа-версию exe под Винду.

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

Вчера кстати, они активизировались и понасоздавали тасок в гитхабе под Винду. У них в планах зарелизить хотя бы рантайм под Винду, пакеты нужно будет устанавливать тем же npm/pnpm. А сверху быструю установку пакетов они когда-нибудь потом сделают.

Лично для меня обсуждать голый JavaScript, без Typescript это как обсуждение старой версии. Забудьте про JavaScript. Для эффективной работы нужно использовать TypeScript.

Обоснуйте, пожалуйста, почему?

Со всем остальным в вашем комменте согласен, но хайп по поводу TypeScript категорически не понимаю.

Тем более, проблема работы с типами вовсе не в том, что плохие программисты ошибаются с типами в коде (как может показаться глядя на мемную картинку в конце), а в том, что в рантайме снаружи (по сети, из поля ввода, из файла) будет получено в переменную неизвестно что. Как TypeScript решает эту проблему, конвертирует данные исходя из типа переменной? А что мешает такой конвертер на ванильном JS написать?

TypeScript давно перестал быть просто хайпом, превратившись в отраслевой стандарт. Однако лишь часть разработчиков осознает неотъемлемую необходимость его использования.

Удивительно, но даже опытные программисты часто допускают ошибки с типами в своем коде. Несмотря на подсказки от сред разработки, не все проблемы удается исправить. При написании кода на TypeScript с включенными strict/strictNullCheck и честном соблюдении системы типов можно гарантировать отсутствие ошибок.

Но в реальности есть два основных момента, где могут возникнуть проблемы, - это неправильные определения типов сторонних библиотек и парсинг JSON. Компилятор TypeScript не выполняет проверку типов во время выполнения, хотя теоретически это можно реализовать. Обычно модели ответов от сервера генерируются из Swagger-спецификаций или конвертируются из классов C#, что исключает человеческий фактор, но не решает проблему обновления моделей данных на сервере. Но у вас может быть монорепозиторий включающий и сервер и клиент на typescript.

Радикальным решением является использование трансформаторов, которые проверяют типы во время выполнения ( https://googlefeud.github.io/ts-runtime-checks/ ). К сожалению, на данный момент это не получило широкого распространения и не поддерживается Microsoft.

И он точно быстрее конкурентов того же класса (сравните с python)

Все таки быстрым его делает JIT-компилятор V8, на создание которого были брошены лучшие ресурсы компании Google. К сожалению PyPy так и остается нишевым продуктом.

Потому что веб-разработка – это мощная, но страшная и отвратительная химера.

Не понимаю прикол статей почему не любят JS, особенно для фронтенда. Как будто бы фронтенд можно написать на крестах или питоне. Это как хаять ассемблер за то, что в нем нет ничего ООП.

Свитчнись на любой язык - у тебя будет свой разрыв шаблона. Но при этом к первому ЯП вопросов особо нет, это не вопросы, это особенности. Классическим молотком гвозди забивать тоже сомнительная по удобству затея, инструмент каменного века как никак. Вам ещё повезло, с годом опыта, что var не застали ))

А разве всё перечисленное - не преимущества Javascript?

Я не могу его хейтить. Хоть я и знаю такие языки как Rust, C++, Python, PHP, JS-подобные языки(Typescript, Node.js, EcmaScript) остаются моими любимчиками. Я прям влюбился в JS)

Может, я что-то неправильно знаю, но ведь JS — это реализация стандарта ECMAScript, а Node.js — is a JavaScript runtime? То есть, в ноде ровно тот же JS, а ES вообще считается самостоятельным языком?

Мне как-то вынесло мозг наличие в js числа "-0" (оно у меня получалось в результате определенных вычислений), которое не было равно "0"... Далее я узнал у существовании числа "+0", которое также не равно "0" и тем более "-0".

Это особенность чисел с плавающей запятой.

Касательно равенства этих значений в js

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

https://floating-point-gui.de/errors/comparison/

Ну и кто сказал, что многословность = уродливость? Во-первых, так читать названия методов намного проще, чем если бы они были сокращены до нескольких букв (привет, строковые функции в PHP). Во-вторых, на ту же Java просмотрите, особенно до версии 8 - куда уж многословнее? Но язык один из самых топовых во всех смыслах, и я бы не сказал, что его прямо не любят.

Наследование на прототипах - ну кому как, мне сначала тоже это казалось дико сложным и непонятным, а потом в какой-то момент я понял, как это круто. Можно самому писать довольно хитрые алгоритмы наследования, а после открытия доступа к полю __proto__ делать это стало ещё проще.

Что до нетривиальных случаев... Да, полезно о них знать, но я, признаться честно, ни разу от такого не страдал: восьмеричной системой не пользуюсь, строки и числа через == не сравниваю, тип переменных на ходу не меняю, а всё, что должно принимать на вход число, пропускаю через parseInt/parseFloat, и работаю с результатом - заодно сразу NaN можно обработать.

Можно самому писать довольно хитрые алгоритмы наследования

А можете рассказать, как это на практике помогает в разработке?

А я тоже не любил как С# разработчик. Но потом начал изучать F# и понял - это функциональный язык и мое отношение к нему связано именно с этим ожиданием ООП от функциональщины. А после появления TS так и вообще не вижу проблем с JS - я на нем просто не пишу))

Не знаю, что я делаю не так, но за 8 лет работы full-stack я ни разу не влетал ни на один из приведенных багов. Единственное, что могу вспомнить, на чем попадался пару раз, это проверка, что поле имеет значение, а там 0 лежит и проверка выдает ложный результат. Зато вот сколько костылей и выстрелов в ногу у меня было за годы использования плюсов до этого, не сосчитать. Самое главное - сотни бессмысленных конструкций, тысячи строк нагромождений наследств, шаблонов и все ради того, чтобы где-то в одном месте кода можно было бы не заморачиваться над тем, а какой у меня сейчас там тип или объект передается. Просто годы, уходящие на то, чтобы понять, что код в стиле стандартной библиотеки - это не круто, это не показатель классного программиста, а просто абстрактные ментальные упражнения, откровенный эквилибристичемский мусор, который нужно забыть и никогда так не делать в реальной разработке. А после этого приходишь в javascript/typescript, у тебя есть function, которая и объект, и класс, и функция, и замыкание, у тебя есть async/await, и все, по факту это все, что нужно, чтобы решать все свои задачи.

Sign up to leave a comment.

Articles