If you're searching for a programming language to learn, JavaScript is probably the best option: it's easy to get started (you just need a web browser) and is a very useful language to learn since it allows to develop web apps, dekstop apps (Node.js, Electron), mobile apps (Ionic, React Native) by using a single programming language.
This guide briefly explains JavaScript fundamentals with some examples. Prior programming knowledge is assumed.
Tip: Use your browser's console to try the examples in this guide.
In JavaScript variables are declared with var
. No need to specify a type:
var x;
Values, though, do have type. The simplest ones are numbers, strings and booleans:
var n = 7;
var s = 'hello';
var b = true;
typeof n; // 'number'
typeof s; // 'string'
typeof b; // 'boolean'
Note: There's no distinction between integers and floats.
Note: Comments are inserted with //
or /*
and */
.
You can use null
to represent non-valid values. There's also a special
undefined
value which is automatically given to non-initialized variables:
var x;
console.log(x); // undefined
Note: console.log
prints values to the console.
JavaScript has a very simple syntax for array literals:
var numeri = [ 1, 2, 3 ];
Unlike other languages, JavaScript allows arrays to contain values of different types:
var chaos = [ 1, 'hello', false, null ];
This is how you access individual array elements:
var chars = [ 'a', 'b', 'c' ];
console.log(chars[0]); // 'a'
console.log(chars[1]); // 'b'
console.log(chars[2]); // 'c'
chars[0] = 'z';
console.log(chars); // [ 'z', 'b', 'c' ]
JavaScript arrays have type object
and can have properties. The most useful
one is length
:
[ 'a', 'b', 'c' ].length; // 3
Same syntax as C and many other languages:
if (x > 5) {
console.log('x is bigger than 5');
} else {
console.log('x is lower than or equal to 5');
}
In boolean expressions remember that JavaScript has sloppy (==
) and strict
(===
) equal tests:
console.log('5' == 5); // true
console.log('5' === 5); // false
Note: There are also !=
and !==
operator with similar semantics.
Note: Use ==
and !=
with caution. There's risk in propagating values
with unpredictable type.
In JavaScript null
, undefined
and empty strings are equivalent to false
,
so conditionals are often written like this:
if (x) {
console.log('x has no value');
} else {
console.log('x is: ' + x);
}
Same syntax as many other languages:
// Counting from 1 to 10
for (var i = 0; i < 10; i++) {
console.log(i + 1);
}
A JavaScript function is a parametrized sequence of instructions:
function sum(a, b) {
return a + b;
}
var x = sum(7, 3);
console.log(x); // 10
Note: Just like variables, parameters have no type.
JavaScript functions are treated as values so you can assign them to variables:
var aFunction = function (x) {
console.log(x);
};
aFunction('Hi'); // 'Hi'
This example also shows another JavaScript feature: anonymous functions.
Anonymous functions make sense when immediately assigned or invoked:
(function (x) {
console.log(x);
})('Hi'); // 'Hi'
Immediately invoked functions may seem useless, for instance the previous example may also be written like this:
var x = 'Hi';
console.log(x); // 'Hi'
In reality immediately invoked functions allow to preserve the current scope:
function example() {
var n = 7;
console.log(n);
}
esempio(); // 7
console.log(n); // Error (not existent here)
Scope will be treated in detail here.
JavaScript functions may be invoked with an arbitrary number of arguments:
missing arguments will be undefined
, while exceeding arguments will simply be
ignored.
function example(x1, x2) {
if (x2 === undefined) {
console.log(x1);
} else {
console.log([ x1, x2 ]);
}
}
example(7); // 7
example(7, 42); // [ 7, 42 ]
example(7, 42, 666); // [ 7, 42 ]
You can also use the keyword arguments
which represents current arguments as
an array:
function example() {
console.log(arguments[0]);
console.log(arguments[1]);
console.log(arguments[2]);
console.log(arguments.length);
}
example('a', 'b'); // 'a', 'b', undefined, 2
This makes it easy to implement function with a variable number of arguments.
JavaScript variables have a scope that corresponds to the function in which are declared and includes nested functions:
function externalFunction() {
var n = 7;
function aNestedFunction() {
// n accessible here
function anEvenDeeperFunction() {
// n accessible here too
}
}
}
In other words, every function "captures" the execution context in which is declared. In JavaScript we call "closure" a function with its execution context.
Closures allow to preserve an execution context even after a function returns:
function example(x) {
return function () {
return x;
}
}
var f = example(7);
f(); // 7
Here f
preserves example
's execution context even after example
returns.
This behavior is very powerful, but keep in mind memory usage.
JavaScript variables are subjet to "hoisting": when code is executed it doesn't matter where a declaration actually happens, declarations will always be executed first. For instance this code:
function example() {
console.log('hi');
var n = 7;
}
Will be executed as if it was written like this:
function example() {
var n;
console.log('hi');
n = 7;
}
This sometimes causes subtle bugs, so many JavaScript developers try to always write declarations at the beginning of a function in order to be consistent with actual execution.
JavaScript objects are basically sets of name-value pairs called "properties":
var marco = {
name: 'Marco',
age: 30
};
console.log(marco.name); // 'Marco'
console.log(marco.age); // 30
Here we have an object with two properties called name
and age
with values
'Marco'
and 30
. The .
operator is used to access property values given
their names. Alternatively, you can use this syntax:
console.log(marco['name']); // 'Marco'
console.log(marco['age']); // 30
This syntax have 2 benefits. First, it allows dynamic access:
var whichProperty = 'name';
console.log(marco[whichProperty]); // 'Marco'
Second, it allows using names otherwise forbidden such as names with special characters or language reserved identifiers:
var weirdObject = {
'property with a weird name': 42
};
console.log(weirdObject['property with a weird name']); // 42
Since JavaScript functions are values, they can be assigned as property values and used like methods:
var marco = {
saySomething: function (what) {
console.log(what);
}
};
marco.saySomething('hi'); // 'hi'
The kayword this
can be used within a method to access other properties of
the same object:
var marco = {
name: 'Marco',
sayHi: function () {
console.log('Hi, my name is ' + this.name);
}
};
marco.sayHi(); // 'Hi, my name is Marco'
Objects are always "editable": you can add, delete or change values of properties, even when they are methods.
var marco = {}; // Let's start with an empty object
marco.name = 'Marco'; // We add a property
// We add a method
marco.sayHi = function () {
console.log('Hi, my name is ' + this.name);
};
// We add, modify and finally delete a property
marco.age = 30;
marco.age = 31;
delete marco.age;
JavaScript object properties are easily iterable:
var marco = { name: 'Marco', age: 30 };
for (var propertyName in marco) {
console.log(marco[propertyName]);
} // 'Marco', 30
JavaScript functions may be used as object constructors:
function Person(name) {
this.name = name;
this.sayHi = function () {
console.log('Hi, my name is ' + this.name);
};
}
var marco = new Person('Marco');
marco.sayHi(); // 'Hi, my name is Marco'
This has some benefits. First, objects created with a constructor share a common, extensible "prototype" from which they automatically inherit properties:
function Person(name) {
this.name = name;
}
var marco = new Person('Marco');
var fabio = new Person('Fabio');
Person.prototype.sayHi = function () {
console.log('Hi, my name is' + this.nome);
};
marco.sayHi(); // 'Hi, my name isMarco'
fabio.sayHi(); // 'Hi, my name isFabio'
Inherited properties may be overridden:
function Person(name) {
this.name = name;
this.sayHi = function () {
console.log('Hi, my name is ' + this.name);
};
}
var marco = new Person('Marco');
var fabio = new Person('Fabio');
fabio.sayHi = function () {
console.log('Yo! I\'m ' + this.nome);
};
marco.sayHi(); // 'Hi, my name is Marco'
fabio.sayHi(); // 'Yo! I'm Fabio'
Another benefit of constructors is that they allow instanceof
tests:
function Person(name) { ... }
var marco = new Person('Marco');
marco instanceof Persona; // true
var cloneOfMarco = { name: 'Marco' };
cloneOfMarco instanceof Persona; // false
This concludes our JavaScript overview. Other JavaScript guides may be added in future, so stay tuned :D