Comments 58
Если вы знаете ответ, пишите в комментариях.
В первую очередь потому, что JS был слеплен на коленке в кратчайшие сроки. А потом, естественно, стала мешать обратная совместимость.
Да, есть TypeScript, который вроде как является типизированным, но в итоге он же будет переведен все в тот же JS.
Вас как явиста не смущает, что ваш прекрасный ява-код со строгой типизацией сначала станет байт-кодом, где типизация всё еще останется, но уже без особого контроля, а затем и вообще будет в рантайме машинным кодом? Нет? Ну а откуда тогда к TS претензии?
Здесь скорее попытка разобраться
В первую очередь потому, что JS был слеплен на коленке в кратчайшие сроки. А потом, естественно, стала мешать обратная совместимость.
Напомнило ситуацию с Basic. Там тоже было много нелогичного, из-за расширений стандарта, прикрученых изолентой. В детстве мечтал изменить язык, но не было знаний и инструментов. Позже увидел в Python реализоваными те свои представления о «правильном бейсике».
А вообще, мне кажется, если знаешь хотя бы поверхностно несколько языков, все эти странности не удивляют.
Только вот в Java всё же есть рантаймовые проверки типов
Какие? Бросить исключение при касте? Очень полезно.
а в TS их нет вообще
Ознакомьтесь с Typescript type guards. Есть. Только разве что чуть более многословны, так как естественно информации о типе в рантайме нет, и приведение нужно делать по принципу «крякает как утка — значит утка».
TS не кинет исключение, ничего не сообщит, если в рантайме прилетят данные совершенно другого типа, а это случиьтся может вообще без проблем.Если грамотно использовать TS и соблюдать согласованной контракта общения с источниками внешних данных, то рантайме проверки не нужны. Более того рантайм проверки вреды и противореччат концепции TypeScript, который не существуют в рантайме by design и это неплохо. Если и делать где-то рантайм проверки, то при поступлении внешних данных источник которых не поддается контролю (JSON.parse).
Это не так, с чего бы преобразовывать к string, внезапно?
document.write(typeof numbers[0]);
Выведет number
Код автора на тему «в массивах одни лишь стринги !!!1!!» надо, разумеется, писать так:
document.write("Type elements in mix: ");
for (key in mix) {
document.write(typeof mix[key] + " ");
}
И сразу наступят чудеса.
var numbers = [1,2,3,4,5];
var sum = numbers[0] + numbers[1];
document.write("<br /> sum numbers = " + sum);
то получим 3.
А если так
var numbers = [1,2,3,4,5];
document.write("<br /> sum numbers = " + numbers[0] + numbers[1]);
то будет 12. Это связано с тем, что операция "+" сначала преобразует numbers[0] в string? И если написать так:
document.write("<br /> sum numbers = " + (numbers[0] + numbers[1]));
тогда будет 3
1) Делаем string + number. Итог — string.
2) Делаем string (c №1) + number. Итог — string.
Итого две операции конкатенации со строкой.
sum numbers = " + numbers[0] + numbers[1]Оператор + работает как конкатенация, если хотя бы один операнд строковый, и как числовое сложение в обратном случае. Ну и вычисляется слева направо
Нет :) JS сначала проходит по коду и собирает в память все переменные и функции, а потом уже начинает наполнять переменные и вызывать ф-и. Порядок написания не важен. А IE3-5 и прочих динозавров сейчас мало кто поддерживает.
Кстати, почему решили взять ES5, а не последние версии, где и классы и BigInt есть?
А про зону видимости переменных/ функций/ методов — это фича. Это может появиться ниже, или при следующем тике, но сейчас этого нет. TS предварительно смотрит весь код, и подхватывает объявления, которые могут быть и несколькими строками ниже, и сверит типы.
В этом плане Java более похожа на C/C++, но это просто правила игры в каждом из ЯП.
{ [key: string]: string }
Record<string> читается и пишется веселее.
Проблемы слабой (я бы сказал даже broken by design) типизации TS не решает и никак решить не может (т. к. является надмножеством JS).
То есть проблемы (или фичи, если угодно) того, что [1] + 2 === «12» или ToBoolean([]) === true никуда не денутся (как и многие другие).
Аналогично со сравнением на равенство. Разделение === на отдельные equality и identity TS не даст, как и возможности нормально сравнивать объекты (массивы).
Точно так же, с отсутствием целочисленных/decimal чисел, перегрузки операторов и многое, многое другое, увы.
Я на Java никогда не писал, но знаю C++. По строгости типизации его сложно переплюнуть, по-моему. И говорить, что нет глубокого сравнения двух объектов «из коробки» — ну, в C++ его нет, и в JS тоже. Для первого — перезагружай оператор сравнения, для второго — подключай lodash.
Nobody's perfect.
По строгости типизации его сложно переплюнуть, по-моему.Вообще C++ справедливо считается «ярким примером» языка со слабой типизацией. :)
нет глубокого сравнения двух объектов «из коробки» — ну, в C++ его нет, и в JS тожеНе очень корректное сравнение — C++ низкоуровневый язык с zero-cost abstractions как ключевая концепция.
Сравните лучше с языками примерно того же класса — тем же Python (да и в Java, если я ничего не путаю, это тоже успешно реализовано).
let n: number;
n = [1] + 1;
console.log(n);
TS2365: Operator '+' cannot be applied to types 'number[]' and '1'.
ЧЯДНТ?
А вообще это проблема не typescript-a (да, я согласен что есть проблемные места подобные указанным), это проблемы тайпингов, так вот — их можно подправить, сделать строже, это не сильно сложно.
ЧЯДНТ?Всё так, это мой косяк.
TypeScript пропускает сложение чисел и строк, разрешая неявное приведение типов между ними (и это меня слегка раздражает).
Во всех остальных случаях TS ругается, да. Честно говоря, логику такого решения я совсем не понимаю — это и не строгая типизация, и не надмножество JS.
это проблемы тайпингов, так вот — их можно подправитьЯ либо не согласен, либо не понял. :) Можете развернуть мысль?
Похоже у Вас либо версия несвежая либо в настройках послабления, я на прошлой неделе в своем коде втыкал parseInt что бы обойти ругательства typescript. UPD прочитал пост serf и вспомнил что у меня еще линтер подключен, вполне возможно что он ругался, да.
>Я либо не согласен, либо не понял. :) Можете развернуть мысль?
Все поведение js для typescript компайлера описано в тайпингах функций js, сам typescript чекер достаточно тупенький. За операторы не уверен (точнее почти уверен что нет), а вот вывод типов функций и методов встроенных объектов точно можно править. Я правил для reduce — он на какой то версии криво выводил типы (в моем кейсе по моему вообще не учитывался тип функции-аргумента). Загляните в node_modules/typescript/lib, там сразу видны тайпинги с которыми ts работает.
либо версия несвежая либо в настройках послабленияНет, это именно штатное поведение. Проверял на tsc версии 3.3.3333 с флагом --strict. (Хотя смутно припоминаю, что оно так работает очень давно.)
Опять же, линтеры это здорово, но слегка отдельная история.
Все поведение js для typescript компайлера описано в тайпингах функций js, сам typescript чекер достаточно тупенький. За операторы не уверен (точнее почти уверен что нет), а вот вывод типов функций и методов встроенных объектов точно можно править.А, ну это-то я знаю, да. Даже заглядывать никуда особо не надо, IDE (да и тот же VS Code) сами умеют перекидывать на нужный тайпинг.
А сложение строки с числом — это преобразование number -> string
JavaScript — это интерпретируемый, скриптовый язык для написания сценариев.Современные JS-движки, как правило, используют JIT-компиляцию (т. е. JS-код на лету компилируется сразу в машинные инструкции).
Редкое исключение — V8, он использует компиляцию в байт-код с последующей интерпретацией; но и он использует компилятор для оптимизирующей компиляции горячих участков (это тоже общая практика в JS-движках).
В JS есть тип Object. Если в Java это суперкласс всех классов, то в JS это просто один из типов.В JS это тоже суперкласс всех классов. Все встроенные и пользовательские классы автоматически наследуются от Object.
Хотя для пользовательских классов это при желании можно обойти.
Когда же дело касается JS и его слабой типизации, то в дело вступает настоящая анархия. В массив можно складывать что угодно, элементы любых типов,А ещё в массиве могут быть «пропасти»:
let a = new Array(5); // 5 указывает длину; не делайте так!
a.length; // => 5
a[0]; // undefined
'1' in a; // false
a.forEach(value => console.log(value)); // ничего не выведет
Советую подробнее почитать про устройство массивов в JS, там много интересного и неожиданного (спойлер: они просто объекты со свойствами, которые являются валидным строковым представлением целых чисел, и пачкой методов в классе Array).2. Для java программиста может показаться глотком свежего воздуха разработка на js хотя бы из-за наличия шикарных инструментов разработчика и самого процесса разработки. Сравнить хотя бы старт и перестарт проекта на spring и koa например. Я уж молчу про меньшую академичность кода и практически отсутствующий бойлерплейт код.
3. js отнимает у java всё больше пространства, развивается быстрее и занимает всё больше ниш. Вот и в десктор ворвался, размахивая хромиумом.
Это очень неплохой гайд про особенности JS, там перечисленны спорные и неочевидные моменты, которые часто вызывают трудности и непонимание.
Если первый в 2019 году выглядит как нереально гипертрофированный… мамонт, который даже начинать изучать просто страшно, да и, по сути своей, бессмысленно.
То вторые, приходя в JS, последний откровенно загаживают.
В JS есть много прикольного и интересного, но бывшие жаба/си-шарп-проггеры ничего этого не хотят — они ведь круутыыые, они ведь не какие-то там js-разрабы, а потому, они хотят кодить на JS аки на своих языках… со всеми типо_типизациями_которые_разумеется_решают_все_проблемы итд.
Это приводит к порождению гор едва читаемого кода, который тупит почти на всех устройствах.
Статическая типизация в принципе не спасает от ошибок.
Горы лабораторных работ студентов на Си и «плюсах» тому яркое подтверждение.
Если жаба такая крутая, то почему джава-программист «смотрит» на JS?
Ведь, «в теории» должно быть ровно наоборот…
И как, по вашему — эти приколы облегчают или затрудняют сопровождение программ, написанных другими программистами?
В Си — одна из наиболее слабых систем типов. Rust или Haskell в этом плане более выразительны. (Например, их системы типов позволяют избежать null pointer error).
Лично я не сторонник слабой типизации, но мой коллега, недавно попробовавший JavaScript, почему-то был в восторге от нее. Возможно, это дело вкуса. А как считаете вы, что лучше слабая или сильная типизация?
С технологической точки зрения «лучше» конечно же формально верифицированная зависимыми типами программа с понятной человеку спецификацией. Но в реальном мире на получение доказательства корректности «правильного квиксорта» у меня уйдёт пара дней.
Каждая из статической/динамической сильной/слабой типизаций даёт свои профиты и даёт языкам свои ниши.
Люди часто наезжают на JavaScript и понятно, за что, он не идеален. Мне нравится статическая типизация. Во-первых чтобы что-то написать, нужно продумать типы, что даёт половину решения и «места, куда писать код». Во-вторых при достаточно хороших типизациях написанный код «просто работает», иногда даже с первого раза. Но чем больше разбираешься с системами типов, тем больше хочется описать, что не всегда возможно. В итоге ушёл в JavaScript, который никогда не мешает и не требуется ничего доказывать компилятору.
Но чем больше разбираешься с системами типов, тем больше хочется описать, что не всегда возможно.
Когда нужно написать какой-нибудь write once код, делающий что-то мелкое, но интересное со сложными структурами данных — статическая типизация требует то, что можно с полным правом назвать «бойлерплейтом»: да, всё опишешь, но это особо никому не пригодится. Идея, например, написать писать на тайпскрипте скрипт настройки dev-сервера у меня восторга не вызывает даже в теории — доказывать тайпскрипту, что у меня тут типы все как надо сходятся — будет на редкость бессмысленным занятием.
А вот когда пишешь что-то сложное, большое, и поддерживаемое разными людьми — статическая типизация спасает от огромного количества головной боли буквально во всём.
Вот знаете, вроде и обидеть не хочется, но и приятного после прочтения тоже мало чего рождается. Зачем нам эти мысли вслух? Зачем вы начинаете копаться в языке не прочитав ничего по нему? Ведь вы даже азов не выучили. Просто представьте если бы кто-то сравнивал Норвежский язык и Русский — но без словарей, без этимологии итд, просто так. Смотрите — здесь слово похоже, но значит оно совсем другое — как так? Есть спецификация, либо читаете ее и вопросов больше не рождается, либо хотя бы каких-нибудь Илью Кантора, Акселя Раушмайера, Дмитрия Сошникова, Кайла Симпсона, Дугласа Крокфорда… Материалов в нашу JS-эру пруд пруди. Нет, надо взяться, наковырять на авось какой-то несуразицы. Так ладно бы вы это в файлик на рабочем столе сохранили и вернулись к нему со здравыми мыслями когда лень уйдет и появится желание читать мануалы/спеку. Так нет, надо накатать на Хабр, ведь это же бложек куда грех не написать. :(
Вот не хочется бомбить, но прямо читать такое больно.
Получается, что вы имеете возможность узнать об ошибке еще до запуска приложения. В JS, в силу отсутствия компилятора, такой проверки нет. И ошибки, допущенные вами в момент написания кода будут обнаружены только после запуска скрипта.
IDE со встроенными инструментами анализа синтаксиса, линтеры… Не — не слышали.
Писать JS-код в блокноте (без всех плюшек IDE) — ну такое…
Возможно, это дело вкуса. А как считаете вы, что лучше слабая или сильная типизация?Что лучше — шурупы или гвозди? Это дело не вкуса, а задачи.
Java и JavaScript — это не одно и тоже!Многие работники сферы HR с вами не согласились бы.
Возможно, это дело вкуса. А как считаете вы, что лучше слабая или сильная типизация?Зависит от проекта. Если проект не одноразовый и сложнее todo app, то TypeScript конечно стоит выбирать изначально и сразу в strict режиме. С ростом проекта и команды преимущества будут ощущаться все сильнее в отличии от JS когда с ростом будут увеличиваться только проблемы.
Но, в JS это нормально, потому что понятия класса, функции, методов класса размыты. Слабая типизация во всем.
до "ECMAScript 2015" в нем нет классов, там наследование основано на прототипах.
функция "Person" является объектом-конструктором, а
new Person("Igor", 26);
создаст объект-экземпляр.
Динамическая природа JS проявится в том, что можно на-ходу добавлять поля/методы к прототипу объекта-конструкора и они становтся доступы у всех объектов-экземпляров.
К "классовом" языке свойства и методы класса динамически менять не получится.
Первый взгляд на JavaScript глазами Java — разработчика