The material, the translation of which we are publishing today, is devoted to the basics of JavaScript and is intended for novice programmers. It can be considered as a small reference book on the basic structures of JS. Here, in particular, we will talk about the data type system, variables, arrays, functions, object prototypes, and some other features of the language.

Primitive data types
JavaScript has the following primitive data types:
number ,
boolean ,
string ,
undefined ,
null . Immediately it should be noted that, when working with primitive data types, for example, with string literals, we, even without carrying out an explicit conversion, will be able to refer to their methods and properties. The point here is that when trying to perform such operations, literals are automatically equipped with the appropriate object wrapper.
▍Number
There is only one type of number in JavaScript — double-precision floating-point numbers. This leads to the fact that the results of the calculation of some expressions are arithmetically incorrect. Perhaps you already know that in JS the value of the expression
0.1 + 0.2 not equal to
0.3 . At the same time, when working with integers such problems are not observed, that is,
1 + 2 === 3 .
JavaScript has a
Number object, which is an object wrapper for numeric values. Objects of type
Number can be created either using a command like
var a = new Number(10) , or you can rely on the automatic behavior of the system described above. This, in particular, allows calling methods stored in
Number.prototype as applied to numeric literals:
(123).toString(); //"123" (1.23).toFixed(1); //"1.2"
There are global functions designed to convert values of other types into a numeric type. These are
parseInt() ,
parseFloat() and the
Number() construct, which in this case acts as a normal function that performs type conversion:
parseInt("1") //1 parseInt("text") //NaN parseFloat("1.234") //1.234 Number("1") //1 Number("1.234") //1.234
If during the operation with numbers something is obtained that is not a number (during some calculations, or when trying to convert something to a number), JavaScript will not give an error, but will present the result of such an operation as the value
NaN (Not-a-Number, not a number). In order to check whether a certain value is
NaN , you can use the function
isNaN() .
JS arithmetic operations work in a very familiar way, but you need to pay attention to the fact that the
+ operator can perform both addition of numbers and string concatenation.
1 + 1 //2 "1" + "1" //"11" 1 + "1" //"11"
▍Strings
Strings in JavaScript are sequences of Unicode characters. String literals create, enclosing the text to be placed in them, in double (
"" ) or single (
'' ) quotes. As already mentioned, when working with string literals we can rely on the corresponding object wrapper, in the prototype of which there are many useful methods, among them are
substring() ,
indexOf() ,
concat() .
"text".substring(1,3) //ex "text".indexOf('x') //2 "text".concat(" end") //text end
Strings, like other primitive values, are immutable. For example, the method
concat() does not modify the existing string, but creates a new one.
▍Logic values
The logical data type in JS is represented by two values -
true and
false . The language can automatically convert various values to a logical data type. So, false, in addition to the logical value
false , are the values
null ,
undefined ,
'' (empty line),
0 and
NaN . Everything else, including any objects, represents true values. In the course of performing logical operations, everything that is considered true is converted to
true , and everything that is considered false is converted to
false . Take a look at the following example. In accordance with the principles outlined above, the empty string will be converted to
false and as a result of the execution of this code, the string
This is false will appear in the console.
let text = ''; if(text) { console.log("This is true"); } else { console.log("This is false"); }
Objects
Objects are dynamic structures consisting of key-value pairs. Values can have primitive data types, can be objects or functions.
Objects are easiest to create using object literal syntax:
let obj = { message : "A message", doSomething : function() {} }
Object properties can, at any time, read, add, edit and delete. Here is how it is done:
- Reading properties:
object.name, object[expression] . - Writing data to properties (if the property being accessed does not exist, a new property with the specified key is added):
object.name = value , object[expression] = value . - Deletion of properties:
delete object.name , delete object[expression] .
Here are some examples:
let obj = {}; // obj.message = "A message"; // obj.message = "A new message"; // delete object.message; //
Objects in the language are implemented as hash tables. You can create a simple hash table using the
Object.create(null) command:
let french = Object.create(null); french["yes"] = "oui"; french["no"] = "non"; french["yes"];//"oui"
If the object needs to be made immutable, you can use the
Object.freeze() command.
To iterate through all the properties of an object, you can use the
Object.keys() command:
function logProperty(name){ console.log(name); // console.log(obj[name]); // } Object.keys(obj).forEach(logProperty);
▍Comparison of primitive types and objects
In practical work with primitive values, it is possible, as already mentioned, to perceive them as objects that have properties and methods, although they are not objects. Primitive values are immutable, the internal structure of objects can change.
Variables
In JavaScript, variables can be declared using the
var ,
let and
const keywords.
When using the
var keyword, you can declare a variable, and, if necessary, initialize it with a certain value. If the variable is not initialized, its value is
undefined . Variables declared using the
var keyword have a functional scope.
The
let keyword is very similar to
var , the difference is that variables declared with the
let keyword have a block scope.
Variables declared using the
const keyword, which, considering that the values of such variables cannot be changed, will be more correctly called "constants" have a block scope. The
const keyword, which “freezes” the value of a variable declared using it, can be compared with the
Object.freeze() method, which “freezes” objects.
If a variable is declared outside of any function, its scope is global.
Arrays
Arrays in JavaScript are implemented using objects. As a result, speaking of arrays, we are, in fact, discussing objects that are similar to arrays. You can work with array elements using their indices. Numeric indices are converted to strings and used as names to access the values of the elements of the arrays. For example, a structure of the form
arr[1] similar to a structure of the type
arr['1'] , and both will give access to the same value:
arr[1] === arr['1'] . In accordance with the above, a simple array declared by the command
let arr = ['A', 'B', 'C'] is represented as an object of approximately the following form:
{ '0': 'A', '1': 'B', '2': 'C' }
Deleting array elements using the
delete command leaves “holes” in it. In order to avoid this problem, you can use the
splice() command, but it works slowly, since, after removing an element, it moves the remaining elements of the array, in fact, shifting them to the beginning of the array, to the left.
let arr = ['A', 'B', 'C']; delete arr[1]; console.log(arr); // ['A', empty, 'C'] console.log(arr.length); // 3
Array methods make it easy to implement data structures such as stacks and queues:
// let stack = []; stack.push(1); // [1] stack.push(2); // [1, 2] let last = stack.pop(); // [1] console.log(last); // 2 // let queue = []; queue.push(1); // [1] queue.push(2); // [1, 2] let first = queue.shift();//[2] console.log(first); // 1
Functions
Functions in JavaScript are objects. Functions can be assigned to variables, stored in objects or arrays, passed as arguments to other functions, and returned from other functions.
There are three ways to declare functions:
- Classic function declaration (Function Declaration or Function Statement).
- The use of functional expressions (Function Expression), which are also called functional literals (Function Literal).
- Using the arrow function syntax (Arrow Function).
▍ Classic function declaration
With this approach to declaring functions, the following rules apply:
- The first keyword in the function declaration line is
function . - Functions must be assigned a name.
- The function can be used in the code that is before its declaration due to the mechanism of lifting the function declaration to the upper part of the scope in which it is declared.
This is what a classic function declaration looks like:
function doSomething(){}
▍Functional expressions
When using functional expressions, consider the following:
- The
function keyword is no longer the first word in a function declaration line. - The presence of a function name is optional. It is possible to use both anonymous and named functional expressions.
- Commands for calling such functions should follow the commands of their declaration.
- This function can be started immediately after the declaration, using the IIFE syntax (Immediately Invoked Function Expression - immediately called functional expression).
The functional expression looks like this:
let doSomething = function() {}
▍Fireout functions
Arrow functions, in fact, can be considered “syntactic sugar” for creating anonymous functional expressions. It should be noted that such functions do not have their own entities
this and
arguments . The declaration of the arrow function looks like this:
let doSomething = () = > {};
▍Ways to call functions
Functions can be called in various ways.
Normal function call
doSomething(arguments)
Function call as object method
theObject.doSomething(arguments) theObject["doSomething"](arguments)
Function call as constructor
new doSomething(arguments)
Calling a function using the apply () method
doSomething.apply(theObject, [arguments]) doSomething.call(theObject, arguments)
Calling a function using the bind () method
let doSomethingWithObject = doSomething.bind(theObject); doSomethingWithObject();
Functions can be called with more or fewer arguments than the number of parameters that were specified when they were declared. During the work of the function, the “extra” arguments will be simply ignored (although the function will have access to them), the missing parameters will get the value
undefined .
Functions have two pseudo-parameters:
this and
arguments .
▍ Keyword this
The keyword
this is the context of the function. The value to which it points depends on how the function was called. Here are the values that the this keyword takes depending on how the function is called (they, with code examples, the constructions of which are used here, are described above):
- The usual function call is
window / undefined . - The function call as an object method is
theObject . - A function call as a constructor is a new object.
- Calling a function using the
apply() method - theObject . - Calling a function using the
bind() method - theObject .
▍ arguments keyword
The
arguments keyword is a pseudo-parameter that gives access to all the arguments used in the function call. It looks like an array, but is not an array. In particular, it has no array methods.
function reduceToSum(total, value){ return total + value; } function sum(){ let args = Array.prototype.slice.call(arguments); return args.reduce(reduceToSum, 0); } sum(1,2,3);
An alternative to the
arguments keyword is the new syntax for the remaining parameters. In the following example,
args is an array containing everything that was passed to the function when it was called.
function sum(...args){ return args.reduce(reduceToSum, 0); }
ReturnOperator return
A function that does not have a
return will return
undefined . Using the
return keyword, pay attention to how the automatic semicolon insertion mechanism works. For example, the following function returns not an empty object, but an
undefined value:
function getObject(){ return { } } getObject()
In order to avoid such a problem, the opening brace should be placed on the same line as the
return :
function getObject(){ return { } }
Dynamic typing
JavaScript is a language with dynamic typing. This means that specific values are of types, and variables are not. During program execution, values of different types can be written to the same variable. Here is an example of a function that works with values of different types:
function log(value){ console.log(value); } log(1); log("text"); log({message : "text"});
To determine the type of data stored in a variable, you can use the
typeof() operator:
let n = 1; typeof(n); //number let s = "text"; typeof(s); //string let fn = function() {}; typeof(fn); //function
Single threaded execution model
The JavaScript runtime is single-threaded. This, in particular, is expressed in the impossibility of simultaneously performing two functions (unless we take into account the possibilities of asynchronous code execution, which we do not affect here). In the runtime, there is a so-called Event Queue, which stores a list of tasks that need to be processed. As a result, the problem of interlocking resources is not typical for a single-flow JS execution scheme, so there is no need for a locking mechanism. However, code that enters the event queue must be executed quickly. If you overload with hard work, in the browser application, the main thread, the application page will not react to the user's impact and the browser will offer to close this page.
Exception Handling
JavaScript has a mechanism for handling exceptions. It works according to a quite common principle for such mechanisms: the code that can cause an error is made using the
try/catch construct. The code itself is in a
try block, errors are processed in a
catch .
It is interesting to note that sometimes JavaScript, in the event of an emergency, does not produce error messages. This is due to the fact that JS did not throw errors before adopting the ECMAScript 3 standard.
For example, in the following code snippet, an attempt to change a “frozen” object will fail, but no exception will be thrown.
let obj = Object.freeze({}); obj.message = "text";
Some of the "silent" errors of JS appear in strict mode, you can enable it using the
"use strict"; construct
"use strict"; .
Prototype system
At the heart of such JS mechanisms as constructor functions, the
Object.create() command, the
class keyword, is the prototype system.
Consider the following example:
let service = { doSomething : function() {} } let specializedService = Object.create(service); console.log(specializedService.__proto__ === service);
Here, the
Object.create() command is used to create a
specializedService object, the prototype of which was to make the
service object. As a result, it turns out that the
doSomething() method can be called by accessing the
specializedService object. In addition, this means that the
__proto__ property of a
specializedService object points to a
service object.
Now create a similar object using the
class keyword:
class Service { doSomething(){} } class SpecializedService extends Service { } let specializedService = new SpecializedService(); console.log(specializedService.__proto__ === SpecializedService.prototype);
Methods declared in the
Service class will be added to the
Service.prototype object. Instances of the
Service class will have the same prototype (
Service.prototype ). All instances will delegate method calls to the
Service.prototype object. As a result, it turns out that methods are declared only once, in
Service.prototype , after which they are "inherited" by all instances of the class.
A prototype chain
Objects can be "heirs" of other objects. Each object has a prototype whose methods are available to it. If you try to access a property that is not in the object itself, JavaScript will start searching for it in the prototype chain. This process will continue until the property is found, or until the search reaches the end of the chain.
About functional programming in javascript
In JavaScript, functions are first-class objects; the language supports a closure mechanism. This opens the way to the implementation of functional programming techniques in JS. In particular, we are talking about the possibility of using higher-order functions.
A closure is an internal function that has access to variables declared inside the parent function, even after executing the parent function.
A higher order function is a function that can accept other functions as arguments, return functions, or do both.
Functional programming in JS is covered in a variety of publications. If this is interesting to you, here are some materials on this topic dedicated
to first-class functions ,
composition ,
decorators ,
closures and
readability of code written in a functional style.
Results
The power of JavaScript lies in its simplicity. Understanding the basic mechanisms of the language allows a programmer who uses JS to more effectively use these mechanisms and lays the foundation for his professional growth.
Dear readers! What do you think, what features of JavaScript cause the most problems for beginners?
