Как стать автором
Обновить

Первый взгляд на JavaScript глазами Java — разработчика

Время на прочтение6 мин
Количество просмотров15K


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, почему-то был в восторге от нее. Возможно, это дело вкуса. А как считаете вы, что лучше слабая или сильная типизация?
Теги:
Хабы:
Всего голосов 66: ↑22 и ↓44-22
Комментарии58

Публикации

Истории

Работа

React разработчик
84 вакансии
Java разработчик
386 вакансий

Ближайшие события

27 августа – 7 октября
Премия digital-кейсов «Проксима»
МоскваОнлайн
28 – 29 сентября
Конференция E-CODE
МоскваОнлайн
28 сентября – 5 октября
О! Хакатон
Онлайн
30 сентября – 1 октября
Конференция фронтенд-разработчиков FrontendConf 2024
МоскваОнлайн
3 – 18 октября
Kokoc Hackathon 2024
Онлайн
7 – 8 ноября
Конференция byteoilgas_conf 2024
МоскваОнлайн