(Part 1)
Javascript has been emerging as the most popular and widely used programming language since the millennium and is dominating the industry like no other programming language has ever done before. Javascript is considered the standard programming language of the web while web itself is the single most widely used computer platform ever built.
It is at least one time every traditional Delphi programmer is challenged with learning Javascript — but deterred due to the fundamental differences of the programming models these two languages are designed on. The most challenging aspect of this learning curve is making correspondences with the development patterns an average Delphi programmer is used to.
The aim of this article is to bring the Delphi developer under the Javascript light and show where the Delphi dots are connected within Javascript programming patterns. The article purposefully avoids extreme cases of Javascript when introducing basic concepts. This will help the Delphi developers in avoiding the pitfall of looking too deep down the water when they can barely swim.
Let’s start with the differences between these great development environments.
Compound IDE vs Multi-window debugging
The most dreadful deterrent factor of the Delphi to Javascript journey is Delphi’s most compound and brilliant IDE — and the conveniences Delphi programmers accustomed to get from it. Delphi is one of the fastest development environments and almost all the code editing, linting, refactoring, debugging and deployments are just a press of a button away if not automatic. The first difference of concepts the traditional Delphi programmer should put in to his head is the lack of compound environment the Javascript development lifecycle currently has. It is true that the modern editors and task automation tools has brought these conveniences very close — but they need to be setup — which, sometimes, is not very straightforward for someone who has used to the completeness of Delphi environment. In short, make your mind to shift from all-in-one IDE to an environment which consists of many tools and multiple windows in your desktop.
The Technology Behind Javascript
It is a common misconception that Javascript executes a script one line at a time. But the truth is that, even though a Javascript program doesn’t have a compilation step, the Javascript engine compiles the source instantly every time it runs, create the byte code and starts executing. This is called Just In Time compilation.
The other major difference is that Javascript is not a programming environment — it is a language standard. In other words, where you run Javascript may be diverse — it could be in the Browser or in NodeJS — each environment sets different I/O to your program— but the language is the same. The Javascript language standards are set by Ecma International, the governing body of the standard.
This can be further explained using the following example
console.log(‘Hello Javascript’);
If you execute this command in Node JS, you will see the output in the command window where Node JS runs. In contrast, if you run this command in a browser, you will see the output in the developer console of the browser. What does this mean?
This means Javascript itself is a standard syntax — but the I/O will be depending on where it runs.
One other example is how a change of a DOM element in the browser can trigger a Javascript function you write. In contrast, Node JS don’t have DOM elements — but it can trigger a function when the Node JS program receives a remote request. Both the programs have the same specifications and standard — but the I/O can be different depending on where your program runs.
So, whenever you run a Javascript program, your I/O and triggering mechanism will be depending on where your program runs. Now, don’t worry — you will not write programs common for Node JS and the browser. They are always separate.
Strict Mode
Javascript is flexible and, sometimes, too flexible — that the flexibility was alleged to be making the programmers do more mistakes than they should. In later years the “strict mode” was introduced to Javascript in order to control this flexibility. The strict mode imposes certain restrictions on the flexibility and almost the entire community regards this as a positive step. So, we are going to do all the Javascript programming in strict mode. Simply add use strict
as the first line of your Javascript code.
‘use strict’console.log(“strict mode”);
How to test the examples
The best way to perform tests on the topics we discuss would be to spin up Node JS and run your tests there. Here is a guide to do this setup without having any knowledge in Node JS:
https://medium.com/@hex.nanotech/quick-start-node-js-with-debugging-49aeee657b4d
Let’s get started now.
Delphi Variables vs Javascript Variables
Javascript variables are not strictly typed. In other words, you can simply define a variable with no type associated with it. The type of a variable at any given time is the type of the value it holds.
Let’s see a typical variable deceleration in Javascript
var i; //This variable type is "undefined"
or
var i = 10; //This variable is a number
and later…
i = ‘banana’ //And now this variable is of the string type
The second most important character of Javascript against Delphi is that you can declare a variable anywhere you want.
In 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;
In Javascript
function showMeHow(){
var s = 'This is how';
console.log(s); var i = 10;
var j = 15; console.log(i + j);}
The “undefined” vs “ReferenceError”
This is one of the biggest pitfalls the Delphi to Javascript developers fall in to. Although “undefined” sounds a vibe of non-existing or not-found, this really means that the entity you are trying to refer is there — but it is not defined well. On the other hand, when something is not found or cannot referred to, it is the “ReferenceError” Javascript will throw. Take a look at the following snippet.
var i;console.log(i); // undefined
console.log(j); //Reference Error
When trying to log i
the variable at this point is already there- but there is no value assigned. This causes undefined
. Now when trying to log j
the variable is really not there- so, the ReferenceError
would be thrown. It is very important for the migrating Delphi developers to have a good grasp in this concept.
Variable Hosting
The other great characteristic of Javascript variables is the way they are hoisted within the scope. The programmer has the freedom to declare a variable anywhere — but, at run time, the variable will be appeared as if they are declared at the very beginning of the scope.
function hoistingDemo() { console.log(i); //undefined console.log(j) // ReferenceError var i;}
Have a closer look at the above function. The variable i
is declared at the bottom of the function and there is no variable called j
. Now the statement console.log(i)
outputs “undefined”. This means, even though the i
is not declared by the time the console statement is executed, it is still there. In contrast, the variable j
is not there for a fact and it generates the ReferenceError.
The Data Types
Javascript data types are categorized into two main branches:
- Primitive Types — numbers, strings, boolean etc
- Object Types — arrays, objects, functions (seriously?) etc
The main difference between these types are that the Primitive Types are direct variables. Think of them as a regular Integer variable in Delphi — the variable itself holds the value. The Object Types, on the other hand, are referenced. That is, the variable really points to a memory address in the heap or stack — the value of the variable is there in this address. Think of Object Types as a pointer
in Delphi — the memory is allocated and the variable only refers to this allocated memory.
Primitive Types are pretty simple. They behave just like any variable in a typical language.
var i = 2;var s = “Hello JS”;var powerUser = true;
Object Types too are pretty simple in the deceleration and the management too. This is a useful flexibility in Javascript.
var aStudent = new Object();
var myArray = new Array();
Also, there is a short hand syntax for creating objects. This syntax is called “literal” syntax. An object can be created with an “object literal” and an array can be created with an “array literal”.
var aStudent = {};var myArray = [];
This is the most used and fastest way to create objects and arrays in conventional Javascript.
How to free the memory allocated by object variable types
Well, the answer is “you cannot” and “you really don’t have to”. Unlike Delphi, Javascript is a garbage collected language. This means that the memory disposals are fully controlled by the language run-time. The allocated object type variables are automatically freed when the Javascript engine decides that they are needed no more. This is achieved by tracking the references which are maid to an allocated object. One important aspect of Javascript garbage collection mechanism is that there is no guarantee that an object is freed up soon as its last reference was taken off. This is a fully automatic operation and the programmer has no hand whatsoever in it.
Delphi semantic of this behavior are objects which implements TInterfacedObject
interface where such objects will automatically be destroyed when the reference count of them become zero. Another close example is Delphi Strings. Delphi strings are allocated memory for by FastMM memory manager behind the scenes. This memory is automatically freed up when the string is no more referenced anywhere in the code.
Working with Objects
Let’s create an object and assign some properties to it. In the following snippet we create the aStudent
object and create two properties of it — the “name” and “age” properties.
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 }
Every property descriptor has 4 fields.
configurabletrue
if and only if the type of this property descriptor may be changed and if the property may be deleted from the corresponding object.
Defaults to false
.
enumerabletrue
if and only if this property shows up during enumeration of the properties on the corresponding object.
Defaults to false
.
value
The value associated with the property. Can be any valid JavaScript value (number, object, function, etc).
Defaults to undefined
.
writabletrue
if and only if the value associated with the property may be changed with an assignment operator.
Defaults to false
.
Is it that hard? Really?
Not really. Although the object properties can be created in the above way, Javascript offers a flexible shorthand syntax for this too.
var aStudent = new Object(); // or var aStudent = {}aStudent[“name”] = “Jhon”; //bracket notation
aStudent.age = 15; //dot notation
Good news never end in Javascript. Here is how you can do it in a single statement. Javascript is that fun.
var aStudent = {name: “Jhon”, age: 15};
And go on, add more properties to an existing object.
aStudent.grade = 10;//Let’s add another property by a variable
var genderProperty = “sex”;
aStudent[genderProperty] = “male”console.log(aStudent);
The output of the combination of the last two snippets
{ name: ‘Jhon’, age: 15, grade: 10, sex: ‘male’ }
Summary
Play with these differences and do your own experiments. Javascript has a very soft learning curve — which unfortunately appears daunting to Delphi programmers. This series of articles will take that barrier off and put the migrating programmer on the fast track with auto pilot on.
We will discuss the all amazing functions in Javascript in the next article.