«Существует только два вида языков: те, на которые жалуются и те, которыми никто не пользуется», — Бьёрн Страуструп, создатель C++
Очень часто слышатся заявления о том, что JavaScript нужно заменить каким-то другим языком. Причиной всегда становится то, что у JavaScript накопилось слишком много странностей, которые давно нужно было исправить.
Но поскольку их не исправили, то это очевидно означает, что JavaScript — отстойный язык, который просто никак не исправишь. И что его нужно заменить, и желательно любимым языком очередного жалобщика.
Но действительно ли это так?
Как мы оказались в такой ситуации?
Не стоит ждать, что я назову JavaScript идеальным языком. У него есть странные причуды. Он был спроектирован за десять дней, а затем его изменили так, чтобы он напоминал Java. К сожалению, это наследие, с которым мы вынуждены жить.
Но ни один язык не идеален, а JavaScript значительно улучшился после ES6 и продолжает своё развитие. Он эволюционировал из «игрушечного языка», используемого только для анимирования элементов веб-страниц, в серьёзный язык программирования, применяемый сегодня для выполнения больших и сложных веб-приложений.
JavaScript сегодня в буквальном смысле повсюду и является самым используемым языком программирования в мире.
Так почему же некоторые разработчики всё равно требуют его заменить?
Познай свой язык
Больша?я часть критики JavaScript возникла вследствие невежества, незнания языка и нежелания по-настоящему его изучить.
Ключевое слово
this
, прототипное наследование и нехватка иммутабельности — вот три основных источника путаницы в JavaScript. Я понимаю вас, если вы привыкли к языку, ведущему себя иначе. Мне понятно ваше смятение, а иногда и раздражение.Но всё это не является непреодолимыми препятствиями. В изучении того, как на самом деле работает JavaScript нет ничего космически сложного, если у вас действительно будет желание учиться.
Вполне можно понять, почему разработчики стремятся к тому, чтобы другой язык заменил JavaScript, раз и навсегда устранив все его проблемы, но это нереалистично и не станет реальным решением.
Не ломайте веб
Главный принцип проектирования для JavaScript, а также для HTML и CSS, заключается в том, что новые возможности никогда не должны «ломать» уже существующие веб-сайты.
По сути, это превращает JavaScript в язык программирования, в котором возможно только добавление: возможности могут добавляться только в том случае, если они не повредят существующим веб-сайтам, но уже имеющиеся возможности никогда не должны меняться или удаляться.
Этот принцип гарантирует, что уже готовые веб-сайты никогда не поломаются, даже если они создавались десятки лет назад, и комитет TC39 прилагает серьёзные усилия для того, чтобы этот принцип не нарушался.
Это хорошая черта, но она накладывает на JavaScript бремя: возможности могут только добавляться в него, но никогда не меняться.
Поэтому несмотря на то, что сбивающие с толку аспекты JavaScript, например, ключевое слово
this
, теоретически можно исправить, это может нанести урон существующим веб-сайтам, которые идеально работали до внесения изменений. И это просто неприемлемо, потому что нарушает принцип «не ломайте веб».Другой язык — не решение
Теоретически, на замену JavaScript можно реализовать новый язык. Предполагаю, что это станет техническим и логистическим кошмаром, который продлится целую вечность, но в целом это вполне реализуемо.
Но этот новый язык тоже должен будет придерживаться принципа «не ломайте веб», что по сути также превратит его в только дополняемый язык. Думаю, вы уже можете предвидеть, как энтузиазм относительного этого языка постепенно угаснет, и вскоре мы снова услышим те же стоны о необходимости его замены.
Ограничения, накладываемые на JavaScript этим принципом, ограничивают возможные пути его эволюции, и будут относиться к любому языку, который стремится его придерживаться. Именно это превратило JavaScript в то, чем он является сегодня, и язык, который бы заменил его, никоим образом не смог бы избежать той же судьбы.
На самом деле беспрецедентная обратная совместимость JavaScript, сохраняемая два с лишним десятка лет, является огромным достижением. Она сыграла серьёзную роль в эволюции того веба, который мы имеем сейчас, и JavaScript следует за это благодарить, а не ненавидеть.
С чистого листа?
Надеюсь, теперь вы осознаёте, насколько мала вероятность того, что другой язык полностью заменит JavaScript. Но если вы всё равно не хотите подробно изучать JavaScript, то для вас есть надежда в лице WebAssembly и дюжины других языков, которые компилируются в JavaScript.
Меня не перестаёт впечатлять TypeScript, добавивший к JavaScript статическую типизацию, и PureScript, который по сути является Haskell в браузере, позволяющим писать полностью работоспособный код в парадигме функционального программирования.
Но, как это всегда бывает, дополнительный этап компиляции добавляет сложности и вопрос заключается в том, стоит ли оно того. На данный момент я бы порекомендовал вам изучать TypeScript, потому что он является надмножеством JavaScript, и следовательно, они очень схожи. Кроме того, он активно разрабатывается и имеет большое сообщество.
Также вам понадобится время на его изучение. Время, которое можно потратить на тщательное изучение JavaScript. В нём нет ничего особо трудного, и после того, как вы изучите его причуды, увидите, что это невероятно мощный и гибкий язык.
Он неидеален, но, повторюсь, как и любой другой язык.
Выбор за вами.
Комментарии (204)
lanseg
27.11.2019 13:05+1Мне, вообще, не слишком по душе языки с нестрогой динамической типизацией.
igor-sheludko
27.11.2019 20:56+2Уместно говорить что JS — это плохо, поработав с ним несколько лет. Просто «мне не по душе» — довольно слабая аргументация.
Простой пример для бэкенда. Вы получаете данные от веб-апи другого сервиса. На том же c# вам нужно описать структуры, в которые вы будете парсить Json. А если ответ сервиса поменяется (после апдейта) — у вас все посыпется. На node и js такие задачи отыгрываются с меньшей болью за счёт проверок нужных элементов формата. Динамическая типизация — это не всегда плохо, иногда это полезно. А ещё есть TypeScript.piton_nsk
27.11.2019 21:06На том же c# вам нужно описать структуры, в которые вы будете парсить Json. А если ответ сервиса поменяется (после апдейта) — у вас все посыпется.
Может я до конца не понял мысль, но поечму все должно посыпаться?igor-sheludko
28.11.2019 00:19-1Пример не удачный. Получили данные, спарсили, что-то использовали для обработки и передали дальше. Если что-то важное поменяется, то оно так или иначе обнаруживается либо проверками, либо эксепшином. При грамотной проверке данных и обработке ошибок большой разницы не будет. Преимущества могут быть только в более коротком и постом коде на JS.
Guitariz
28.11.2019 09:23При грамотном проектировании на <любое название языка> большой разницы не будет — да.
Вопрос, должно ли приложение падать, когда на бек приходят неконсистентные данные — мой ответ да, но у каждого свое видение.piton_nsk
28.11.2019 12:38Вопрос, должно ли приложение падать, когда на бек приходят неконсистентные данные
Это тоже важный вопрос, имхо зависит от приложения. Ну или от того, что именно считать неконсистентными данными.
piton_nsk
28.11.2019 12:52Преимущества могут быть только в более коротком и постом коде на JS.
Парсинг 3 варианта jsonvar user = JsonConvert.DeserializeObject<User>("{ Name:'Test', Age:10}"); user = JsonConvert.DeserializeObject<User>("{ Age:10}"); user = JsonConvert.DeserializeObject<User>("{ Name:'Test', Age:10, NewProperty:5}");
kasthack_phoenix
27.11.2019 21:29+4А если ответ сервиса поменяется (после апдейта) — у вас все посыпется
Что по вашему должно произойти при правильной реализации? Вернуться где-нибудь NAN, если вместо числа пришла строка?
norguhtar
28.11.2019 05:57Там про изменение структуры json. Но это обычно можно в сериализаторе подшаманить включив игнор неизвестных полей.
doctorw
27.11.2019 22:59+3А если ответ сервиса поменяется (после апдейта) — у вас все посыпется.
Пусть лучше сыпется, зато мы сразу об этом узнаем, чем оно где-то там внутри тихо проглотит несоответствие контракта, а потом ошибка вылезет совсем в другом месте создавая возможность попортить данные.igor-sheludko
28.11.2019 00:22-1Многое будет зависеть от обработки ошибок, но пожалуй лучше сразу обнаружить. Если только нам не все равно что там приходит. Но в этом случае можно и не парсить.
MooNDeaR
27.11.2019 23:29+2Я что-то не понял почему "посыпется" — это плохо? Лучше, чтобы произошло "что-то", но не знаю что?
viirtus
27.11.2019 23:51Видимо, вы никогда не писали бэкенд на языках со статической типизацией.
Требующие динамики штуки делаются точно так же с использованием map/hash-table/итд.
Там, где это не нужно (99.9% случаев), статические контракты делают код читаемым и легко поддерживаемым, а апи — версионируемым и надёжным.
0xd34df00d
28.11.2019 02:49На node и js такие задачи отыгрываются с меньшей болью за счёт проверок нужных элементов формата.
Не понял этот аргумент.
Конкретно на C# я не писал, а вот на ещё более строго типизированном хаскеле я таки писал и пишу. Если речь о нужных элементах, то я просто в своём представлении жсон-структуры описываю лишь нужные мне элементы, и наличие/типы остальных меня не волнуют. Если речь о типах элементов, то я пишу
Either
и тому подобные вещи и явно обрабатываю все возможные варианты типов, которые я поддерживаю.
Можно даже обмазаться современными фишками и написать, чтобы это всё прозрачно было, почти как в жс, только со всеми статическими проверками и гарантиями.
igor-sheludko
28.11.2019 08:55Да, вы правы, большой проблемы нет. Все можно решить, но, пожалуй, с большим объемом кода и большим временем, затраченным на такую ситуацию (описание структур и обработка ошибок). Вообще нет большого смысла обсуждать абстрактные задачи. Интересный эксперимент мог бы быть в реализации одной и той же задачи на разных языках. Но это возможно для бэкенда. На фронте вариантов пока что нет. Только JS. И принести новый язык в браузер — это большая работа, при этом JS выкидывать нельзя для совместимости.
0xd34df00d
28.11.2019 23:28Все можно решить, но, пожалуй, с большим объемом кода
Да не сказал бы. Я просто пишу
data MyRecord = MyRecord { name :: String , age :: Int , address :: ... } deriving (Generic, FromJSON)
и всё, описана структура ошибок, десериализация есть, все дела. Ошибки не описаны, но за них отвечает библиотека, да и всё равно лучшее, что я могу сделать — это их обработать.
К слову об обработке… Если у меня есть файл со 100500 строками жсона, и мне надо их распарсить с возможностью обработки этих самых ошибок, то у меня будет очень тупой код типа такого:
parseFile filename = do contents <- readFile filename case sequence eitherDecode' $ lines contents of Left err -> putStrLn [i|Unable to parse JSON: #{err}|] Right records -> ... тут делаем что-то с записями ...
И, например, если записей действительно 100500, и надо подсчитать какую-то статистику по ним, то такой код будет работать за O(1) по памяти, что тоже приятно.
А как у вас там с этим?
Crandel
01.12.2019 13:54-1Все можно решить, но, пожалуй, с большим объемом кода и большим временем, затраченным на такую ситуацию (описание структур и обработка ошибок)
Чтобы больше не писать такой ерунды рекомендую посмотреть это видео. На хаскеле и скале реализуется так же
Scott Wlaschin - Talk Session: Domain Modeling Made Functionalvintage
28.11.2019 19:46На том же C# вам ничего не мешает пользоваться динамической типизацией там, где она вам нужна. А не как в ноде — никогда не знаешь что прилетит в функцию.
mr_tron
27.11.2019 13:37+4Другие языки тоже столкнутся с такими проблемами?
Это прост красиво null == 0 false null < 0 false null <= 0 true Самое очевидное приведение типов. [] + [] "" [] + {} "[object Object]" {} + [] 0 {} + {} NaN А это числа, которые сортируются как строки [1,0, 4, 13, 9, 3].sort() Array(6) [ 0, 1, 13, 3, 4, 9 ] переполняются как инты 1 << 31 -2147483648 1 << 32 1 и теряют точность как эммм... флоаты? 103209823048320840000 + 1 103209823048320840000 103209823048320840000 + 20000 103209823048320860000
gearbox
27.11.2019 14:00+1Ни в коем случае не пытаясь оправдать очевидные ляпы в языке, задам все же вопрос который задаю каждый раз когда вижу эти замечательные списки ляпов или когда мне задают подобные вопросы на собеседованиях — что именно вы пишете что втыкаетесь в эти проблемы?
Поведение sort описано в документации, то что в js нет интов (не было, теперь есть но их надо объявлять явно) — должно быть известно с первых дней программирования на этом языке (ну или переходите на язык на котором можно писать не читая документации)
Со всем остальным — если вы пишете нормальный код и используете нормальные пакеты — вы просто не должны сталкиваться. Я за четыре года не столкнулся ни с чем не только из вышеперечисленного но и из гораздо более полных и обширных плачей Ярославны по этому поводу.Free_ze
27.11.2019 14:14+1что именно вы пишете что втыкаетесь в эти проблемы?
Никто именно так не пишет, разумеется. Но у всех и всегда случаются баги, а с такими раскладами их признаки способны всплывать далеко от места возникновения ошибки. Отладка и тестирование становятся интереснее, но дольше. К сожалению, власть TS здесь ограничена комплайл-таймом, требуются изменения в дизайне платформы.
Внимание, наброс:секрет ли, что фронт-енд сейчас — самая долгая в разработке и стабилизации часть типичного веб-приложения? Это объяснимо, но не последней причиной этому — дизайн JS.JustDont
27.11.2019 15:29секрет ли, что фронт-енд сейчас — самая долгая в разработке и стабилизации часть типичного веб-приложения?
Што?
Словом «самая» — вы сравниваете что с чем, конкретно? Фронт с остальной частью? А объем функционала вы во внимание не хотите принять? Если не хотите — так я вам сразу скажу, что фронтэнд гугла был самым простым и легким в стабилизации. А если хотите — тогда переформулируйте ваше утверждение так, чтоб оно не было бредом.
А еще вы можете попробовать сравнить веб фронт-энд с написанием, скажем, аналогичного фронтэнда на С++. Давайте посмотрим, что там будет быстрее разрабатываться и стабилизироваться?Free_ze
27.11.2019 15:44-1Словом «самая» — вы сравниваете что с чем, конкретно? Фронт с остальной частью?
Именно.
А объем функционала вы во внимание не хотите принять?
В мире существуют не только веб-проекты с фокусом на морде, но и энтерпрайз с жирной бизнес-логикой. Мы абстрактный функционал сравниваем или языки?
Я отталкиваюсь от своего опыта — среднего уровня (по сложности) фронт и относительно ёмкую бизнес-логику, что пилят фуллстеки. Да, среднестатистические разработчики. Фронт статистически генерирует больше багов. Можно сказать, что мы криворукие, но ведь тогда всё было плохо равномерно, почему у доброго десятка команд одинаковые проблемы?
вы можете попробовать сравнить веб фронт-энд с написанием, скажем, аналогичного фронтэнда на С++
Достойный оппонент, да) Как насчет C#? И не хотелось бы сейчас баттлить React vs Blazor, фреймворки оставим за скобками.
Я согласен с тем, что поехавшая верстка, кроссбраузерность — это проблемы не про JS. Но куча всякого в стиле: «Сервер прислал не то, что ожидали и понеслась...» — этого сплошь и рядом.JustDont
27.11.2019 15:56+2Как насчет C#?
Да без проблем. Хоть дельфи. Веб всё равно окажется быстрее с запасом. Были времена когда для нормальной жизни без фреймворков нужно было сначала написать себе неслабую вспомогательную библиотеку, но сейчас, во времена вебкомпонентов и всего подобного — уже нет, не надо. Даже без шаблонизации можно спокойно жить, потому что вся статика всё равно будет свёрстана в html, а движуха императивных правок в DOM будет ограничена точками, где она действительно нужна.
Но куча всякого в стиле: «Сервер прислал не то, что ожидали и понеслась...»
Это происходит не потому, что проверять ответы сервера в JS — это прям так сложно и нетривиально, а потому, что во многих случаях вполне допустимо просто ничего не делать (и пусть страница падает себе, юзеры переживут). В тех местах, где в вебе происходит что-нибудь дорогое (например, деньги плотятся) — там ответы сервера очень даже так проверяют, и не падают.Free_ze
27.11.2019 16:12Веб всё равно окажется быстрее с запасом.
Вы отождествляете браузерные API с JS и фреймворки с языками, не надо так.
Прототипы — да, быстрее. Но поддерживать имеющуюся объемную кодобазу, если оценивать разработку фич «брутто» (с тестированием и стабилизацией), то выходит уже не так прекрасно.
пусть страница падает себе, юзеры переживут
ОК, но наши юзеры, например, не будут в восторге от такого поворота, вот на отладку хитрых кейсов всё время и уходит.
там ответы сервера очень даже так проверяют, и не падают.
Руками проверяют, тонной тестов и ручного тестирования. Это дорого. Но делать нечего, пока только JS/TS.JustDont
27.11.2019 16:33Вы отождествляете браузерные API с JS и фреймворки с языками, не надо так.
А вы, когда упомянули C# — вы конечно же имели в виду, что вы хотите на нём посоревноваться с JS только языком, не привлекая стандартные библиотеки? Точно-точно это имели в виду?
ОК, но наши юзеры, например, не будут в восторге от такого поворота, вот на отладку хитрых кейсов всё время и уходит.
Нормальные люди выбирают транспортный слой со строгой типизацией. Все прочие — сидят JS отлаживают, ручным тестированием.
А потом у них в итоге JS плохой, ага. Про танцора и яйца в этой теме уже, кажется, поминали.Free_ze
27.11.2019 16:38Точно-точно это имели в виду?
Почему вы считаете, что могло быть иначе?) Глупо было бы отлицать то, что JS правит веб-фронтом на данный момент. Но это не делает лучше язык лучше.
Нормальные люди выбирают транспортный слой со строгой типизацией.
Вот бы сейчас проблемы платформы инфраструктурными прокладками решать) Это точно удешевит процесс разработки?JustDont
27.11.2019 16:45Почему вы считаете, что могло быть иначе?)
Потому что в этом контексте меряться бессмысленно: на C# вы просто не напишете фронтэнд на «голом языке», и на JS тоже. Некоторый объем сторонних библиотек или браузерного API вам будет необходим в любом случае.
Вот бы сейчас проблемы платформы инфраструктурными прокладками решать)
Если ваша проблема в том, что вы доставляете что-то неожиданное с бека на фронт — то как вы собрались это решать без создания привязки типов, которая ваше «непредсказуемое» всегда будет превращать в предсказуемое что для фронта, что для бэка?
Ах да, я и забыл, ручным тестированием и нытьём на то, что типы в JS посмели работать не точно так же, как на бэке или в транспорте (что справедливо практически для любых разных произвольно взятых технологий, кстати).
Это определенно удешевляет процесс разработки, ага.Free_ze
27.11.2019 17:34на C# вы просто не напишете фронтэнд на «голом языке», и на JS тоже.
Чтобы сравнивать языки, мне не нужно писать фронт-енд) Достаточно писать логику (то, что у вас промеж вызовов API фреймворка).
как вы собрались это решать без создания привязки типов, которая ваше «непредсказуемое» всегда будет превращать в предсказуемое что для фронта, что для бэка?
Никак, можно только снижать вероятность факапов теми или иными средствами.
Это определенно удешевляет процесс разработки, ага.
Да, для нас это наиболее дешевый вариант, наименьшее из зол.
Язык/платформа, безопасная к типам в рантайме, решила бы эту проблему бесплатно.JustDont
27.11.2019 17:48+2Достаточно писать логику
Так и пишите. Или для JS вы скажете, что вам для написания логики типичного условного фронтэнда надо складывать массивы с объектами, а в JS это странно работает?Free_ze
27.11.2019 17:53-2С моего объяснения причин «складывания массивов с объектами» диалог и начался.
JustDont
27.11.2019 17:57+2Ваше «объяснение» никак не привязано к собственно JS.
Free_ze
27.11.2019 18:04-3В том же дотнете такая проблема невозможна потому, что там типы контролируются виртуальной машиной даже в рантайме.
0xd34df00d
27.11.2019 18:23+3А зачем их контролировать в рантайме в том случае, когда у вас есть достаточно сильный тайпчекер в компилтайме?
Free_ze
27.11.2019 18:36-2У JS его нет ни в каком тайме)
С TS уже неплохо, но тогда размывается граница между проектами (допустим, фронту модельки генеряться полагаясь на другой проект).
Формализации взаимодействия с третьей стороной это помогает на уровне: «Будем полагать, что этот компонент подчиняется этому контракту». Если ожидания не оправдались — все пойдет JS-сценарию.0xd34df00d
27.11.2019 19:45В рантайме таки есть, просто там ещё есть преобразования.
Типов нигде нет в том случае, если вы пишете на С с
void*
.
dakuan
27.11.2019 19:07Или для JS вы скажете, что вам для написания логики типичного условного фронтэнда надо складывать массивы с объектами, а в JS это странно работает?
Проблема не в том, что это «странно» работает, а в том, что это вообще работает. И это усложняет поиск багов. В нормальном языке подобный код должен вызывать исключение.
mr_tron
27.11.2019 15:02Ну вот первое это из моего опыта. Словил багу, где с сервера в json приходил null вместо числа.
Сортировка может и описана в документации, но это поведение неожиданное, тоесть надо действительно сесть и прочитать сперва документацию от корки до корки, чтобы узнать подробности про вот такое поведение. В более предсказуемом языке глубоко документацию надо читать чтобы узнать о фичах, а не о подводных камнях. Чувствуете разницу?
И что кстати значит, что в js нет интов? А что же тогда переполняется? Типичный int.JustDont
27.11.2019 15:33В более предсказуемом языке глубоко документацию надо читать чтобы узнать о фичах, а не о подводных камнях.
Примеры «более предсказуемых языков» не назовете? Вместе посмеемся.
Вообще, если вам не приходилось идти в документацию (а то и в исходный код) ради выяснения, почему у вас что-то, что казалось должно бы работать — не работает; то скорее всего это означает не крутизну языка, а то, что вы на этом языке ничего по-настоящему серьезного не делали.fougasse
27.11.2019 16:59+1Ниразу не ходил в исходник C++, Java, Kotlin, C#, python.
Даже не понимаю, что вы понимаете под исходником языка — компилятор?
Или реализация сравнения null или сложения находится где-то в другом месте?JustDont
27.11.2019 17:09+2Даже не понимаю, что вы понимаете под исходником языка — компилятор?
В нормальных языках компилятор языка написан на самом языке, так что да.
Но моя фраза про «исходный код» была о том, что не всегда ответы на интересное поведение языка можно найти в документации. Иногда документации об этом попросту нет — и тогда кому-нибудь (не обязательно вам) приходится смотреть в исходный код, да.fougasse
27.11.2019 17:27-2Т.е. (если следовать вашей аналогии) предлагается идти в исходники, например, gcc/clang для того, чтобы узнать как (не)работает простейшая операция сложение?
Референс от Mozilla:
Addition (+)
The addition operator produces the sum of numeric operands or string concatenation.
Syntax
Operator: x + y
Examples
// Number + Number -> addition
1 + 2 // 3
Куда мне нужно смотреть в компиляторе для случая
103209823048320840000 + 1 == 103209823048320840000
JustDont
27.11.2019 17:49+1Сфигали вы смотрите на сложение, а не на типы?
fougasse
27.11.2019 20:43-1Ну, ок, смотрю я на тип — дабл.
Я реально не понимаю, почему, если литерал явно больше максимального значения — это вообще "работает". Я в спеке нашел только количество значений у типа. Про ситуацию с переполнением — там, вроде, ничего нет.
Хотя, справедливости ради, могли бы и, вообще, в строку неявно конвертировать и конкатенацию делать — ещё более дикое поведение.
Почему игнорируются последние разряды, а не первые?JustDont
27.11.2019 23:40+2Ну, ок, смотрю я на тип — дабл.
Нет, не дабл.
> The JavaScript Number type is double-precision 64-bit binary format IEEE 754 value.
А уж если б вы открыли спецификацию IEEE754, или в крайнем случае прошли бы по ссылке на википедию, которая все основы разжёвывает, вы бы там нашли и описание поведения при переполнении.
gearbox
27.11.2019 17:31+3>Словил багу, где с сервера в json приходил null вместо числа.
Это типичное нарушение правил гигиены. Информация пришедшая из-за пределов периметра должна валидироваться, это от языка не зависит. Если не уверены что проверили все и везде — есть unknown в typescript для контроля периметра, если хочется по феншую. Но проверять придется.
>но это поведение неожиданное
Неожиданно пользоваться функцией не зная ее сигнатуры. sort принимает на входе функцию сравнения. Это необязательный параметр, но это параметр. Если вы открыли доку что бы посмотреть сигнатуру функции — вы это увидели. Дальше простая цепочка — если есть параметр и его можно не указывать — значит есть поведение по умолчанию. Какое? Ответ видим в том же абзаце где описывается этот параметр. Ситуация описанная Вами может возникнуть только при программировании наугад.
>В более предсказуемом языке глубоко документацию надо читать чтобы узнать о фичах, а не о подводных камнях. Чувствуете разницу?
Нет, не чувствую. Берем язык x и используем функцию y. О наличии функции y в языке x мы как узнали? common knowledge?
>И что кстати значит, что в js нет интов?
обычные числа в js — float, инты надо задавать явно — либо в массивах (intXArray) либо Bigint. Переполнение возникает потому что Вы применяете bitwise операцию к float, она естественно делается с приведением типа а приводится к 32 разрядному инту, результат внезапно приводится обратно к float. То есть воткнувшийся в эту ситуацию не понимает как хранятся числа в js — это я уже упомянул, знать надо. Все остальное — следствие. Попытка применить битовую операцию к float у любого вменяемого программиста вызовет вопрос — как оно будет сделано.Neikist
27.11.2019 18:02-1О наличии функции y в языке x мы как узнали? common knowledge?
Во первых да, в стандартных библиотеках многих языков очень многое пересекается. Во вторых есть IDE, прекрасно работающие со статически типизированными языками и обычно достаточно попробовать написать что то по смыслу похожее — IDE подскажет названия и сигнатуры всех функций и типов.gearbox
27.11.2019 18:10+2тогда не понимаю в чем проблема? Нет IDE для js или Вы не умеете ей пользоваться? Или она не подсказывает сигнатуры? С тем же сортом — как его можно использовать зная только название? Как он отсортирует — по возрастанию или по убыванию? Что вернет — новый отсортированный массив или отсортирует тот на котором вызван? Есть какое то общепрограммистское соглашение по сигнатурам функций сортировок которого все придерживаются а js цинично и с особой жестокостью нарушает?
Neikist
27.11.2019 19:05Вот не поверите, сколько пишу на котлине — в документацию или сорцы используемого кода лезть приходилось только за совсем неочевидным (в случае если редактирую уже сущестувующий код). IDE сразу подсказывает может ли функция вернуть null или нет (а так же ругнется компилятор), функция не может вернуть значения разных типов. Int это 5 и 0, а float это 5f или 5.0f. И просто так инт с флоатом не сложить, компилятор сразу ругнется вместе с IDE.
IDE для языка со слабой динамической типизацией будет гораздо хуже в этих отношениях.
Что касается sort — на обычном списке или коллекции его вызвать нельзя (интерфейс не имеет методов для изменения), сначала необходимо преобразовать в изменяемую коллекцию (правда иммутабельности полноценной тоже нет для списков, но это отдельный разговор), а потом отсортировать именно ее. На обычном списке IDE подсказывает только sorted, которая список изменить не может (напомню, интерфейс не имеет методов для изменения) а только возвращает новый, отсортированный список.
Ну и ни разу не видел sort который бы сортировал не по возрастанию. А как отсортировать по возрастанию цифры понятно — Int, Float и прочие реализуют интерфейс Comparable.
fougasse
27.11.2019 16:56Я с вами согласен, но как проблема со сложением зависит он того есть в JS тип int или нет?
103209823048320840000 + 1 = 103209823048320840000
103209823048320840000 + 20000 =103209823048320860000
где-то в документации можно найти что-то, что поможет так не «встрять»?gearbox
27.11.2019 17:32Это поведение float. Странно что вы этого не видите по первой строке.
>где-то в документации можно найти что-то, что поможет так не «встрять»?
Number_typefougasse
27.11.2019 20:47-3Упоминания про overflow в спеке нет.
Упоминания про литералы вне диапазона — """
Beyond this range, integers in JavaScript are not safe anymore and will be a double-precision floating point approximation of the value.
"""
Что такое not-safe?
Как-то много вопросов из спеки для такой простой проблемы как число, не так ли?
AlexBin
28.11.2019 18:17Это поведение float.
Это поведение float в JS.
Правильное поведение при переполнении чего либо выбросить ошибку переполнения.
При сложении [] + {} правильное поведение — это выбросить ошибку.
Было бы даже лучше, если бы функция sort выдавала ошибку сортировки чисел без указания метода сортировки, чем сортировала их по умолчанию как строки.
И т. д.
На такие тривиальные вещи глубоко читать документацию, стандарты и исходники языка — это онанизм.
Ну то есть, если я покупаю автомобиль, я не хочу читать инструкцию, как пользоваться дверной ручкой, стеклоподъемниками или дворниками. Я хочу выполнить интуитивно понятные действия и получить предсказуемый результат.
И уж тем более, я не хочу, чтобы бай дизайн было заложено поведение, что если включить дворники на пятой скорости, самопроизвольно открывался капот. Даже если это поведение описано в документации, мне такой автомобиль не нужен, ибо неизвестно, чего еще можно от него ожидать.staticlab
28.11.2019 18:28я не хочу, чтобы бай дизайн было заложено поведение, что если включить дворники на пятой скорости, самопроизвольно открывался капот
А частичное отключение автопилота при повороте штурвала на Airbus A310 как вам? Это тривиальная вещи или нет? Нужно ли об этом было инструктировать пилотов рейса SU593 об этом?
AlexBin
28.11.2019 19:21А частичное отключение автопилота при повороте штурвала на Airbus A310 как вам?
Никак. Я в этом ничего не понимаю. Я не знаю, тривиальная это вещь, или нет. Я не знаю, принято так на других самолетах, или нет. Я не знаю, интуитивно это для пилота, или нет.
Извините, не могу ответить.
AlexBin
28.11.2019 19:47+1Послушайте, я же не многого прошу. Просто пускай язык перестанет пытаться исправлять ошибки, которые допустил я.
Если я забыл провалидировать данные или преобразовать типы, я хочу сразу получить ошибку, а не ситуацию, когда у меня оказывается целый месяц в базу пишутся неправильные данные, и какой-то клиент это случайно заметил.
Если я забыл открыть файл перед записью, я хочу сразу получить ошибку, а не чтобы язык писал в какой-то файл по умолчанию, чтобы в продакшне это привело к отсутствующим файлам, когда они понадобятся.
Ну то есть, я конечно не против умного поведения, но тогда такое поведение должно быть либо более менее безопасным, либо хотя бы интуитивно предсказуемым. А у JS эта граница похоже плохо откалибрована.
gearbox
28.11.2019 22:21+1Это поведение float в IEEE 754. Ну или покажите мне язык где бросает эксепшин на это: 103209823048320840000 + 1?
Neikist
28.11.2019 23:21-1Котлин ругнется на этапе компиляции если попытаетесь такой литерал использовать, что значение выходит за границы диапазона. Да подозреваю многие языки ругнутся. А Float такое позволит, да. Но для этого придется записать 103209823048320840000f + 1f, т.е. явно задекларировать что этот литерал значение с плавающей точкой.
AlexBin
28.11.2019 23:52-1Это поведение float в IEEE 754.
Ну хреновое поведение, что я могу сказать.
Ну или покажите мне язык где бросает эксепшин на это: 103209823048320840000 + 1?
Как я уже написал выше:
Ну то есть, я конечно не против умного поведения, но тогда такое поведение должно быть либо более менее безопасным, либо хотя бы интуитивно предсказуемым.
То есть, если язык может решить эту проблему без каких-либо последствий, то почему нет? А если не может, то нужно вываливать ошибку. Вот сейчас у меня под рукой питон, он прозрачно и предсказуемо выполняет операцию, не заставляя меня идти читать стандарты, документацию и исходники по таким элементарным вещам.
Яваскрипт же просто молча не выполнит операцию, и к каким последствиям это приведет, и когда эти последствия кто-нибудь заметит — загадка, ожидающая захватывающих дебагов в будущем.
tcapb1
28.11.2019 11:11Всё равно вам придётся держать в голове и то, что числа сортируются как строки, и то что целые числа по умолчанию не int, а float. А также множество всяких других нелогичностей JS. Т.е. мы изначально при разработке должны учитывать больше, чем программисты на других, более грамотно спроектированных языках.
Если не будете держать в голове — получите кучу головной боли, когда приложение перестанет работать как задумано. Например, в массиве изначально были числа от 1 до 5, и всё сортировалось как надо, а потом туда добавились числа 10, 11 и т.д. Сортировка сбилась. Или у вас есть автоинкремент, который изначально работает как надо, а потом, когда он доходит до больших чисел — упираемся в точность float. Приятной отладки.
JS конечно не один такой. В других языках тоже есть много странного легаси, вещей, которые надо учитывать. Можно вспомнить PHP с прыгающими параметрами needle и haystack в функциях, багом с порядком аргументов в тернарном операторе, который тянулся до PHP 7.4 (да и теперь по сути была лишь обрезана функциональность). И да, любой, даже самый прекрасный язык со временем обрастает легаси и неинтуитивным поведением (всё сразу спроектировать идеально видимо просто невозможно, а потом для обратной совместимости приходится тянуть хвосты).
Но есть языки, на которых программировать приятнее, держать в голове при разработке приходится меньше, тесты получаются компактнее, а выстрелить в ногу — сложнее.vintage
28.11.2019 20:01То чувство, когда давно не пользовался сортировкой в JS и уже забыл про эти подводные камни.
0xf0a00
27.11.2019 14:03Вам же пишут:
Больша?я часть критики JavaScript возникла вследствие невежества, незнания языка и нежелания по-настоящему его изучить.
Это не инструмент убогий, это вы дурак и невежда и не поняли божественный JS.vlreshet
27.11.2019 14:05-1Это не инструмент убогий, это вы дурак и невежда и не поняли божественный JS.
Ну, не так грубо, но в целом так оно и есть. Пока одни ноют что на нём писать невозможно — другие на нём огромные SPA выстраивают, и сложнейшие бекенды на ноде.Angmarets
27.11.2019 14:21+2При должном усердии я могу есть суп вилкой. Однако если мне в ресторане подадут к супу вилку — я буду ныть.
vlreshet
27.11.2019 15:08Ну, в Китае вам к супу вообще палочки выдадут. И продуктивнее будет научиться ими правильно и быстро есть, а не пытаться черпать как ложкой, да возмущаться что если сунуть палочку в нос — то будет больно. Мол, с ложкой такого не сделаешь. Вот и тут так — ну сложилось уже исторически что в браузерах правит JS — значит его нужно изучить и работать. Суровая реальность.
Free_ze
27.11.2019 15:22+1vlreshet
27.11.2019 15:48+2Это забавно, но не более. В этой картинке не ломается обратная совместимость, в случае установки круглых колёс. А вот заменить главный язык в браузере — это совсем другое. Скажите бизнесу что вам не нравится писать на JS, и надо всю кодовую базу за последние 20 лет выкинуть)
Free_ze
27.11.2019 16:03Можно добавить режимы совместимости (JS не привыкать после strict mode) или параллельно готовить альтернативу со слоем совместимости (WASM).
Не думаю, что ошибусь насчет того, что подавляющее число проектов на JS живет меньше 5 лет в первозданном виде. У JS миграции ограничиваются скорее исполняющей средой (браузеры), а не тоннами кода, который работает десятилетиями.vlreshet
27.11.2019 16:26+3jQuery вышел в 2006-ом году. На нём до сих пор дохренилеард сайтов (да тот же хабр имеет его на фронте). Тысячи плагинов, скриптов, и т.д. Такие ли 5 лет живёт JS код?
Free_ze
27.11.2019 16:34+1jQuery вышел в 2006-ом году.
ОК, jQuery и еще пара сотен проектов могут не входить в указанное мной «подавляющие большинство».
да тот же хабр имеет его на фронте
Сколько редизайнов было на хабре за время его существования?
Тысячи плагинов, скриптов, и т.д.
… и ни одного нормального WYSIWYG-редактора))JustDont
27.11.2019 16:38+1… и ни одного нормального WYSIWYG-редактора))
В оффлайне (с гораздо более долгой историей) дай-то бог один нормальный найдётся (и это не ворд). А вы от веба что-то хотите.
justboris
28.11.2019 00:54ОК, jQuery и еще пара сотен проектов могут не входить в указанное мной «подавляющие большинство».
На всякий случай замечу, что согласно исследованию больше 80% сайтов все ещё используют jQuery. При этом в вакансиях от разработчиков сейчас требуют в основном другие фреймворки. То есть разрабатывающиеся сейчас проекты не совпадают с тем, что мы видим в свободном интернете.
Чем это еще объяснить кроме как не большим количеством легаси сайтов?
Free_ze
28.11.2019 11:56Чем это еще объяснить кроме как не большим количеством легаси сайтов?
Многие продолжают использовать jQ, потому что их всё в ней устраивает, например.
При этом в вакансиях от разработчиков сейчас требуют в основном другие фреймворки.
По моему скромному мнению, саму библиотеку можно изучать на ходу и нет никакого смысла писать это в требования.justboris
28.11.2019 11:58Хорошо, а как это согласуется с вашим "подавляющее число проектов на JS живет меньше 5 лет в первозданном виде"?
Люди не могут с одной библиотеки Javascript на другую переехать, а вы предлагаете заменить язык целиком.
Free_ze
28.11.2019 12:44А если допустить вероятность, что большинство (кому ехать, а не шашечки) продолжает использовать даже в новых проектах то, что они хорошо знают — jQuery?
Люди не могут с одной библиотеки Javascript на другую переехать, а вы предлагаете заменить язык целиком.
Люди могут просто не хотеть, потому что нынешние альтернативы не дадут ощутимых преимуществ в конкретных условиях.
Я ни в коем случае не говорю, что нужно устраивать JS геноцид, миграция обязательно должна быть эволюционной, позволяющей совмещать старые и новые реализации.
fougasse
27.11.2019 17:01Вполне получается сказать бизнесу, что не нравится писать на Java и быстрее будет на Котлине, например.
Никто никакую базу не выкидывает, если нормально подойти к процессу миграции.
Или Java недостаточно популярна?
ivanuzzo
27.11.2019 20:39+4в Китае к супу выдают ложку, правда, немного не такую, как у европейцев.
Вот такую выдадут:
Ваш пример некорректен.
gatoazul
27.11.2019 21:05Согласен с вашим ответом по сути, но в Китае суп все-таки пьют, а не едят палочками. По крайней мере «есть суп» на китайский переводится как «пить суп».
0xf0a00
27.11.2019 15:24Мой сарказм вы приняли за чистую монету как я погляжу.
Пока одни ноют что на нём писать невозможно
Плохому танцору… дальше сами знаете. Таким людям дай идеальный язык все равно найдут проблему.
другие на нём огромные SPA выстраивают, и сложнейшие бекенды на ноде
Не аргумент ни разу. Оно так потому что JS обезьянок много, они готовы работать за еду, одну и туже обезьянку можно послать писать и фронт и бэк, а если у обезьянки недосточно мозгов ее всегда можно заменить потому что за воротами очередь. Отсюда колоссальная экономия на разработчиках в ущерб качеству продукта. Но у нас не век когда писали хорошо и грамотно, у нас век «эффективного менеджмента» когда отказоусточивость подменили аргументом «зато быстро поднимается», когда многопоточность заменили «да просто n инстансов запустим на проде», когда удобный отзывчивый UI с низким потреблением ресурсов заменили на объевшегося грибами выпускника художественного и пару JS обезьянок по 300$ с той же художки которым в лапки дали электрон.
Но самая большая проблема всего этого в том что JS обезъянки мнят себя не ясно чем, считают что круче JS ничего нет и не будет, категорически отказываются переучиваться или учить еще какой то язык с аргументным аргументом «я же могу сделать это на JS». Можешь, но выйдет лютейшее гов… А все от того что образования профильного у них как правило нету и понятия об области применения инструмента как правило тоже. Я ведь тоже могу написать бэк на C++ или Delphi, но пишу то на Java.igor-sheludko
28.11.2019 09:25Я тоже многому удивляюсь, но:
1) JS — не первый и не единственный язык про который можно сказать так, как вы высказались. До js-обезьянок были php, python, ruby и прочие обезьянки, которые осваивали эти языки потому что они простые и шли кодить на них. Ещё 15 лет назад молодое дарование убеждало меня, что преподавать С++ в ВУЗе нужно прекратить и заменить его на python.
2) Так уж повернулась история и мы имеем то, что имеем. Даже MS не смогла особо ничего лучше придумать для веба, чем создать TS. При том что до этого они вполне удачно создали C# для кроссплатформенной разработки. Я все же думаю, что там не обезьянки такие решения принимают.
3) В одном языке для фронта и бэка для небольших проектов много плюсов. А так как есть тенденция к микросервисам, то с точки зрения управления разработкой больших проблем не возникает. Разные части бэкенда большого проекта могут быть реализованы на наиболее подходящих языках.
vlreshet
27.11.2019 14:03
О, обожаю этот аргумент. Вопрос: часто вам приходится объект с массивом складывать?Самое очевидное приведение типов.
[] + []
""
[] + {}
"[object Object]"
{} + []
0
{} + {}
NaN
Ну, как минимум, тот же PHP страдает той же проблемойи теряют точность как эммм... флоаты?
103209823048320840000 + 1
103209823048320840000
php > var_dump(103209823048320840000 === (103209823048320840000 + 1));
И куча других языков тоже.
bool(true)worldmind
27.11.2019 15:53+1gearbox скорее всего такие ляпы не часто приводят к багам (хотя если случиться, то придётся долго дебажить), но они сигнализируют о том какого качества было проектирование языка, а хочется использовать хорошо сделанный инструмент, тот же питон содержит намного меньше таких ляпов, не говоря уже про хаскел.
gearbox
27.11.2019 17:47>но они сигнализируют о том какого качества было проектирование языка
А я и не говорю о том что язык прекрасен. Я говорю о том что эти ляпы не мешают жить если вы пишете на js так как вы пишите на нормальном языке. То есть ляпы есть но они не вынуждают вас их использовать. В этом и заключается мой вопрос — покажите мне ситуацию к которой вас подталкивает дизайн js в которой потребуются знания этих ляпов. Что касается хаскела — как хаскелист любитель/начинающий дилетант с удовольствием послушаю историй успешных хаскелистов овладевших языком не зная что там под капотом. Можно привести пример эффективной сортировки написанной на хаскеле без глубокого знания ситуации под капотом :) (для тех кто не в теме оставлю тут)worldmind
27.11.2019 17:53+1Так есть огромная разница между пониманием внутренней логики инструмента и заучиванием ляпов.
gearbox
27.11.2019 18:06+1Ляпы не надо учить. Если писать на js нормальный код с нормальными практиками — вы просто в них не будете втыкаться. 90% ляпов — неявное приведение типов. Странно слышать от апологетов статичной типизации что они страдают от того как они заложились на то что js будет приводить типы так как они рассчитывали. Апологет статичной типизации никак не рассчитывает, он либо приводит явно либо проверяет. Проблемы с js как правило у народа пришедшего с таких же динамичных языков, просто там приведение работает по другому и при этом они знают КАК.
Не закладывайтесь на приведение. Используйте === и явные преобразования типов.
zagayevskiy
27.11.2019 19:01+2Как насчёт функции, в которую приходит параметр, который иногда boolean, а иногда — лямбда? Это реальный случай, вот так сделали, какие-то люди, которые уже уволились. Это — норма?
Или вот я сейчас придумал — два параметра, на выходе — сумма. И нечаянно(порефакторили не так, а подсказать инструменты не могут) передали туда массив и объект, а на выходе — пустая строка. Это, что ли, норма?gearbox
28.11.2019 19:39>Как насчёт функции, в которую приходит параметр, который иногда boolean, а иногда — лямбда?
Никак. Там ведь стоит на входе if typeof bla bla, верно?zagayevskiy
28.11.2019 19:48Вы с таким пафосом говорите, будто это я этот говнокод написал. Нет, например, не стоит. А даже если стоит — что в этом хорошего? То есть каждую мельчайшую функцию надо проверить на тему того, что она там себе обрабатывает? Вот уж нафиг.
gearbox
28.11.2019 21:33+3>будто это я этот говнокод написал.
Нет конечно, но кто то же его писал? Какое отношение кривизна программиста имеет к дизайну языка? Напомню, изначально моя позиция — ляпы в языке есть, жить они не мешают. Если вы приводите свой пример в опровержение моих слов то моя позиция — лично Вам мешают жить плохие программисты. Те самые что на уровне прокладки между монитором и креслом. Есть ли они в js — есть, много, обсуждение этой статьи в том числе показывает наглядно что народ языка не знает. Есть ли они в других языках? Не знаю, мне реально без разницы.
>То есть каждую мельчайшую функцию надо проверить на тему того, что она там себе обрабатывает? Вот уж нафиг.
У Вас на входе функции — union, конечно будете проверять. Расскажите мне как вы обойдетесь без проверки на nil в go или тот же nothing в maybe? Это ведь не дизайн языка, это дизайн функции, и такому дизайнеру в любом языке оторвут руки предварительно поломав пальцы.
Не хотите выхватить сюрпризов в рантайме — используйте инструменты — eslint и typescript. В общем если хотите жить нормально — возможности есть. Для плача Ярославны поводы — тоже. Тут как бы сам себе выбирает что больше по душе.0xd34df00d
28.11.2019 23:32Расскажите мне как вы обойдетесь без проверки на nil в go или тот же nothing в maybe?
Я просто не буду проверять на nothing в maybe, если я не могу это адекватно обработать на этом уровне. Пусть код выше проверяет, а тайпчекер уже гарантирует, что кто-то это да проверит.
gearbox
29.11.2019 14:18>Я просто не буду проверять на nothing в maybe, если я не могу это адекватно обработать на этом уровне.
Да это понятно, я к тому что в любом случае эта обработка где то должна существовать. Я js c хаскелем и не пытаюсь сравнить :)
>а тайпчекер уже гарантирует, что кто-то это да проверит.
Так и в js можно притянуть typescript, там вполне себе приличный тайпчекер, просто речь изначально о js — я поэтому особо статичную типизацию в тред не несу. А так то есть вполне себе убойный аргумент — typescript и фронт с бэком на нем в одном наборе типов. Но это уже реально совсем другая история.
0xd34df00d
27.11.2019 18:30не говоря уже про хаскел
У меня до сих пор бугурт от совершенно корявой иерархии тайпклассов нумериков в стандартной prelude (и у кучи других людей тоже). Впрочем, со сравнением хотя бы проблем нет:
Prelude> 103209823048320840000 == (103209823048320840000 + 1) False
worldmind
27.11.2019 18:33Я на Хаскел смотрел давненько, уже подзабыл что там с этой иерархией было, не исключаю что и мне тогда некоторые вещи показались странными, но это совсем другого уровня проблемы, да и иерархия достаточно ограниченная структура и вполне может оказаться что все варианты со своими проблемами.
gearbox
28.11.2019 22:13:)
Prelude> 103209823048320840000.0 == 103209823048320840000.0 + 1.0 True
0xd34df00d
28.11.2019 23:21Ну так это IEEE754, что от него ждать. Вот если взять
Data.Ratio
...
Prelude> :m + Data.Ratio Prelude Data.Ratio> 103209823048320840000.0 == 103209823048320840000.0 + (1.0 :: Ratio Int) False
fougasse
27.11.2019 17:04-1Оправдание — так себе.
Почему +10000 не работает, а +15000 — уже «нормально»(ожидаемо) складывается?
Aingis
27.11.2019 18:59+1Самое очевидное приведение типов. [] + [] "" [] + {} "[object Object]" {} + [] 0 {} + {} NaN
Вы правда с этим столкнулись в коде или привели копипасту для плюсов? Приведение типов работает консистентно и как ожидается:
console.log([] + []) "" console.log([] + {}) "[object Object]" console.log({} + []) "[object Object]" console.log({} + {}) "[object Object][object Object]"
Mingun
27.11.2019 19:04-2А теперь уберите неизвестно зачем вами вставленный
console.log()
и удивитесь :)staticlab
27.11.2019 19:13+2А когда такой код может встретиться вне контекста выражения и зачем он может быть нужен?
Mingun
27.11.2019 19:37+4Выше уже объяснили: суть не в том, нужен или не нужен в каком-либо там контексте, а в том, какого… это вообще работает. А вы так огульно заменили инструкцию выражением и, типа, теперь всё нормально, проблемы как бы и нет. «Язык-то отличный, это вы дурак». А это, кстати, ещё один вопрос, почему в разных контекстах получаются разные результаты.
staticlab
27.11.2019 19:49А вы так огульно заменили инструкцию выражением
Не я :)
И в теории, если некоторый статический язык поддерживает перегруженный унарный оператор + для массивов, то в контексте выражения
{} + []
приведёт к ошибке типов, а в контексте инструкций — к валидной операции+[]
, если только символ+
не будет иметь в этом контексте особого смысла (как в Obj-C).
ivanuzzo
27.11.2019 20:46для создания бэкдоров и эксплоитов?
staticlab
28.11.2019 11:41+1Можете привести пример?
ivanuzzo
29.11.2019 16:46смотря для чего вам это нужно.
staticlab
30.11.2019 12:01+1Знать потенциальные векторы атаки всегда неплохо. Вот мне и интересно, как можно проэксплуатировать такое поведение JS.
ivanuzzo
30.11.2019 13:02-1Я склонен считать, что задавая подобные вопросы, вы предварительно не ознакомились с понятием обфускации в javascript. Думаю, с этого нужно начать. Такое поведение JS можно проэксплуатировать тем, что под внешне нечитабельной мешаниной из кода может оказаться вполне читабельная функция или команда. И делать она может все, что угодно, начиная от безобидного редиректа на другой ресурс.
И если человек не знаком с понятием обфускации, он вполне может пропустить такое у себя. И долго еще гадать, что за магия здесь происходит. И да, это можно сделать в любом языке, я думаю.justboris
30.11.2019 15:37Про обфускацию понятно, но это же не единственный вариант её реализации. От наличия или отсутствия этой конкретной фичи ситуация с эксплойтами не меняется. Закроют эту возможность – останутся другие: http://www.jsfuck.com
igor-sheludko
27.11.2019 21:00Ну так автор же про то, что нужно просто привыкнуть. Это непривычно, после другого языка. Кто много пишет на js, уже не удивляется :)
Guitariz
28.11.2019 09:30
polar11beer
28.11.2019 11:58+1Если пишете на языке, нужно знать его сильные и слабые стороны. То, что в javascript что-то работает не так, как ожидается после других языков, это не проблема javascript. Другие языки не столкнутся с этими проблемами, зато столкнутся с другими.
Скажем, в C++ нежелательно бросать исключение в конструкторе объекта, иначе можно получить утечку памяти. Тоже не очевидный момент, его просто нужно знать.
maxzh83
27.11.2019 14:03На данный момент я бы порекомендовал вам изучать TypeScript
Зачем? Если в заголовке такое:
JavaScript не нужно ничем заменять
JustDont
27.11.2019 15:36Затем, что TS не заменяет JS, и TS и JS не относятся друг к другу как непересекающиеся множества.
maxzh83
27.11.2019 15:50-1Ну это жонглирование словами. Расширить язык радикально другой концепцией (типизацией) не сильно отличается от замены на другой язык.
JustDont
27.11.2019 15:59+1Да нет, отличается. Или по-вашему ява с дженериками и ява без дженериков — это «не сильно отличается от замены на другой язык» (концепция-то радикальная)? Ну-ну.
rudinandrey
27.11.2019 15:31не знаю, страшно быть заминусованным, но я скажу что JS прекрасный язык, не надо его ничем менять. Не понимаю людей усложняющих себе жизнь всякими строгими типизациями и прочими вещами прокладками, что надо из одного языка компилить в другой язык. потом если что-то идет не так мучаться дополнительно. Да раньше было сложно отлаживать, сейчас открыл консоль, все видно. Честно не понимаю зачем простую вещь, делать сложной.
JustDont
27.11.2019 15:37Если вам с помощью простой вещи нужно будет делать большие сложные вещи — вы в итоге изобретете и свою собственную
убогуюстрогую типизацию, и многое другое.
nbytes
28.11.2019 02:52Почему же усложняющих, есть один крупный проект на TS и если бы без него, я даже боюсь представить, во что бы это вылилось, у нас 95% ошибок отлавливается при компиляции и если не дай бог бэк сломал контракты, при обновлении моделей из сваггера сразу все видно, параллельно другой командой ведётся проект поменьше но на JS, и столько сколько они дебежат это ужас, все ошибки только в рантайме. И дело тут не в архитектуре проектов, а именно в том, что одни «усложнили» себе жизнь типизацией, а другие «облегчили» используя обычный JS без типов.
softaria
27.11.2019 17:33+1Источник проблемы в том, что браузер сделали интерпретатором, а не чистой средой исполнения. Как кажется, у WASM есть все шансы это исправить — единый исполняемый код и любое количество компилируемых в него языков.
staticlab
27.11.2019 18:13+1Шанс есть, но сейчас WASM-модули вынуждены активно использовать glue-слой на JS для любого внешнего взаимодействия, в том числе и с DOM. Кроме того, для языков со своим рантаймом (.NET, Java) этот рантайм приходится тащить с собой в каждом приложении.
softaria
27.11.2019 18:17API к DOM, думаю, вопрос времени. А вот языки, скорее всего, появятся какие-то новые. Ну или это будут диалекты существующих. Тащить рантайм точно никто не станет.
none7
27.11.2019 21:15+1Очень далёкого времени. В настоящий момент даже планов таких нет и возможно не будет. Разработчики стандарта не видят проблемы в существовании оберток на JavaScript. Ведь WebAssembly существует для числодробилок и импорта существующего кода на Си. А если приходится часто обращаться к JavaScript коду, то это управляющий код и должен писаться на JavaScript.
softaria
27.11.2019 21:21-1none7
27.11.2019 21:35А гугл в своё время писал клиентскую часть Gmail на Java. Значит ли это, что JavaScript существует для эмуляции Java? Это конечно возможно, но оптимальным решением это определённо не будет.
softaria
27.11.2019 21:38А при чем здесь гугл и его webtookit?
WASM позиционируется вот так: WebAssembly (abbreviated Wasm) is a binary instruction format for a stack-based virtual machine. Wasm is designed as a portable target for compilation of high-level languages like C/C++/Rust, enabling deployment on the web for client and server applications.
Никакой привязки именно к си здесь нет.none7
27.11.2019 21:52+1А при чем здесь гугл и его webtookit?
Притом, что тоже низкопроизводительный велосипед как и все реализации компиляторов из Вашего списка. FAQ: Mostly HTML/CSS/JavaScript app with a few high-performance WebAssembly modules (e.g., graphing, simulation, image/sound/video processing, visualization, animation, compression, etc., examples which we can already see in asm.js today) allowing developers to reuse popular WebAssembly libraries just like JavaScript libraries today.
И какие могут быть высокопроизводительные библиотеки на чём то кроме C/C++/Rust?
Neikist
27.11.2019 21:28-1Ну например бридж в реакт нейтиве к нативу реально проблема. Почему обратное должно быть неверно?
то это управляющий код и должен писаться на JavaScript
В этом и проблема.
igor-sheludko
27.11.2019 21:13Проблемы нет. Старые фичи есть для совместимости, а новые фичи делают работу удобнее. Просто нужно стараться использовать новые фичи.
staticlab
27.11.2019 17:54+4А как бы выглядело развитие веба со статически типизированным языком, который не позволяет делать полифиллы? Кажется, IE затормозил бы тогда развитие экосистемы ещё сильнее.
Free_ze
27.11.2019 18:12-1По-человечески — наследованием и внедрением зависимостей. Без манкипатчинга.
Или по гадкому пути — через обертки, на манер jQ.staticlab
27.11.2019 18:24То есть разработчики альтернативного браузера должны были бы сделать класс Array2 extends Array, чтобы добавить в него новый метод flatMap()?
Понял, что описал не тот случай. Однако не могу придумать варианта, как использовать в коде метод из новой версии API, сохранив обратную совместимость, например в Java. Разве что использовать для новых методов какие-то внешние библиотеки со статическими методами, как Apache Collections (т.е. вызывать, например,
Arrays.flatMap(array, ...)
вместоarray.flatMap(...)
).Free_ze
27.11.2019 19:11Я понял вашу мысль. Да, просто DI здесь не поможет.
Можно было бы положиться, например, на методы-расширения из C#, но это тоже будет своего рода манкипатчинг. Но типобезопасно.staticlab
27.11.2019 19:18Если в новой версии рантайма в расширяемом классе появится метод с такой же сигнатурой, произойдёт ошибка?
Да, просто DI здесь не поможет.
Кстати, возможно, и мог бы помочь, но только если бы DI был на уровне платформы и работал прозрачно абсолютно для всех классов, включая внешние библиотеки. Правда здесь тогда были бы возможны злоупотребления, как в Ruby (где авторы Rails сильно расширили стандартные методы, отчего многие новые библиотеки стали привязаны к ActiveSupport).
Karl_Marx
27.11.2019 21:01+1Не согласен с автором оригинала. Если веб-стандарты ограничивают разработчика использованием только одного языка, каким бы он ни был хорошим или плохим, это означает, что веб уже сломан. Таких ограничений нет нигде, хочешь писать для серверов на Linux — вот тебе куча языков на любой вкус, включая тот же JavaScript, собираешься писать под Windows — пожалуйста, на Android — вот тебе C++, Java, Kotlin.
То, что в результате имитации бурной деятельности на протяжении десятков лет W3C предлагает разработчикам взять JavaScript и заткнуться, означает, что это не стандарты, а куча дерьма.JustDont
27.11.2019 23:50+3Если веб-стандарты ограничивают разработчика использованием только одного языка, каким бы он ни был хорошим или плохим, это означает, что веб уже сломан.
Вы всегда можете написать свой браузер. Или вообще отдавать через http-запрос скомпилированный бинарник для выполнения на клиентской машине уже чего угодно и как угодно. Дерзайте. Мир ждёт новых покорителей веба.Karl_Marx
28.11.2019 01:34+2Проблема в том, что это не будет поддерживаться никем, кроме написавшего, а W3C не предоставляет стандартов для того, чтобы я, Mozilla, Google, Apple или Facebook занимались подобными вещами и эти вещи были бы одинаково безопасны и совместимы друг с другом. Понимаете, о чем речь? По сути, WebAssembly это первая попытка сделать нечто подобное, и то, она была с трудом продавлена корпорациями в то время как престарелые бюрократы сидели, плевали в потолок и годами игнорировали тот факт, что современный веб уже давно не про документы и анимированные баннеры, а про веб приложения.
JustDont
28.11.2019 09:29W3C не предоставляет стандартов
А, ну всё понятно, наконец-то виноватый найден. Вот из-за кого никто не может свой любимый C компилировать сразу в веб.
По сути, WebAssembly это первая попытка сделать нечто подобное
Мне кажется, вы не вполне понимаете, зачем добавили wasm. Подсказка: нет, не для того, чтоб любимый C можно было сразу в веб компилировать. Языки и wasm вообще не причём, так, не более, чем любопытный дополнительный эффект, от которого у многих зачем-то повышенное слюноотделение случилось.
vanxant
28.11.2019 01:17+3Если веб-стандарты ограничивают разработчика использованием только одного языка
Давайте сначала дождёмся того прекрасного момента, когда такие мелкие конторки как МС и яблоко осилят имплементацию хотя бы одного языка согласно веб-стандарту.
vladkorotnev
28.11.2019 04:01новые возможности никогда не должны «ломать» уже существующие веб-сайты.
То-то у меня развалилась самодельная браузерка, использующая кучу видео и звука в том числе на заставке, из-за того, что в один день стало нельзя их использовать не по вызову пользователя (клик или пр.)
Clasen01
28.11.2019 04:45Когда читаю статьи про Rust, то в комментариях тоже постоянно натыкаюсь на локальные противостояния «C++ лучше Rust», «С++ не нужен, Rust всему голова». /sarcasm:on Ребята, а как же «каждой задаче свой инструмент? Мы же все здесь профессионалы, к чему ругань? /sarcasm:off :)
slonopotamus
28.11.2019 10:17каждой задаче свой инструмент
Ну во-первых, множество языков позиционируют себя как general-purpose programming language.
Во-вторых, невозможность создать язык который строго лучше чем уже существующий, и при этом решающий бОльший спектр задач, нуждается в доказательстве. Причём тут ещё скользкий момент с тем что значит "лучше".
TargetSan
28.11.2019 21:54Ну вот я например сегодня продолбался с unicode command line parameters потому что винда не умеет юникод как однобайтовую кодировку без 1000 приседаний, а комитет на кодировки положил с прибором, к примеру депрекейтнув wstring_convert и не предоставив альтернативу. И таких косяков родом из времён чуть ли не мейнфреймов навалом. И фиксить тх никто не желает с мантрой "Святая Совместимость!!11одинодин".
Накипело.
ttas
28.11.2019 09:09В ES5 появился
'use strict'
. Разве нельзя использовать что-то подобное для указания версии без обратной совместимости? Разве не лукавит автор, сообщая, что возможно только добавление?JustDont
28.11.2019 09:35Да, разработчики браузеров так и горят желанием добавить еще один движок рядом с имеющимися, на этот раз для выполнения некоего «next-gen JS».
justboris
28.11.2019 11:01В теории можно, Google пробовал добавить нативную поддержку Dart в браузеры. Но что-то пошло не так, и проект отменился. Было бы здорово, если бы кто-то в теме рассказал бы, в чем там были причины
Neikist
28.11.2019 11:08Наверно в том что другие браузеры не поддержали, а без этого смысла не было, разработчики бы не использовали. Ну и в те времена dart не сильно от js отличался. Тоже интерпретируемый, тоже динамическая типизация…
JustDont
28.11.2019 11:20+1В том, что никому не впёрлось работать на хотелки гугла. Это в первую очередь. Во вторую — всё те же самые вопросы, которые поднимаются при попытке добавить любой «некст-ген» движок:
1) Кому это нужно?
2) Как это будет совместимо с имеющимся вебом?
3) Какие это решает проблемы, которые не могут быть решены менее трудоёмкими (читай: менее дорогими для разработчиков браузеров) способами?
vanxant
28.11.2019 11:54… а зачем? Основные баги дизайна и ранних имплементаций как раз use strict и пофиксил.
Современный JS на самом деле классный. Для своей конкретной ниши по крайней мере.
Кому не хватает статической типизации в компайл тайме — для них есть тупоскрипт.
Ноют в основном люди из «махрового ынтырпрайза», которые привыкли для каждой кнопки делать свой класс с геттерами и сеттерами и с одной строчкой полезного кода. JS позволяет просто написать эту одну строчку и пойти дальше.
i360u
28.11.2019 09:43В экосистеме javaScript существует достаточно средств для того, чтобы «не стрелять себе в ногу», это и статический анализ с аннотацией типов, и проверки типов в рантайме. Современный синтаксис позволяет писать красивый и эффективный код. Современные средства разработки позволяют делать это с необходимым удобством. Этого вполне достаточно для полноценной промышленной разработки, даже БЕЗ использования TypeScript транспайла. JavaScript это поразительно гибкий, выразительный и мощный язык. Но нужно понимать, что JS- это, в первую очередь, СКРИПТОВОЙ язык, предназначенный для исполнения в весьма специфичной среде, и естественно, он имеет ряд отличий от системных языков и ряда прикладных. А любители прострелить себе колено найдут возможность для этого на абсолютно ЛЮБОМ языке, я гарантирую.
7abbix
28.11.2019 10:20-1Javascript нужно вообще отменить и даже запретить.
Потому что настолько корявый нечитабельный, вырвиглазный синтаксис, как у JavaScript, не только не воспринимается на чтение, в отличие от нормальных языков типа C#, Java (только по синтаксису), но и способствует размножению огромного количества багов.staticlab
28.11.2019 11:47+1Javascript нужно вообще отменить и даже запретить.
Вас в Госдуме покусали?
7abbix
28.11.2019 12:16-2Я против незаконной госдумы, представляющей только видимость деятельности парламента, а никак не функциональный орган власти.
А по поводу JavaScript:
Язык, который изначально создан с ошибками в дизайне, а именно он не читабельный и не фул пруф, хотя используется в той среде, где это необходимо. Нужно было понимать изначально, что сайты клепают все подряд и кое как, а потом читают и копируют примеры из такого кода, синтаксис которого не интерпретируется мозгом без специального глубокого анализа, поэтому легко остаются незамеченными баги.staticlab
28.11.2019 12:51синтаксис которого не интерпретируется мозгом без специального глубокого анализа, поэтому легко остаются незамеченными баги
В этом отношении джаваскрипту далеко до C++, в котором намного больше неочевидных нюансов поведения кода, 19 способов инициализации переменных, undefined behavior — то, что подстерегает программиста на каждом шагу, а авторы PVSStudio зарабатывают деньги на инструменте, находящем ошибки в коде, в котором мозг никаких проблем не замечает. И при этом именно на нём пишутся браузеры. Давайте его запретим, потому что кому-то он по этим причинам не нравится.
7abbix
28.11.2019 13:37Вот тут согласен. С++ не только экстримально сложен для написания безопасного кода, но и еще позволяет легко убить систему при малейшей ошибке и так же с синтаксисом всё плохо.
FanatPHP
28.11.2019 10:34Огромное спасибо за нормальный русский язык.
Ваша работа выгодно отличается от традиционного качества переводов на Хабре, когда переводить берутся исходя из принципа "достаточно примерно понимать, что написано на английском и можно совсем не знать русский".
vasyapivo
Стоит, JS — язык написанный не для того, чтобы мы сейчас на нём писали огромные SPA. JS это куча хаков и обратной совместимости. Потому новый язык нужен хотя бы, чтобы убрать проблемы с приведением типов или прототипное наследование, которое создаёт проблем больше чем решает. JS не должен был быть индустриальным стандартом для вёба, то что он им стал — это роковое стечение обстоятельств.
Людям нужны не языки ради языков, скорость и эффетивность разработки. Потому люди не просто ругают C++ и пишут на нём. Они ругают C++ и уходят на Go чтобы легче и быстрее решать свои проблемы.
По мне, так строгая типизация для больших приложений просто необходима, нам нужны элементы нормального ООП с инкапсуляцией и наследованием. Нужен синтаксический сахар и большая стандартная библиотека. По-факту, нам нужен Kotlin для web, и думаю, скоро его допилят.
0xd34df00d
Не все. Не во всех задачах можно просто взять и уйти на go/rust/haskell, увы.
В конце концов, наличие у языка проблем не означает, что другие языки подойдут лучше.
endymion
vasyapivo и пишет, что нужны не языки ради языков, а языки, которые решают определенные проблемы.
zim32
Ну так придумали уже такой язык, тайпскрипт называется. Рассматривайте джаваскрипт как ассемблер для веба. Завэчем его трогать.
nsinreal
У тайпскрипта в корне лежат те же проблемы, что и у джаваскрипта, потому что он старается быть максимально "джаваскриптом с типамии".
tonad
Что бы браузер перестал потреблять ресурсы как ААА игры?
JustDont
А вы готовы на то, чтоб сайты писались столько же времени, сколько и ААА игры?
Neikist
Сайты бы не писались столько же времени даже если бы использовались те же инструменты. В играх на порядки больше контента и на порядки больше логики с вычислениями.
JustDont
Да что вы говорите. Я в младые годы пилил интерфейсы даже не на С++, а на вполне себе прилизанной и ходящей строем яве. И видел, как их пилили убеленные сединами люди с офигенным опытом (не чета зеленому мне). И то, и другое было мягко говоря небыстрым.
Единственное, что выдерживает сравнение по скорости на простых случаях, это Delphi. Но более масштабные или сложные случаи в вебе всё равно масштабируются куда быстрее.
Но я даже не об этом писал, а о том, что неэффективное использование вычислительных ресурсов возникает в первую очередь от перехода между разными уровнями абстракций. Высокоуровневый DSL для хороших и быстрых описаний интерфейсов и презентаций будет заведомо менее производительным, чем низкоуровневый язык «близкий к процессору».
Neikist
Флаттер говорит вам что можно было сделать и нормально. И разрабатывать быстро интерфейсы, и разрабатывать быстрые интерфейсы.
JustDont
Как только гугльаппс (или что-то отдаленно сравнимое по сложности) будут написаны на флаттере — я вам прям сразу же поверю.
Я видел этот ваш флаттер, и идеологически это шаг вот прямо в те времена, когда swing был модным и очень молодёжным. Как эпически выразился один товарищ в комментах к другой статье — «флаттер предлагает революционный подход в виде императивного написания интерфейсов». А мужики-то и не знали, что единственный способ закодить интерфейс в конце 90-х хипстеры из 2020 будут называть «революционным».
У меня и в браузере ничего мягко говоря не тормозит.
Neikist
Эмм… Что это за статья такая странная? Вообще флаттер как раз декларативный подход предлагает. В этом плане он у реакта многое слизал насколько знаю.
JustDont
Где? Даже титульный пример на flutter.dev написан на жуткой смеси функциональщины с попытками изобрести свой собственный html с блекджеком и танцами.
Это, разумеется, не тот императивный подход, который был в 90-е, но и совсем не декларативщина.
А с каких пор реакт декларативен? «Есть шаблончики» != «декларативен». Шаблончики конечно декларативны, сами по себе если. А вот декларативно ли оно будет всё в целом — зависит от того, сколько можно и сколько нельзя сделать одними шаблонами.
Neikist
Я все таки придерживаюсь другого мнения на этот счет, но лучше нам закончить. Во первых это уже совсем далеко от темы статьи уходит, во вторых мы вряд ли друг друга переубедим.
vintage
Почему вы считаете Реакт сколь-нибудь декларативным?
Neikist
Про реакт я без понятия, я его в глаза ни разу не видел. Я считаю декларативным флаттер, и он многое взял у реакта.
И да, во флаттере в ui можно применять циклы, условия и прочее, но дерево виджетов строится на основе состояния, которое меняется только строго определенным образом. Мне этого хватает чтобы флаттер считать декларативным UI фреймворком. То что состояние может и меняется кучей разных способов — это уже другое.
vintage
https://ru.wikipedia.org/wiki/%D0%94%D0%B5%D0%BA%D0%BB%D0%B0%D1%80%D0%B0%D1%82%D0%B8%D0%B2%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5
Neikist
Я просто разделяю декларативное программирование и декларативное описание UI. Сам дарт императивный, но описание UI на флаттере считаю декларативным.
vintage
Я может не на тот флаттер смотрю, но где тут декларативность?
Neikist
Функция build в стейтлесс виджетах или стейте стейтфул виджетов. Именно она и описывает UI. Все остальное бизнес логика, и она уже не декларативная само собой.
vintage
Вы похоже выдаёте желаемое за действительное. Посмотрите ещё раз код внимательно.
tonad
Это быстрее чем сейчас? Конечно готов…
zim32
Конечно в том что браузеры столько жрут виноват джаваскрипт, а не устаревший сложный dom, куча рекламы ифрейм в ифрейме в ифрейме, куча говнокода и зависимостей из npm. Нет это.все джаваскрипт.
codemafia
И начинают ругать Go за проблемы работы с памятью и т.п.
SerVB
Kotlin/JS стабилен давно, ждать не надо) Использовать приятно.