Java и JavaScript — это не одно и тоже! Теперь вы знаете главную тайну масонов. В этой статье я хочу поделиться с вами мыслями и соображениями о языке JavaScript через глаза Java — разработчика. Проведу сравнение структур данных, типов, функций, объектов, классов и других общих возможностей языков Java и JavaScript.

Фундамент


JavaScript — это интерпретируемый, скриптовый язык для написания сценариев.  Это значит, что тот код, который вы напишите, будет выполняться построчно, от инструкции в инструкции, от скрипта к скрипту. Java — язык компилируемый, это значит, что перед стартом программы на Java, компилятор должен перевести весь код, написанный вами, в специальный машинный код, понятный для JVM - bytecode.

Неудобства для Java-разработчика, начавшего писать на JS, связанные с этими отличиями будут следующие:

  • Перед запуском компиляции вашего кода, написанного на Java, компилятор проведет за вас синтаксический и семантический анализ, и в случае проблем — оповестит вас об этом. Получается, что вы имеете возможность узнать об ошибке еще до запуска приложения. В JS, в силу отсутствия компилятора, такой проверки нет. И ошибки, допущенные вами в момент написания кода будут обнаружены только после запуска скрипта.
  • Следующее неудобство возможно только для версии JS до ES5. Т.к. JavaScript выполняется построчно стиль написания функций, вызывающие другие функции, будет отличаться от принципов Чистого кода «дядюшки» Боба, проповедуемого для написания программ на Java. В JS, если из функции foo() необходимо вызвать функцию bar(), вы должны определить bar() до foo(). Если сделать наоборот, как в Java — приложениях, то вызов может закончится неудачно в некоторых старых браузерах.

// Пример на Java
public class JavaVsJS {

    public static void foo(String name) {
        bar(name);
    }

    private static void bar(String name) {
        System.out.println(name);
    }

    public static void main(String[] args) {
        JavaVsJS.foo("Igor Ivanovich");
    }
}

// Пример на JavaScript
var name = "Igor Ivanovich";

// Функция bar() определена до своего вызова в foo()
function bar(name) {
    document.write(name);
}

function foo(name) {
    bar(name);
}

foo(name);

Переменные и их типы


JavaScript — слабо типизированный язык, в отличии от Java. С одной стороны, это дает больше гибкости, с другой — больше возможностей совершить выстрел в ногу. Для объявления переменной в JS достаточно использовать ключевое слово var, после которого указать имя переменной и, если необходимо, значение. На практике же необязательно даже использовать ключевое слово var.

var name_1 = "Igor Ivanovich";
name_2 = "Renat Raphaelevich";

Теперь о типах. В JS для целочисленных и чисел с плавающей точкой нет разных типов. Они объединены в типе number.String, boolean такие же как и в Java. В JS есть тип Object. Если в Java это суперкласс всех классов, то в JS это просто один из типов.

var a_number = 10;     // number    
var b_number = 10.01;  // number

var a_string = "10";   // string
var b_string = "10.1"; // string

var tr = true; //boolean

var person = {name: "Igor", secondName: "Ivanovich"}; //object

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

10 +1
> 11
10 +"1"
> "101"
true && false
> false
true && 1
> 1
true && 0
> 0
true && "1"
> "1"
false && "1"
> false
false && 0
> false
0.1 + 0.7
> 0.7999999999999999

Некоторые результаты могут немного смутить Java-разработчика. Например, возможность использовать тип boolean таким образом: true && 1 и при этом получать какой-то результат. В Java невозможно провести такую операцию т.к. компилятор выдаст ошибку о том, что нельзя использовать оператор && с типами не boolean.  Теперь обратим внимание на еще одно отличие JS и Java: операторы === и !==. Это операции сравнения, необходимые слабо типизированному языку, такому как JS.  === — вернет true, если сравниваемые объекты равны по значению и их типы совпадают. !==, соответственно, вернет true, если сравниваемые объекты не равны по значению или их типы не совпадают. Рассмотрим несколько примеров:

10 == 10
> true
10 == "10"
> true
10 === "10"
> false
10 != "10"
> false
10 !== "10"
> true
10 !== 10
> false

Функции


В JS, так же как и в Java, функции могут возвращать/не возвращать значение, быть с аргументами и без. Вызвать функцию можно как в коде JS, как было показано в примере выше, так и реакцией на определенное событие на элементе html-разметки.

<!-- Вызов функции на элементе по событию клика на кнопку -->
<input type="button" value="CLICK" onclick="foo();">

//Описание функции foo()
function foo() {
    document.write("Calling foo");
}

При нажатии на кнопку на странице будет напечатано «Calling foo» как результат вызова функции. Теперь о странностях на которые может обратить внимания Java-разработчик. Вернемся к примеру выше, где функция foo() вызывает в себе функцию bar() — которая используется только как внутренняя функция. По идеи мы ожидаем того, что ее можно сделать приватной. Но в JS нет никаких селекторов доступа. Нет возможности сделать поле private простым добавлением этого слова перед объявлением функции. Пойдем дальше. Создадим объект — экземпляр класса со своими полями и одним методом.

function getLocation() {
    if (this.person === "Igor" && this.age > 25) {
        document.write("Your name " + this.person + ", location = Vishnevaia 1");
    } else {
        document.write("Your name " + this.person + ", location = rp Sokoloviy");
    }
}

function Person(person, age) {
    this.person = person;
    this.age = age;
    this.getLocation = getLocation;
}

var igor = new Person("Igor", 26);

igor.getLocation();
document.write("<br />");
getLocation();

Если смотреть на этот код глазами Java-разработчика, то можно отметить,  что функция Person — является конструктором объектов класса Person и определением полей, и методов, входящих в класс. Функция getLocation() является функцией класса Person. Внутри нее мы используем обращение к полям экземпляра класса this.person и this.age. Логично, что эта функция, использующая текущей экземпляр класса Person, должна работать только с ним и последний вызов функции getLocation() не должен работать. Но, в JS это нормально, потому что понятия класса, функции, методов класса размыты. Слабая типизация во всем. Выполнив этот скрипт вы получите следующий вывод в окне браузера:

Your name Igor, location = Vishnevaia 1
Your name undefined, location = rp Sokoloviy

Однако, переписав код следующим образом, определив функцию внутри класса, ее вызов не для экземпляра класса будет недоступен:

function Person(person, age) {
    this.person = person;
    this.age = age;
    this.getLocation = function () {
        if (this.person === "Igor" && this.age > 25) {
           document.write("Your name " + this.person + ", location = Vishnevaia 1");
        } else {
           document.write("Your name " + this.person + ", location = rp Sokoloviy");
        }
    };
}

var igor = new Person("Igor", 26);

igor.getLocation();
document.write("<br />");
getLocation();

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

Массивы


Когда мы говорим о массивах, то представляем структуру данных, хранящую однотипные элементы, доступ к которым осуществляется по индексу. Это в Java. Когда же дело касается JS и его слабой типизации, то в дело вступает настоящая анархия. В следующим примере мы создаем 4 массива. В первом элементы разных типов, во втором только числа, в третьем boolean, в четвертом boolean и number:

var mix = [3, "Igor Ivanovich", "Renat Raphaelevich", "Sergey Sergeevich", 1, 12.3, true];

var numbers = [1,2,3,4,5];

var booleans = [false, false, true];

var mix2 = [false, 1, 2];

document.write("Type elements in mix: ");
for (element in mix) {
    document.write(typeof mix[element] + " ");
}
document.write("<br /> Type elements in numbers: ");
for (element in numbers) {
    document.write(typeof numbers[element] + " ");
}
document.write("<br /> Type elements in booleans: ");
for (element in booleans) {
    document.write(typeof booleans[element] + " ");
}
document.write("<br /> Type elements in mix2: ");
for (element in mix2) {
    document.write(typeof mix2[element] + " ");
}
var sum = numbers[0] + numbers[1];
document.write("<br /> sum numbers = " + sum);

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

Type elements in mix: number string string string number number boolean 
Type elements in numbers: number number number number number 
Type elements in booleans: boolean boolean boolean 
Type elements in mix2: boolean number number 
sum numbers = 12

Вывод


При первом касании с языком JavaScript у Java — разработчика могут возникнуть все вышеперечисленные замечания и вопросы. При моем первом знакомстве с JS я испытывал не самые веселые эмоции. Скорее это было вот так: «Что за ...?». Многие отличия и не понимания кроются в разнице типизаций двух языков. Я не знаю зачем JS нужна слабая типизация.

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

Да, есть TypeScript, который вроде как является типизированным, но в итоге он же будет переведен все в тот же JS. Лично я не сторонник слабой типизации, но мой коллега, недавно попробовавший JavaScript, почему-то был в восторге от нее. Возможно, это дело вкуса. А как считаете вы, что лучше слабая или сильная типизация?

Комментарии (56)


  1. JustDont
    03.03.2019 16:37
    +6

    Если вы знаете ответ, пишите в комментариях.

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

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

    Вас как явиста не смущает, что ваш прекрасный ява-код со строгой типизацией сначала станет байт-кодом, где типизация всё еще останется, но уже без особого контроля, а затем и вообще будет в рантайме машинным кодом? Нет? Ну а откуда тогда к TS претензии?


    1. nicholasgribanov Автор
      03.03.2019 16:50
      -1

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


    1. funca
      03.03.2019 17:26

      Общего у JavaScript и Java как у морской свинки и обычных свиней. JavaScript создавался под впечатлением от языков функционального программирования, таких как scheme. Ключевое в нем first-order functions и замыкания. А слово Java и С-подобный синтаксис появились по соображениям маркетинга.


    1. mactep3230
      03.03.2019 19:19

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

      Напомнило ситуацию с Basic. Там тоже было много нелогичного, из-за расширений стандарта, прикрученых изолентой. В детстве мечтал изменить язык, но не было знаний и инструментов. Позже увидел в Python реализоваными те свои представления о «правильном бейсике».
      А вообще, мне кажется, если знаешь хотя бы поверхностно несколько языков, все эти странности не удивляют.


    1. AxisPod
      04.03.2019 09:17

      Только вот в Java всё же есть рантаймовые проверки типов, а в TS их нет вообще и это может приводить к весёлым багам. Я бы даже сказал не «может», а приводит. TS не кинет исключение, ничего не сообщит, если в рантайме прилетят данные совершенно другого типа, а это случиьтся может вообще без проблем.


      1. JustDont
        04.03.2019 13:02

        Только вот в Java всё же есть рантаймовые проверки типов

        Какие? Бросить исключение при касте? Очень полезно.

        а в TS их нет вообще

        Ознакомьтесь с Typescript type guards. Есть. Только разве что чуть более многословны, так как естественно информации о типе в рантайме нет, и приведение нужно делать по принципу «крякает как утка — значит утка».


      1. gearbox
        04.03.2019 21:09

        Есть генераторы рантайм проверок на основе дефиниций (https://github.com/fabiandev/ts-runtime). swagger/raml/graphql тоже транслируются как в дефиниции так и в рантайм проверки. Большинство более менее зрелых технологий такой инструментарий предоставляют. Не хватает — компилятор typescript доступен, API открыто, можно сваять свой трансформер, это не сложно (https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API). Да, не из коробки. Но имхо, ожидать из коробки рантайм проверки от статичного анализатора — так себе хотелка.


      1. serf
        05.03.2019 09:11

        TS не кинет исключение, ничего не сообщит, если в рантайме прилетят данные совершенно другого типа, а это случиьтся может вообще без проблем.
        Если грамотно использовать TS и соблюдать согласованной контракта общения с источниками внешних данных, то рантайме проверки не нужны. Более того рантайм проверки вреды и противореччат концепции TypeScript, который не существуют в рантайме by design и это неплохо. Если и делать где-то рантайм проверки, то при поступлении внешних данных источник которых не поддается контролю (JSON.parse).


  1. dopusteam
    03.03.2019 16:37
    +4

    «В массив можно складывать что угодно, элементы любых типов, все они будут преобразованы в string»

    Это не так, с чего бы преобразовывать к string, внезапно?

    document.write(typeof numbers[0]);
    


    Выведет number


    1. JustDont
      03.03.2019 16:48
      +3

      Это потому что автор подумал, что for… in у него такой же как и в яве. А меж тем «такой же как и в яве» будет только лишь for… of.
      Код автора на тему «в массивах одни лишь стринги !!!1!!» надо, разумеется, писать так:

      document.write("Type elements in mix: ");
      for (key in mix) {
          document.write(typeof mix[key] + " ");
      }

      И сразу наступят чудеса.


      1. nicholasgribanov Автор
        03.03.2019 16:51
        -1

        Благодарю! Это конечно фейл)


        1. dopusteam
          03.03.2019 16:57

          Добро пожаловать в клуб)


          1. nicholasgribanov Автор
            03.03.2019 17:01

            Спасибо) Зато еще одно отличие в копилку: for in))


    1. nicholasgribanov Автор
      03.03.2019 17:05
      -1

      Тогда вопрос. Если вывести сумму таким образом:

      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. JustDont
        03.03.2019 17:08

        Читайте выражение так, как его разбирает парсер:
        1) Делаем string + number. Итог — string.
        2) Делаем string (c №1) + number. Итог — string.
        Итого две операции конкатенации со строкой.


      1. shaukote
        03.03.2019 17:08
        -1

        sum numbers = " + numbers[0] + numbers[1]
        Оператор + работает как конкатенация, если хотя бы один операнд строковый, и как числовое сложение в обратном случае. Ну и вычисляется слева направо


      1. khim
        03.03.2019 17:54

        Но ведь в Java сложение работает так же… а вы говорили, что знаете Java…


  1. valsaven
    03.03.2019 16:41
    +9

    «В JS, если из функция foo() необходимо вызвать функцию bar(), вы должны определить bar() до foo(). Если сделать наоборот, как в Java — приложениях, то вызов может закончится неудачно в некоторых старых браузерах.»
    Нет :) JS сначала проходит по коду и собирает в память все переменные и функции, а потом уже начинает наполнять переменные и вызывать ф-и. Порядок написания не важен. А IE3-5 и прочих динозавров сейчас мало кто поддерживает.

    Кстати, почему решили взять ES5, а не последние версии, где и классы и BigInt есть?


    1. CoolCmd
      03.03.2019 17:14
      +5

      по-моему даже в IE5 такого нет. у автора минимум знания JS и максимум фантазии.


  1. AndyPike
    03.03.2019 16:51

    Все «недостатки» (а для кого-то фичи — как к этому подходить) удобно и понятно решены в TypeScript. Да, он компилируется в JS, но проверка типов довольно строгая. И засунуть что-то произвольное в массив, объявленный как items!: Array<{ [key: string]: string }> TS не даст.

    А про зону видимости переменных/ функций/ методов — это фича. Это может появиться ниже, или при следующем тике, но сейчас этого нет. TS предварительно смотрит весь код, и подхватывает объявления, которые могут быть и несколькими строками ниже, и сверит типы.

    В этом плане Java более похожа на C/C++, но это просто правила игры в каждом из ЯП.


    1. JustDont
      03.03.2019 16:56

      { [key: string]: string }

      Record<string> читается и пишется веселее.


      1. serf
        05.03.2019 09:14

        Только там 2 аргумента.


        1. JustDont
          05.03.2019 10:26

          Да. И тем не менее, это то же самое, что и Record<string>.


          1. serf
            05.03.2019 10:30

            1. JustDont
              05.03.2019 10:43

              Вот жеж (к вопросу о «программировании на бумажке» из соседней статьи). Я почему-то до последнего был уверен, что один из параметров Record имеет какой-то дефолт.


    1. shaukote
      03.03.2019 17:04

      Ну, как бы хорош не был TS, про «все недостатки» это всё же преувеличение.

      Проблемы слабой (я бы сказал даже broken by design) типизации TS не решает и никак решить не может (т. к. является надмножеством JS).
      То есть проблемы (или фичи, если угодно) того, что [1] + 2 === «12» или ToBoolean([]) === true никуда не денутся (как и многие другие).
      Аналогично со сравнением на равенство. Разделение === на отдельные equality и identity TS не даст, как и возможности нормально сравнивать объекты (массивы).

      Точно так же, с отсутствием целочисленных/decimal чисел, перегрузки операторов и многое, многое другое, увы.


      1. AndyPike
        03.03.2019 17:20

        Да, согласен. Но любой JS программист знает, что массив тут пройдёт через .toString(). Да и все прочие '==='. Это всё понятно.Но тоже имеет право на жизнь.

        Я на Java никогда не писал, но знаю C++. По строгости типизации его сложно переплюнуть, по-моему. И говорить, что нет глубокого сравнения двух объектов «из коробки» — ну, в C++ его нет, и в JS тоже. Для первого — перезагружай оператор сравнения, для второго — подключай lodash.

        Nobody's perfect.


        1. shaukote
          03.03.2019 17:30

          По строгости типизации его сложно переплюнуть, по-моему.
          Вообще C++ справедливо считается «ярким примером» языка со слабой типизацией. :)

          нет глубокого сравнения двух объектов «из коробки» — ну, в C++ его нет, и в JS тоже
          Не очень корректное сравнение — C++ низкоуровневый язык с zero-cost abstractions как ключевая концепция.
          Сравните лучше с языками примерно того же класса — тем же Python (да и в Java, если я ничего не путаю, это тоже успешно реализовано).


        1. 0xd34df00d
          03.03.2019 19:11

          Плюсы по строгости типизации очень легко переплевываются (а по выразительности — и подавно).

          А глубокое сравнение из коробки, кстати, скоро будет.


      1. gearbox
        03.03.2019 22:58

        >То есть проблемы (или фичи, если угодно) того, что [1] + 2 === «12» или ToBoolean([]) === true никуда не денутся (как и многие другие).

            let n: number;                                                                                                                                                      
            n = [1] + 1;                                                                                                                                                        
            console.log(n); 
        


        TS2365: Operator '+' cannot be applied to types 'number[]' and '1'.

        ЧЯДНТ?

        А вообще это проблема не typescript-a (да, я согласен что есть проблемные места подобные указанным), это проблемы тайпингов, так вот — их можно подправить, сделать строже, это не сильно сложно.


        1. shaukote
          05.03.2019 08:41

          ЧЯДНТ?
          Всё так, это мой косяк.
          TypeScript пропускает сложение чисел и строк, разрешая неявное приведение типов между ними (и это меня слегка раздражает).
          Во всех остальных случаях TS ругается, да. Честно говоря, логику такого решения я совсем не понимаю — это и не строгая типизация, и не надмножество JS.

          это проблемы тайпингов, так вот — их можно подправить
          Я либо не согласен, либо не понял. :) Можете развернуть мысль?


          1. gearbox
            05.03.2019 11:19

            >TypeScript пропускает сложение чисел и строк
            Похоже у Вас либо версия несвежая либо в настройках послабления, я на прошлой неделе в своем коде втыкал parseInt что бы обойти ругательства typescript. UPD прочитал пост serf и вспомнил что у меня еще линтер подключен, вполне возможно что он ругался, да.

            >Я либо не согласен, либо не понял. :) Можете развернуть мысль?

            Все поведение js для typescript компайлера описано в тайпингах функций js, сам typescript чекер достаточно тупенький. За операторы не уверен (точнее почти уверен что нет), а вот вывод типов функций и методов встроенных объектов точно можно править. Я правил для reduce — он на какой то версии криво выводил типы (в моем кейсе по моему вообще не учитывался тип функции-аргумента). Загляните в node_modules/typescript/lib, там сразу видны тайпинги с которыми ts работает.


            1. shaukote
              05.03.2019 17:06

              либо версия несвежая либо в настройках послабления
              Нет, это именно штатное поведение. Проверял на tsc версии 3.3.3333 с флагом --strict. (Хотя смутно припоминаю, что оно так работает очень давно.)

              Опять же, линтеры это здорово, но слегка отдельная история.

              Все поведение js для typescript компайлера описано в тайпингах функций js, сам typescript чекер достаточно тупенький. За операторы не уверен (точнее почти уверен что нет), а вот вывод типов функций и методов встроенных объектов точно можно править.
              А, ну это-то я знаю, да. Даже заглядывать никуда особо не надо, IDE (да и тот же VS Code) сами умеют перекидывать на нужный тайпинг.


      1. serf
        05.03.2019 09:16

        То есть проблемы (или фичи, если угодно) того, что [1] + 2 === «12
        Подобные случаи думаю могут обработать статические анализаторы кода. Вероятно даже готовое решение как например lgtm.com.


        1. shaukote
          05.03.2019 14:40

          Да это вполне понятно. Речь же не об этом, о а том, что система типов TS покрывает отнюдь не все проблемы (или особенности, которые многие считаются таковыми) типизации JS.


  1. shaukote
    03.03.2019 17:24
    +1

    Позволю себе слегка поправить (за что глаз зацепился).

    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).


  1. lazant
    03.03.2019 17:33
    +2

    1. Мне кажется есть смысл сравнивать js с java в области nodejs.
    2. Для java программиста может показаться глотком свежего воздуха разработка на js хотя бы из-за наличия шикарных инструментов разработчика и самого процесса разработки. Сравнить хотя бы старт и перестарт проекта на spring и koa например. Я уж молчу про меньшую академичность кода и практически отсутствующий бойлерплейт код.
    3. js отнимает у java всё больше пространства, развивается быстрее и занимает всё больше ниш. Вот и в десктор ворвался, размахивая хромиумом.


  1. Dolios
    03.03.2019 17:33

    Автор, почитайте bonsaiden.github.io/JavaScript-Garden
    Это очень неплохой гайд про особенности JS, там перечисленны спорные и неочевидные моменты, которые часто вызывают трудности и непонимание.


  1. PaulMaly
    03.03.2019 18:05
    -1

    В целом сравнение интересное, но подошли к нему недостаточно профессионально и местами слишком поверхностно. Кое-где даже с фантазией. Но все равно спасибо.


    1. PaulMaly
      04.03.2019 10:11

      Интересно было бы послушать мнение минусующих вместо безликих минусов.


  1. gearbox
    03.03.2019 18:09
    +1

    Если не понятна разница между const/let и var (а еще есть hoisting) то может лучше не писать про JS а читать про JS?


  1. shaman4d
    03.03.2019 18:14
    +2

    Странная статья с полезностью, стремящейся к нулю.


    1. serf
      05.03.2019 09:20

      Просто автор совершил открытие что в мире существует не только java и делится с нами своими уникальными и незабываемыми впечатлениями. Я его понимаю, совершив открытие обычно хочется поделиться им с другими.


  1. msatersam11
    03.03.2019 19:46
    -4

    Мб и заминусуют, но, ИМХО, не вижу ничего хорошего ни в Java, ни в Java-программистах.

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

    То вторые, приходя в JS, последний откровенно загаживают.
    В JS есть много прикольного и интересного, но бывшие жаба/си-шарп-проггеры ничего этого не хотят — они ведь круутыыые, они ведь не какие-то там js-разрабы, а потому, они хотят кодить на JS аки на своих языках… со всеми типо_типизациями_которые_разумеется_решают_все_проблемы итд.
    Это приводит к порождению гор едва читаемого кода, который тупит почти на всех устройствах.

    Статическая типизация в принципе не спасает от ошибок.
    Горы лабораторных работ студентов на Си и «плюсах» тому яркое подтверждение.

    Если жаба такая крутая, то почему джава-программист «смотрит» на JS?
    Ведь, «в теории» должно быть ровно наоборот…


    1. rfq
      03.03.2019 20:20

      можете привести примеры прикольного и интересного?
      И как, по вашему — эти приколы облегчают или затрудняют сопровождение программ, написанных другими программистами?


    1. MikailBag
      03.03.2019 23:41

      В Си — одна из наиболее слабых систем типов. Rust или Haskell в этом плане более выразительны. (Например, их системы типов позволяют избежать null pointer error).


  1. Rulexec
    03.03.2019 19:56
    +1

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

    С технологической точки зрения «лучше» конечно же формально верифицированная зависимыми типами программа с понятной человеку спецификацией. Но в реальном мире на получение доказательства корректности «правильного квиксорта» у меня уйдёт пара дней.


    Каждая из статической/динамической сильной/слабой типизаций даёт свои профиты и даёт языкам свои ниши.


    Люди часто наезжают на JavaScript и понятно, за что, он не идеален. Мне нравится статическая типизация. Во-первых чтобы что-то написать, нужно продумать типы, что даёт половину решения и «места, куда писать код». Во-вторых при достаточно хороших типизациях написанный код «просто работает», иногда даже с первого раза. Но чем больше разбираешься с системами типов, тем больше хочется описать, что не всегда возможно. В итоге ушёл в JavaScript, который никогда не мешает и не требуется ничего доказывать компилятору.


    Типы в головах

    image


    1. JustDont
      03.03.2019 22:54

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

      Когда нужно написать какой-нибудь write once код, делающий что-то мелкое, но интересное со сложными структурами данных — статическая типизация требует то, что можно с полным правом назвать «бойлерплейтом»: да, всё опишешь, но это особо никому не пригодится. Идея, например, написать писать на тайпскрипте скрипт настройки dev-сервера у меня восторга не вызывает даже в теории — доказывать тайпскрипту, что у меня тут типы все как надо сходятся — будет на редкость бессмысленным занятием.

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


      1. 0xd34df00d
        06.03.2019 01:08

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

        Сервера я не настраиваю, а вот какие-то файлоперекладывательные скрипты на хаскеле писать вполне приятно. Начиная от описания опций в виде record'а и генерации парсера опций (очень круто, кстати, что вы там про бойлерплейт говорили?) и заканчивая тем, что мне так тупо проще.


  1. qbz
    04.03.2019 05:18

    Вот знаете, вроде и обидеть не хочется, но и приятного после прочтения тоже мало чего рождается. Зачем нам эти мысли вслух? Зачем вы начинаете копаться в языке не прочитав ничего по нему? Ведь вы даже азов не выучили. Просто представьте если бы кто-то сравнивал Норвежский язык и Русский — но без словарей, без этимологии итд, просто так. Смотрите — здесь слово похоже, но значит оно совсем другое — как так? Есть спецификация, либо читаете ее и вопросов больше не рождается, либо хотя бы каких-нибудь Илью Кантора, Акселя Раушмайера, Дмитрия Сошникова, Кайла Симпсона, Дугласа Крокфорда… Материалов в нашу JS-эру пруд пруди. Нет, надо взяться, наковырять на авось какой-то несуразицы. Так ладно бы вы это в файлик на рабочем столе сохранили и вернулись к нему со здравыми мыслями когда лень уйдет и появится желание читать мануалы/спеку. Так нет, надо накатать на Хабр, ведь это же бложек куда грех не написать. :(


    Вот не хочется бомбить, но прямо читать такое больно.


  1. Skycaptain
    04.03.2019 06:06

    А в чем собственно смысл статьи? Спровоцировать holy war?


    1. nicholasgribanov Автор
      04.03.2019 06:46

      Такой задачи не было. Была задача поделиться своими самыми первыми впечатлениями от использования JS и рассказать о вещах, которые вызвали у меня как разработчика на Java некоторое неудобство. Возможно, на эти же моменты обратят внимания другие джависты, решившие попробовать JS. Я не сталкиваю лбами JS и Java, даже не было задачи сравнивать. Поэтому реакция сообщества для меня стала неожиданной. Так или иначе имеется гора обратной связи. Спасибо интернету, что дает возможность получать ее в самом честном виде, без купюр, хоть и местами токсичненько


      1. zzzmmtt
        05.03.2019 08:20

        даже не было задачи сравнивать

        И всё-таки вы именно сравнивали.


  1. zzzmmtt
    04.03.2019 10:15
    -1

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

    IDE со встроенными инструментами анализа синтаксиса, линтеры… Не — не слышали.
    Писать JS-код в блокноте (без всех плюшек IDE) — ну такое…


  1. dolovar
    04.03.2019 10:52

    Возможно, это дело вкуса. А как считаете вы, что лучше слабая или сильная типизация?
    Что лучше — шурупы или гвозди? Это дело не вкуса, а задачи.


  1. serf
    05.03.2019 09:05

    Java и JavaScript — это не одно и тоже!
    Многие работники сферы HR с вами не согласились бы.
    Возможно, это дело вкуса. А как считаете вы, что лучше слабая или сильная типизация?
    Зависит от проекта. Если проект не одноразовый и сложнее todo app, то TypeScript конечно стоит выбирать изначально и сразу в strict режиме. С ростом проекта и команды преимущества будут ощущаться все сильнее в отличии от JS когда с ростом будут увеличиваться только проблемы.