Путь от Delphi до Javascript

(Часть 1)

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

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

Цель этой статьи — познакомить разработчика Delphi со светом Javascript и показать, как точки Delphi связаны с шаблонами программирования Javascript. В статье намеренно избегаются крайние случаи использования Javascript при введении основных понятий. Это поможет разработчикам Delphi избежать ловушки, когда они заглядывают слишком глубоко в воду, когда они едва умеют плавать.

Начнем с различий между этими замечательными средами разработки.

Комплексная среда IDE и многооконная отладка

Самым ужасным сдерживающим фактором на пути перехода от Delphi к Javascript является самая сложная и блестящая среда разработки Delphi, а также те удобства, которые программисты Delphi привыкли получать от нее. Delphi — одна из самых быстрых сред разработки, и почти все операции по редактированию кода, линтингу, рефакторингу, отладке и развертыванию выполняются одним нажатием кнопки, если не автоматически. Первое различие концепций, которое должен уложить в голове традиционный программист Delphi, — это отсутствие составной среды, которую в настоящее время имеет жизненный цикл разработки Javascript. Это правда, что современные редакторы и средства автоматизации задач очень приблизили эти удобства — но их нужно настроить — что иногда не очень просто для того, кто привык к полноте среды Delphi. Короче говоря, подумайте о переходе от универсальной IDE к среде, состоящей из множества инструментов и нескольких окон на рабочем столе.

Технология Javascript

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

Другое важное отличие заключается в том, что Javascript — это не среда программирования, а стандарт языка. Другими словами, места, где вы запускаете Javascript, могут быть разными — это может быть браузер или NodeJS — каждая среда устанавливает разные операции ввода-вывода для вашей программы — но язык один и тот же. Стандарты языка Javascript устанавливаются Ecma International, руководящим органом стандарта.

Это можно дополнительно пояснить на следующем примере

console.log(‘Hello Javascript’);

Если вы выполните эту команду в Node JS, вы увидите вывод в командном окне, где запускается Node JS. Напротив, если вы запустите эту команду в браузере, вы увидите вывод в консоли разработчика браузера. Что это значит?

Это означает, что сам Javascript является стандартным синтаксисом, но ввод-вывод будет зависеть от того, где он выполняется.

Еще один пример: изменение элемента DOM в браузере может привести к запуску написанной вами функции Javascript. Напротив, в Node JS нет элементов DOM, но он может запускать функцию, когда программа Node JS получает удаленный запрос. Обе программы имеют одинаковые спецификации и стандарты, но ввод-вывод может различаться в зависимости от того, где работает ваша программа.

Таким образом, всякий раз, когда вы запускаете программу Javascript, ваш ввод-вывод и механизм запуска будут зависеть от того, где выполняется ваша программа. Теперь не переживайте — общих для Node JS и браузера программ вы не напишете. Они всегда отдельно.

Строгий режим

Javascript является гибким, а иногда и слишком гибким — предполагалось, что гибкость заставляет программистов делать больше ошибок, чем они должны. В последующие годы в Javascript был введен «строгий режим», чтобы контролировать эту гибкость. Строгий режим накладывает определенные ограничения на гибкость и почти все сообщество расценивает это как позитивный шаг. Итак, мы собираемся выполнить все программирование на Javascript в строгом режиме. Просто добавьте use strict в качестве первой строки кода Javascript.

‘use strict’
console.log(“strict mode”);

Как тестировать примеры

Лучший способ выполнить тесты по темам, которые мы обсуждаем, — это запустить Node JS и запустить там свои тесты. Вот руководство по настройке без каких-либо знаний в Node JS:

https://medium.com/@hex.nanotech/quick-start-node-js-with-debugging-49aeee657b4d

Давайте начнем сейчас.

Переменные Delphi против переменных Javascript

Переменные Javascript не являются строго типизированными. Другими словами, вы можете просто определить переменную без связанного с ней типа. Тип переменной в любой момент времени — это тип хранимого в ней значения.

Давайте посмотрим на типичное замедление переменной в Javascript.

var i;    //This variable type is "undefined"

or

var i = 10;   //This variable is a number

и позже…

i = ‘banana’  //And now this variable is of the string type

Вторым наиболее важным отличием Javascript от Delphi является то, что вы можете объявить переменную где угодно.

В Дельфах

function ShowMeHow: Integer;
var
   S: String;   //Variables can be declared only here
   I, J: Integer;
begin
   S := 'This is how';
   ShowMessage(S);
   I := 10;
   J := 15;
   ShowMessage(InttoStr(I + J));
end;

В Javascript

function showMeHow(){
   
   var s = 'This is how';
   console.log(s);
   var i = 10;
   var j = 15;
   console.log(i + j);
}

«Неопределенное» против «ReferenceError»

Это одна из самых больших ловушек, в которую попадают разработчики Delphi to Javascript. Хотя «неопределенный» звучит как несуществующий или ненайденный, на самом деле это означает, что сущность, на которую вы пытаетесь ссылаться, существует, но не определена должным образом. С другой стороны, когда что-то не найдено или на него нельзя сослаться, будет выброшен Javascript «ReferenceError». Взгляните на следующий фрагмент.

var i;
console.log(i); // undefined
console.log(j); //Reference Error

При попытке записать i переменная в этот момент уже существует, но ей не присвоено значение. Это вызывает undefined . Теперь при попытке записать j переменной действительно нет, поэтому будет выброшено ReferenceError. Разработчикам Delphi, выполняющим миграцию, очень важно хорошо понимать эту концепцию.

Вариативный хостинг

Другая замечательная характеристика переменных Javascript — это то, как они поднимаются в пределах области видимости. Программист может объявить переменную где угодно, но во время выполнения переменная будет отображаться так, как если бы она была объявлена ​​в самом начале области видимости.

function hoistingDemo() {
  console.log(i); //undefined
  console.log(j) // ReferenceError
  var i;
}

Посмотрите внимательнее на приведенную выше функцию. Переменная i объявлена ​​внизу функции, и нет переменной с именем j. Теперь оператор console.log(i) выводит «undefined». Это означает, что даже если i не объявлено к моменту выполнения оператора консоли, оно все еще существует. Напротив, переменная j фактически отсутствует и генерирует ошибку ReferenceError.

Типы данных

Типы данных Javascript делятся на две основные ветви:

  1. Примитивные типы — числа, строки, логические значения и т. д.
  2. Типы объектов — массивы, объекты, функции (серьезно?) и т. д.

Основное различие между этими типами заключается в том, что примитивные типы являются прямыми переменными. Думайте о них как об обычной переменной Integer в Delphi — переменная сама содержит значение. Типы объектов, с другой стороны, являются ссылками. То есть переменная действительно указывает на адрес памяти в куче или стеке — там в этом адресе и находится значение переменной. Думайте о типах объектов как о pointer в Delphi — память выделяется, и переменная ссылается только на эту выделенную память.

Примитивные типы довольно просты. Они ведут себя точно так же, как и любая переменная в типичном языке.

var i = 2;
var s = “Hello JS”;
var powerUser = true;

Типы объектов тоже довольно просты в торможении и управлении. Это полезная гибкость в Javascript.

var aStudent = new Object();

var myArray = new Array();

Кроме того, существует короткий синтаксис для создания объектов. Этот синтаксис называется «буквенным» синтаксисом. Объект может быть создан с помощью «объектного литерала», а массив может быть создан с помощью «массивного литерала».

var aStudent = {};
var myArray = [];

Это наиболее используемый и быстрый способ создания объектов и массивов в обычном Javascript.

Как освободить память, выделенную объектными типами переменных

Ну, ответ «вы не можете» и «вам действительно не нужно». В отличие от Delphi, Javascript — это язык со сборщиком мусора. Это означает, что освобождение памяти полностью контролируется средой выполнения языка. Выделенные переменные типа объекта автоматически освобождаются, когда механизм Javascript решает, что они больше не нужны. Это достигается путем отслеживания ссылок, связанных с выделенным объектом. Один из важных аспектов механизма сборки мусора Javascript заключается в том, что нет никакой гарантии, что объект будет освобожден сразу же после удаления его последней ссылки. Это полностью автоматическая операция, и программист не имеет к ней никакого отношения.

Семантика Delphi этого поведения - это объекты, которые реализуют интерфейс TInterfacedObject, где такие объекты будут автоматически уничтожены, когда счетчик ссылок на них станет равным нулю. Другой близкий пример — Delphi Strings. Для строк Delphi память выделяется менеджером памяти FastMM за кулисами. Эта память автоматически освобождается, когда в коде больше нет ссылок на строку.

Работа с объектами

Давайте создадим объект и назначим ему некоторые свойства. В следующем фрагменте мы создаем объект aStudent и создаем два его свойства — свойства «имя» и «возраст».

var aStudent = new Object();
Object.defineProperty(aStudent, 'name', {
  enumerable: true,
  configurable: false,
  writable: false,
  value: 'Jhon'
});
Object.defineProperty(aStudent, 'age', {
  enumerable: true,
  configurable: true,
  writable: true,
  value: 15
});
console.log(aStudent);    // { name: 'Jhon', age: 25 }

Каждый дескриптор свойства имеет 4 поля.

configurabletrue тогда и только тогда, когда тип дескриптора этого свойства может быть изменен и если свойство может быть удалено из соответствующего объекта.
По умолчанию равно false.

enumerabletrue тогда и только тогда, когда это свойство отображается во время перечисления свойств соответствующего объекта.
По умолчанию равно false.

valueЗначение, связанное со свойством. Может быть любым допустимым значением JavaScript (число, объект, функция и т. д.).
По умолчанию равно undefined.

writabletrue тогда и только тогда, когда значение, связанное со свойством, может быть изменено с помощью оператора присваивания.
По умолчанию равно false.

Это так сложно? Правда?

Не совсем. Хотя свойства объекта могут быть созданы описанным выше способом, Javascript также предлагает для этого гибкий сокращенный синтаксис.

var aStudent = new Object(); // or var aStudent = {}
aStudent[“name”] = “Jhon”; //bracket notation
aStudent.age = 15; //dot notation

Хорошие новости никогда не заканчиваются в Javascript. Вот как вы можете сделать это в одном выражении. Javascript — это весело.

var aStudent = {name: “Jhon”, age: 15};

И продолжайте, добавьте больше свойств к существующему объекту.

aStudent.grade = 10;
//Let’s add another property by a variable
var genderProperty = “sex”;
aStudent[genderProperty] = “male”
console.log(aStudent);

Вывод комбинации двух последних сниппетов

{имя: «Джон», возраст: 15, класс: 10, пол: «мужской» }

Резюме

Играйте с этими различиями и проводите свои собственные эксперименты. Javascript имеет очень мягкую кривую обучения, которая, к сожалению, кажется пугающей для программистов Delphi. Эта серия статей снимет этот барьер и направит программиста-мигратора на ускоренный путь с включенным автопилотом.

Мы обсудим все удивительные функции в Javascript в следующей статье.