JavaScript Guide, Part 7: strict mode, this keyword, events, modules, mathematical calculations

Published on November 27, 2018

JavaScript Guide, Part 7: strict mode, this keyword, events, modules, mathematical calculations

Original author: Flavio Copes
  • Transfer
  • Tutorial
Today, in the seventh part of the translation of the JavaScript manual, we will talk about executing code in strict mode, about the features of the this keyword, about events, modules, about mathematical calculations. Here we will touch on the topic of work with timers and asynchronous programming.

Part 1: first program, language features, standards
Part 2: code style and program structure
Part 3: variables, data types, expressions, objects
Part 4: functions
Part 5: arrays and cycles
Part 6: exceptions, semicolon, template literals
Part 7: strict mode, this keyword, events, modules, mathematical calculations
Part 8: an overview of the capabilities of the standard ES6
Part 9: a review of the capabilities of the standards ES7, ES8 and ES9



Strict regime


Strict mode (strict mode) appeared in the standard ES5. In this mode, the semantics of the language changes, it is aimed at improving the behavior of JavaScript, which leads to the fact that the code in this mode does not behave like normal. In fact, we are talking about the fact that this mode eliminates the shortcomings, ambiguities of the language, outdated features that remain in it for compatibility reasons.

▍Include strict mode


In order to use strict mode in some code, it must be explicitly enabled. That is, we are not talking about the fact that this mode is applied by default. Such an approach would disrupt the work of countless existing programs based on the mechanisms of the language that have been present in it since the very beginning, since 1996. In fact, the significant efforts of those who develop JavaScript standards are aimed precisely at ensuring compatibility, so that the code written for old versions of standards can be executed on today's JS engines. This approach can be considered one of the keys to the success of JavaScript as a language for web development.

In order to enable strict mode, a special directive is used, which looks like this.

'use strict'

The same effect will cause the directive and recorded in the form "use strict", and the same directive, after which set a semicolon ( 'use strict';and "use strict";). This directive (exactly like this, along with quotes), so that all the code in a certain file would be executed in strict mode, is placed at the beginning of this file.

'use strict'
const name = 'Flavio'
const hello = () => 'hey'
//...

Strict mode can be enabled at the level of a single function. To do this, the corresponding directive must be placed at the beginning of the code of the function body.

function hello() {
  'use strict'
  return 'hey'
}

This can be useful if you need to use strict mode in the existing code base and at the same time including it at the file level is impractical due to lack of time to thoroughly test the code of the entire file.

It should be noted that if strict mode is turned on, you cannot turn it off during program execution.

Consider some of the features of strict mode.

▍ Fighting random initialization of global variables


We have already said that if you accidentally assign some value to an undeclared variable, even if you do it in the function code, such a variable will be made global by default (belonging to the global object). This can lead to surprises.

For example, the following code creates exactly such a variable.

;(function() {
  variable = 'hey'
})()

The variable variablewill be available in the global scope after running IIFE.

If you enable strict mode at the level of this function, the same code will cause an error.

;(function() {
  'use strict'
  variable = 'hey'
})()

▍Errors that occur during the assignment of values


JavaScript, as usual, does not report any errors that occur during the execution of value assignment operations.

For example, in JS there is a value undefined , which is one of the primitive values ​​of a language and is represented by a property of a global object undefined. In the usual JS such a command is quite possible.

undefined = 1

It looks like writing a unit to a certain variable with a name undefined, but in reality it is an attempt to write a new value to the property of a global object, which, by the way, according to the standard, cannot be overwritten. In the normal mode, although such a command is possible, it will lead to nothing - that is, the value undefinedwill not be changed, and the error message will not appear. In strict mode, this will cause an error. In order to see this error message, and at the same time make sure that the value is undefinednot redefined in the normal mode, try running the following code in a browser or in Node.js.

undefined = 1
console.log('This is '+undefined)
;(() => {
  'use strict'
  undefined = 1
})()

The same system behavior is also characteristic when working with such entities as values Infinityand NaN, as well as with other similar ones. Strict mode allows you to avoid all this.

In JavaScript, you can set object properties using the Object.defineProperty () method . In particular, using this method, you can set properties that cannot be changed.

const car = {}
Object.defineProperty(car, 'color', {
   value: 'blue', 
   writable: false 
})
console.log(car.color)
car.color = 'yellow'
console.log(car.color)

Note the attribute writable: falseused when setting the property color.

The above code, executed in normal mode, will not lead to a change in the property of the object color, nor to the conclusion of an error. An attempt to change this property in strict mode will end in an error.

;(() => {
  'use strict'
  car.color = 'red'
})()

The same applies to getters. This code will run, albeit to no avail.

const car = {
  get color() {
    return 'blue'
  }
}
console.log(car.color)
car.color = 'red'
console.log(car.color)

And an attempt to do the same in strict mode will cause an error reporting an attempt to set a property of an object that has only a getter.

;(() => {
  'use strict'
  car.color = 'yellow' 
}
)()

In JavaScript, there is an Object.preventExtensions () method that makes an object non-extensible, that is, one to which new properties cannot be added. When working with such objects in the usual mode, the same features of the language that we considered above appear.

const car = { color: 'blue' }
Object.preventExtensions(car)
console.log(car.model)
car.model = 'Fiesta'
console.log(car.model)

Here both attempts to display the property of an object modelwill result in a value in the console undefined. There was no such property in the object; an attempt to create it after the object was made non-expandable did not lead to anything. The same action in strict mode results in an error message.

;(() => {
  'use strict'
  car.owner = 'Flavio'
}
)()

In the same category of actions that do not lead to any changes, possibly expected by the programmer, but not causing any errors, there are operations in the course of which attempts are made to assign certain properties to primitive values. For example, such code, in the usual mode, will not cause an error, but will not give any results.

let one = 1
one.prop = 2
console.log(one.prop)

The same in strict mode will result in an error message indicating that the number 1cannot create a property prop. Similarly, the system behaves when working with other primitive data types.

▍Error associated with the removal of entities


In normal mode, if you try to delete, using the operator delete , the property of an object that cannot be deleted, deletesimply returns falseand all quietly end in failure.

delete Object.prototype

In strict mode, an error will be displayed here.

▍ Arguments of functions with the same name


Functions may have parameters with the same name, it does not cause errors (although this looks like an error of who created such a function).

;(function(a, a, b) {
  console.log(a, b)
})(1, 2, 3) //2 3

This code in the usual mode displays in the console 2 3. In strict mode, this will cause an error.

By the way, if, when declaring the arrow function, its parameters will have the same name, this, in normal mode, will result in an error message.

Ось Octal values


In normal JavaScript, you can use octal values ​​by adding numbers to the beginning 0.

;(() => {
  console.log(010)
})() //8

Here the decimal representation of the octal number will fall into the console 10, that is 8. This 0before the number can be set randomly. In strict mode it is impossible to work with octal numbers specified in this format. But if you need to use strict mode and work with octal numbers, you can write them in format 0oXX. The following code will also output 8.

;(() => {
  'use strict'
  console.log(0o10)
})() //8

▍Operator with


The operator with , the use of which can lead to confusion, is strictly prohibited.
Changing the behavior of the code in strict mode is not limited to those discussed above. In particular, in this mode, the keyword thiswith which we have already come across and which we will now discuss in more detail behaves differently .

Keyword Features


The keyword this, or execution context, allows you to describe the environment in which the JS code is executed. Its value depends on the place of its use and on whether strict mode is enabled or not.

СтрогKeyword this in strict mode


In strict mode, the value thispassed to the function is not cast to the object. This transformation not only requires resources, but also gives functions access to the global object if they are called from this, set to undefinedor null. This behavior means that the function can gain unauthorized access to the global object. In strict mode, the conversion thispassed to the function is not performed. In order to see the difference between the behavior thisin functions in different modes - try this code using the directive 'use strict'and without it.

;(function() {
  console.log(this)
})()

▍The keyword this in object methods


A method is a function referenced in an object property. The keyword thisin such a function refers to this object. This statement can be illustrated by the following example.

const car = {
  maker: 'Ford',
  model: 'Fiesta',
  drive() {
    console.log(`Driving a ${this.maker} ${this.model} car!`)
  }
}
car.drive()
//Driving a Ford Fiesta car!

In this case, we use the usual function (and not the arrow function - this is important), the keyword thisused in which is automatically attached to the object containing this function.

Note that the above method for declaring an object's method is similar to this:

const car = {
  maker: 'Ford',
  model: 'Fiesta',
  drive: function() {
    console.log(`Driving a ${this.maker} ${this.model} car!`)
  }
}

The same behavior of the keyword thisin the object method can also be observed using the following construct.

const car = {
  maker: 'Ford',
  model: 'Fiesta'
}
car.drive = function() {
  console.log(`Driving a ${this.maker} ${this.model} car!`)
}
car.drive()
//Driving a Ford Fiesta car!

▍The keyword this and arrow functions


Let's try to rewrite the above example using the arrow function as an object method.

const car = {
  maker: 'Ford',
  model: 'Fiesta',
  drive: () => {
    console.log(`Driving a ${this.maker} ${this.model} car!`)
  }
}
car.drive()
//Driving a undefined undefined car!

As you can see, here, instead of the names of the car manufacturer and its model, the values ​​are displayed undefined. The fact is that, as we have said, thisthe arrow function contains a link to the context that includes the function.

It is impossible to bind to an arrow function this, and

▍Partition this


In JavaScript, there is such a thing as binding this. This can be done in different ways. For example, when declaring a function, you can bind its keyword thisto an object using a method bind().

const car = {
  maker: 'Ford',
  model: 'Fiesta'
}
const drive = function() {
  console.log(`Driving a ${this.maker} ${this.model} car!`)
}.bind(car)
drive()
//Driving a Ford Fiesta car!

Using the same method this, you can bind another object to the method of one object.

const car = {
  maker: 'Ford',
  model: 'Fiesta',
  drive() {
    console.log(`Driving a ${this.maker} ${this.model} car!`)
  }
}
const anotherCar = {
  maker: 'Audi',
  model: 'A4'
}
car.drive.bind(anotherCar)()
//Driving a Audi A4 car!

Binding thiscan be organized at the stage of calling the function using the call()and methods apply().

const car = {
  maker: 'Ford',
  model: 'Fiesta'
}
const drive = function(kmh) {
  console.log(`Driving a ${this.maker} ${this.model} car at ${kmh} km/h!`)
}
drive.call(car, 100)
//Driving a Ford Fiesta car at 100 km/h!
drive.apply(car, [100])
//Driving a Ford Fiesta car at 100 km/h!

It thisbinds to what is passed to these methods as the first argument. The difference between these methods is that apply(), as the second argument, it takes an array with the arguments passed to the function, and it call()takes a list of arguments.

▍About this binding in browser event handlers


In event event callbacks, it thisindicates the HTML element with which an event occurred. In order to bind to a callback, as thissomething else, you can use the method bind(). Here is an example illustrating this.

<!DOCTYPE html>
<html>
  <body>
  
    <button id="el">Element (this)</button>
    <button id="win">Window (this</button>
    <script>
      const el = document.getElementById("el")
      el.addEventListener('click', function () {
          alert(this) //object HTMLButtonElement
      })
      const win = document.getElementById("win")
      win.addEventListener('click', function () {
          alert(this) //object Window
      }.bind(this))
    </script>
  </body>
</html>

Developments


JavaScript in the browser uses an event-based programming model. Certain actions are performed by the code in response to events that occur. In this section we will talk about events and how to handle them.

The event can be, for example, the completion of the DOM loading, data retrieval performed as a result of an asynchronous request, mouse click on the page element, page scrolling, input of a certain character from the keyboard. In fact, there are many events, processing which, the JS-code of the page allows you to solve a wide range of tasks on the application's interaction with users, with page elements, with the environment in which the code works.

Событий Event Handlers


You can react to events using event handlers, which are functions that are called when events occur.
If necessary, several handlers can be registered to handle the same event, which will be called if this event occurs. You can register event handlers in various ways. Consider three such ways.

Built-in event handlers


These days, built-in event handlers are rarely used because of their limitations. Previously, they were used much more often. To set such an event handler, its code is added to the HTML markup of the element as a special attribute. In the following example, such a simple event handler onclickthat occurs when a button is clicked is assigned to a button with an inscription Button 1.

<!DOCTYPE html>
<html>
  <body>
  
    <button onclick="alert('Button 1!')">Button 1</button>
    <button onclick="doSomething()">Button 2</button>
    <script>
        function doSomething(){
            const str = 'Button 2!'
            console.log(str)
            alert(str)
        }
      
    </script>
  </body>
</html>

The HTML code for the button Button 2uses a similar approach, but it indicates the function whose code is executed in response to a button click. This code outputs the specified string to the console and displays a window with the same text.

▍ Assignment of the handler to the property of the HTML element


This method of assigning event handlers is suitable for cases where a certain element event should have only one handler. It consists in assigning a function to the corresponding property of the element.

For example, an object windowhas an event onloadthat is triggered after loading the HTML code of the page and all the additional resources it needs, for example, styles and images. If you assign a handler to this event, then when you call it, you can be sure that the browser has loaded the entire contents of the page, with which you can now work programmatically, without fear that some page elements have not yet been loaded.

window.onload = () => {
    alert('Hi!') //страница полностью загружена
}

This approach is often used in the processing of XHR requests. So, during the setup of a request, you can set its onreadystatechange event handler , which will be called when its property status changes readyState. Here is an example of using this approach to load JSON data from a public API.

<!DOCTYPE html>
<html>
  <body>
  
    <button onclick="loadData()">Start</button>
    <script>
        function loadData (){
            const xhr = new XMLHttpRequest()
            const method = 'GET'
            const url = 'https://jsonplaceholder.typicode.com/todos/1'
            xhr.open(method, url, true)
            xhr.onreadystatechange = function () {
                if(xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
                    console.log(xhr.responseText)
                }
            }
            xhr.send()
       }
      
    </script>
  </body>
</html>

You can check whether the handler is assigned to a certain event.

if (window.onload){}

▍Using addEventListener () method


The method addEventListener()that we have already met is a modern mechanism for assigning event handlers. It allows you to register multiple handlers for one event.

window.addEventListener('load', () => {
  //загрузка завершена
})

Please note that IE8 (and older versions of it) do not support the method addEventListener(). It uses a similar method attachEvent(). This should be taken into account if your program must support legacy browsers.

▍About assigning event handlers to various elements


You can connect event handlers to an object windowto handle "global" events, such as keystrokes on the keyboard. At the same time, individual HTML elements are assigned event handlers that react to what happens to these elements, for example, mouse clicks. Therefore, the method is addEventListener()used both with the object windowand with ordinary elements.

Event Event Object


As the first parameter, an event handler can accept an event object - Event. The set of properties of this object depends on the event that it describes. Here, for example, is a code that demonstrates handling keyboard keystroke events using an keydownobject event window.

<!DOCTYPE html>
<html>
  <body>
    <script>
        window.addEventListener('keydown', event => {
            //нажата клавиша на клавиатуре
            console.log(event.type, event.key)
        })
        window.addEventListener('mousedown', event => {
            //нажата кнопка мыши
            //0 - левая кнопка, 2 - правая
            console.log(event.type, event.button, event.clientX, event.clientY)
        })
    </script>
  </body>
</html>

As you can see, here, to display information about the pressed key to the console, the object property is used key. It also uses the property typeindicating the type of event. In this example, in fact, we are working with the KeyboardEvent object , which is used for descriptions of keyboard-related events. This object is an inheritor of the Event object . Objects designed to handle various events extend the capabilities of the standard event object.

In the same example, a MouseEvent object is used to handle mouse-related events . In the event handler, mousedownwe output to the console the type of event, the button number (property button), and pointer coordinates at the time of the click (properties clientXandclientY).

The DragEvent object is used when handling events that occur while dragging page elements.

Among the properties of the object Eventthat are available in other event objects, we can mention the already mentioned property typeand the property targetindicating the DOM element on which the event occurred. The object Eventhas methods. For example, the method createEvent()allows you to create new events.

Спspot events


Consider the following example.

<!DOCTYPE html>
<html>
    <head>
        <style>
            #container { 
                height: 100px;
                width: 200px;
                background-color: blue;
            }
            #child { 
                height: 50px;
                width: 100px;
                background-color: green;
            }
        </style>
    </head>
    <body>
    <div id="container">
        <div id="child">
        </div>
    </div>
    <script>
        const contDiv = document.getElementById('container')
        contDiv.addEventListener('click', event => {
            console.log('container')
        })
        const chDiv = document.getElementById('child')
        chDiv.addEventListener('click', event => {
            console.log('child')
        })
        window.addEventListener('click', event => {
            console.log('window')
        })
      
    </script>
  </body>
</html>

If you open the download page with the code in the browser, open the console and click the mouse first in the free area of ​​the page, then on the blue rectangle, and then on the green, then the console will get the following:

window
container
window
child
container
window


Event

ascent That which can be observed here is called event bubbling. Namely, an event that occurs in a child element extends to the parent element. This process continues until the event reaches the topmost element. If the elements on which the pop-up event passes have the appropriate handlers defined, they will be called according to the order of the event propagation.

Event ascent can be stopped using the stopPropagation()event object method . For example, if it is necessary that, after clicking on an element child, the corresponding event does not extend further, we need to rewrite the code in which we assign an event handler to it click, as follows.

chDiv.addEventListener('click', event => {
    console.log('child')
    event.stopPropagation()
})

If we now perform the same sequence of actions that we performed above, that is, click in the free area of ​​the window, then on the element container, and then on child, the following will be displayed in the console.

window
container
window
child

▍Frequently used events


Consider some of the events, the processing of which is needed most often.

Event load


The event loadis raised on the object windowwhen the page has completed loading. Other elements have similar events, for example, an HTML element body.

Mouse events


The event clickis triggered by a mouse click. Event dblclick- double click. In this case, if event handlers are specified clickand dblclick, the event handler is first called click, and then - dblclick. Events mousedown, mousemove, mouseupcan be used for the treatment of drag and drop objects on the page. It should be noted that if an element is assigned to an event handler mousemove, this handler will be invoked many times during the movement of the mouse pointer over the element. In such situations, if some sufficiently heavy calculations are performed in the corresponding handler, it makes sense to limit the frequency of these calculations. We will talk about this below.

Keyboard events


The event keydownis triggered by pressing the keyboard key. If the key is held down, it continues to be called. When the key is released, the event is triggered keyup.

Scroll event


The event scrollis fired for an object windowwhen scrolling through a page. In the event handler, you can, in order to find out the position of the scroll, access the property window.scrollY.

This event, as well as the event mousemove, is called during the execution of the corresponding operation many times.

Limiting the frequency of calculations in event handlers


Events mousemoveand scrollgive information about the coordinates of the mouse and the position of the scroll. Performing some serious calculations in the event handlers of such events can slow down the program. In such a situation, it makes sense to think about limiting the frequency of such calculations. This technique is called "throttling" (throttling), its implementation can be found in specialized libraries like Lodash . The essence of this technique is to create a mechanism that allows you to limit the frequency of performing certain actions that, without limitation, would be performed too often. Consider our own implementation of this mechanism.

let cached = null
window.addEventListener('mousemove', event => {
    if (!cached) {
        setTimeout(() => {
            //предыдущее событие доступно через переменную cached
            console.log(cached.clientX, cached.clientY)
            cached = null
            }, 100)
    }
    cached = event
})

Now calculations performed when an event occurs are mousemovemade no more than once per 100 milliseconds.

ES modules


In the ES6 standard, a new feature appeared, called the ES-modules. The need for standardization of this opportunity has been long overdue, which means that the developers of client parts of web projects and server programmers writing for Node.js have been using something like that for a long time.

A module is a file containing some code. From this file, you can export, make public, functions and variables. They can be used simply by connecting the module to a certain file with a code, while the internal mechanisms of the module are not accessible from the outside.

In Node.js, the CommonJS standard has been used and continues to be used as a module system for a long time. In browsers, before the advent of ES-modules, various libraries and project building systems were used, imitating the ability to work with modules. Now, after standardization, browsers gradually introduce support for ES-modules, which suggests that quite soon additional funds will not be needed to support the modules. In particular, according to the information of the caniuse.com resource , at the end of November 2018, the level of support for ES modules by browsers slightly exceeds 80%.

Work on the introduction of ES-modules is conducted in Node.js.

ES ES module syntax


Node.js uses this entry to connect ES modules.

import package from 'module-name'

When working with CommonJS modules, the same thing looks like.

const package = require('module-name')

As already mentioned, the module is a JavaScript file that exports something. This is done using a keyword export. For example, we write a module that exports a function that converts the string passed to it to uppercase, and give the file its name uppercase.js. Let the text be like this.

export default str => str.toUpperCase()

Here, the default export command is set in the module, so an anonymous function can be exported. Otherwise, the exported entities must be named.
Now this module can be imported into some code (to another module, for example) and use its capabilities there.

You can upload a module to an HTML page using an <script>attribute tag type="module".

<script type="module" src="index.js"></script>

Please note that this method of importing modules works as deferred loading of the script. In addition, it is important to take into account the fact that in our example in the module uppercase.jsexport is used by default, therefore, when importing it, you can assign any desired name to it. This is how it looks in the code of a web page. In order for you to have this example earned, you will need a local web server. For example, if you use the VSCode editor, you can use its Live Server extension (identifier - ritwickdey.liveserver).

<!DOCTYPE html>
<html>
  <head>
  </head>
  <body>
    <script type="module">
      import toUpperCase from './uppercase.js'
      console.log(toUpperCase('hello'))
    </script>
  </body>
</html>

After downloading this page, the text will get to the console HELLO.

Modules can also be imported using an absolute URL.

import toUpperCase from 'https://flavio-es-modules-example.glitch.me/uppercase.js'

Paths in module import commands can be either absolute or relative, starting with ./or /.

▍Other import and export opportunities


Above, we gave an example of a module that uses the default export.

export default str => str.toUpperCase()

However, several entities can be exported from the module.

const a = 1
const b = 2
const c = 3
export { a, b, c }

If this code is placed in a file module.js, then import everything that it exports, and you can use all of this as follows.

<html>
  <head>
  </head>
  <body>
    <script type="module">
      import * as m from './module.js'
      console.log(m.a, m.b, m.c)
    </script>
  </body>
</html>

The console will be displayed 1 2 3.

You can import from the module only what you need, using the structures of the following type.

import { a } from './module.js'
import { a, b } from './module.js'

You can use what is imported directly.

console.log(a)

Imported entities can be renamed:

import { a, b as two } from './module.js'

If the module uses both the default export and other export commands, then one command can import both what is exported by default and other entities. Rewrite our module module.js.

const a = 1
const b = 2
const c = 3
export { a, b, c }
export default () => console.log('hi')

Here's how to import and use it.

import sayHi, { a } from './module.js'
console.log(a)
sayHi()

An example of working with the module can be found here .

▍CORS


When loading modules, CORS is used . This means that in order to successfully load modules from other domains, they must have a CORS header, allowing cross-site scripting (like Access-Control-Allow-Origin: *).

Nom Attribute nomodule


If the browser does not support working with modules, then working on the page, you can provide a backup mechanism in the form of loading the script using the script tag in which the attribute is specified nomodule. A browser that supports modules will ignore this tag.

<script type="module" src="module.js"></script>
<script nomodule src="fallback.js"></script>

▍About the ES6 and WebPack modules


ES6 modules are a great technology that appeals to the fact that it is included in the ECMAScript standard. But, using modules, you need to strive to ensure that the number of downloaded files would be small, otherwise it may affect page loading performance. In this regard, it should be said that the WebPack bandler used to package the application code, apparently, will not lose relevance for a long time.

Common CommonJS Modules


As already mentioned, Node.js uses the CommonJS module system. This system allows the developer to create small independent code fragments suitable for use in many projects and amenable to offline testing. CommonJS has created a huge ecosystem of npm modules.

Let's write a CommonJS module based on an example that we have already considered. Namely, put the up-node.jsfollowing code in the file .

exports.uppercase = str => str.toUpperCase()

In order to use this module in a certain program, you need to connect it.

const up = require('./up-node.js')
console.log(up.uppercase('hello'))

After executing this code will get to the console HELLO.

Usually packages loaded from npm are imported as shown below.

const package = require('module-name')

CommonJS modules are loaded synchronously and processed in the order in which the corresponding commands are detected in the code. This system is not used in the client code.

You can export several entities from the CommonJS module.

exports.a = 1
exports.b = 2
exports.c = 3

You can import them as follows, using the possibilities for destructuring assignment.

const { a, b, c } = require('./up-node.js')

Mathematical calculations


Mathematical calculations are often found in any program, and JavaScript is no exception. Let's talk about the arithmetic operators of a language and about an object Mathcontaining embedded implementations of some useful functions. In order to experiment with what we are going to talk about here, it is convenient to use the browser JS-console.

▍Arithmetic operators


Addition (+)


The operator +performs the addition of numbers and string concatenation. Here are examples of its use with numbers:

const three = 1 + 2 //3
const four = three + 1 //4

This is how it behaves with strings, converting, if necessary, other data types to string type.

'three' + 1 // three1

Subtraction (-)


const two = 4 - 2 //2

Division (/)


When working with ordinary numbers, the division operator behaves quite expectedly.

20 / 5 //4
20 / 7 //2.857142857142857

If you divide the number by 0, it will not cause an error. The result of such an operation will be the value Infinity(for a positive dividend) or - Infinity(for a negative dividend).

1 / 0 //Infinity
-1 / 0 //-Infinity

Remainder of the division (%)


The operator %returns the remainder of the division, in some situations this may be useful.

20 % 5 //0
20 % 7 //6

The remainder of the division by 0 is a special value NaN(Not a Number is not a number).

1 % 0 //NaN
-1 % 0 //NaN

Multiplication (*)


1 * 2 //2
-1 * 2 //-2

Exponentiation (**)


This operator raises the first operand to the power specified by the second operand.

1 ** 2 //1
2 ** 1 //2
2 ** 2 //4
2 ** 8 //256
8 ** 2 //64

▍ Unary operators


Increment (++)


The unary operator ++can be used to add 1to a certain value. It can be placed before the incremented value or after it.

If it is placed before a variable, it first increases the number stored in it by 1, after which it returns this number.

let x = 0
++x //1
x //1

If you put it after a variable, it will first return its previous value, and then increase it.

let x = 0
x++ //0
x //1

Decrement (-)


The unary operator --is similar to the one above, ++with the difference that it does not increase the values ​​of variables by 1, but decreases them.

let x = 0
x-- //0
x //-1
--x //-2

Unary operator (-)


Such an operator allows positive numbers to be negative and vice versa.

let x = 2
-x //-2
x //2

Unary operator (+)


This operator, if the operand is not a number, tries to convert it to a number. If the operator is already a number, nothing happens.

let x = 2
+x //2
x = '2'
+x //2
x = '2a'
+x //NaN

Прис Assignment Operator and its Varieties


In JavaScript, in addition to the usual assignment operator ( =), there are several varieties of it that simplify the execution of frequently encountered operations. Here, for example, the operator +=.

let x = 2
x += 3
x //5

It can be read as follows: "Add to the value of the variable on the left, what is on the right, and write the result of the addition in the same variable." In fact, the above example can be rewritten as follows.

let x = 2
x = x + 3
x //5

Other similar operators work on the same principle:

  • -=
  • *=
  • /=
  • %=
  • **=

Операторов Operator Priority


When working with complex expressions, the priority of operators must be taken into account. For example, consider the following expression.

const a = 1 * 2 + 5 / 2 % 2

The result of his calculation will be 2.5. In order to understand how the result of this expression is obtained, one must take into account the precedence of operators. The following list of operators begins with those that have the highest priority.

  • - + ++ -- - unary operators, increment and decrement operators
  • / % - multiplication, division, obtaining the remainder of division
  • + - - addition and subtraction
  • = += -= *= /= %= **= - assignment operators

Operators with the same priority are executed in the order they are detected in the expression. If you step by step write the calculation of the above expression, you get the following.

const a = 1 * 2 + 5 / 2 % 2
const a = 2 + 2.5 % 2
const a = 2 + 0.5
const a = 2.5

To override the order in which the statements are executed, the corresponding parts of the expression can be included in parentheses. Consider the following expression.

const a = 1 * (2 + 5) / 2 % 2

The result of his calculation will be 1.5.

▍Math Object


The object Mathcontains properties and methods designed to simplify mathematical calculations. Details about it can be read here . This object is used independently, without creating instances.

Among its properties it is possible, for example, to note Math.E- a constant containing the number e, and Math.PI- a constant containing the number π.

Math.E // 2.718281828459045
Math.PI //3.141592653589793

Here is a list of some useful methods of this object.

  • Math.abs() - returns the absolute value of a number
  • Math.ceil() - rounds a number, returning the smallest integer greater than or equal to the specified one
  • Math.cos() - returns the cosine of an angle expressed in radians
  • Math.floor() - rounds a number, returning the largest integer less than or equal to the specified one
  • Math.max() - returns the maximum of the numbers transferred to it
  • Math.min() - returns the minimum of the numbers transferred to it
  • Math.random() - returns a pseudo-random number from the range [0, 1) (not including 1)
  • Math.round() - rounds the number to the nearest integer
  • Math.sqrt() - returns the square root of

▍Comparison of values


For comparison of values ​​in JavaScript, comparison operators are used, with some of which we have already met.

  • ==- operator of nonstrict equality. Before comparing values, performs type conversion.
  • != - operator of non-strict inequality.

These operators are recommended to be used very carefully, as they can lead to unexpected results of comparisons. Best of all, if for no particular reason, use the appropriate operators that perform strict checks.

  • === - strict equality operator
  • !== - operator of strict inequality

Here are some more comparison operators.

  • < - operator "less"
  • > - operator “more”.
  • <= - operator "less than or equal to."
  • >= - operator "greater or equal".

Here is one of the examples illustrating the features of the work of operators of non-strict and strict equality.

1 === true //false
1 == true //true

In the first case, the values ​​are compared without type conversion, as a result it turns out that the number is 1not equal true. In the second case, the number is 1given to trueand the expression tells us that 1they trueare equal.

Timers and asynchronous programming


The relevant sections of the manual, the translation of which we publish, raise topics on the use of timers and asynchronous programming. These topics were covered in a previously published translation of the course on Node.js. In order to get acquainted with them, we recommend reading the following materials:


Here you can find a PDF version of the translation course for Node.js.

Results


In this article we talked about strict mode, about the features of the this keyword, about events, about modules, about mathematical calculations. Next time we will discuss the innovations that the ES6 standard has brought to the language.

Dear readers! Have you encountered any errors that are caused by using a non-strict equality operator in javascript?