JavaScript Guide, Part 3: Variables, Data Types, Expressions, Objects

Original author: Flavio Copes
  • Transfer
  • Tutorial
Today, in the third part of the translation of the JavaScript guide, we will talk about different ways of declaring variables, data types, expressions, and features of working with objects.

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 features of the ES6 standard
Part 9: ES7, ES8 and ES9 features overview



Variables


A variable is an identifier that has been assigned a value. The variable can be accessed in the program, working in this way with the value assigned to it.

By itself, a variable in JavaScript does not contain information about the type of values ​​that will be stored in it. This means that by writing a variable, for example, a string, you can later write a number into it. Such an operation will not cause an error in the program. That is why JavaScript is sometimes called "untyped" language.

Before using a variable, it must be declared using the keyword varor let. If we are talking about a constant, a keyword is used const. It is possible to declare a variable and assign it some value without using these keywords, but this is not recommended.

Var var keyword


Prior to the ES2015 standard, using a keyword varwas the only way to declare variables.

var a = 0

If this construction is omitted var, the value will be assigned to the undeclared variable. The result of this operation depends on the mode in which the program runs.

So, if the so-called strict mode (strict mode) is included, the similar will cause an error. If strict mode is not enabled, an implicit variable declaration will occur and it will be assigned to the global object. In particular, this means that a variable implicitly declared in this way in a certain function will be available after the function completes. Usually, it is expected that variables declared in functions do not “go beyond” their limits. It looks like this:

function notVar() {
  bNotVar = 1 //лучше так не делать
}
notVar()
console.log(bNotVar)

It will get into the console 1, usually no one expects such behavior from the program, the expression bNotVar = 1does not look like an attempt to declare and initialize a variable, but as an attempt to access a variable that is external to the function of the scope (this is quite normal). As a result, the implicit declaration of variables confuses those who read the code and can lead to unexpected program behavior. Later we will talk about functions and areas of visibility, but in the meantime try to always, when the meaning of a certain expression is to declare a variable, to use specialized keywords. If in this example the body of the function is rewritten as var bNotVar = 1, then an attempt to start the above code snippet will result in an error message (you can see it in the browser console).

Look it, for example, can be as follows: Uncaught ReferenceError: bNotVar is not defined. Its meaning is that the program cannot work with a non-existent variable. It is much better, when you first start the program, to see such an error message than to write incomprehensible code that is able to behave unexpectedly.

If, when a variable is declared, it is not initialized, it is not assigned any value to it, the value will automatically be assigned to it undefined.

var a //typeof a === 'undefined'

Variables declared using a keyword varcan be repeatedly declared again by assigning new values ​​to them (but this can confuse the person who is reading the code).

var a = 1
var a = 2

You can declare several variables in one expression:

var a = 1, b = 2

The scope of a variable (scope) is the area of ​​the program in which this variable is available (visible).

A variable initialized with a keyword varoutside of a function is assigned to a global object. It has a global scope and is accessible from anywhere in the program. If a variable is declared using a keyword varinside a function, then it is visible only inside this function, being a local variable for it.

If a varvariable is declared in the function, using , the name of which coincides with the name of some variable from the global scope, it will “override” the global variable. That is, when accessing such a variable inside a function, its local variant will be used.

It is important to understand that blocks (code areas enclosed in braces) do not create new scopes. A new scope is created when the function is called. The keyword varhas a so-called functional scope, and not block.

If a variable is declared in the function code, it is visible to the entire function code. Even if a variable is declared using a varfunction at the end of a code, it can also be accessed at the beginning of the code, since the JavaScript variable lifting mechanism (hoisting) works. This mechanism "raises" the declaration of variables, but not the operation of their initialization. This can be a source of confusion, so make it a rule to declare variables at the beginning of a function.

Let Keyword let


The let keyword appeared in ES2015, which, simply, can be called a “block” version var. The scope of variables declared using a keyword letis limited to the block, operator or expression in which it is declared, as well as nested blocks.

If the word “let” itself does not seem very clear, one can imagine that the word “let” is used instead. Then the expression let color = 'red'can be translated into English like this: “let the color be red”, and into Russian - like this: “let the color be red”.

When using a keyword, letyou can get rid of the ambiguities that accompany the keyword var(for example, you will not be able to double, using let, declare the same variable). Usingletoutside the function, say, when initializing cycles, does not lead to the creation of global variables.

For example, this code will cause an error:

for (let i = 0; i < 5; i++) {
    console.log(i)
}
console.log(i)

If, on initialization of the cycle, the counter iis announced using the keyword var, it iwill be available outside the cycle, after it completes the work.

Nowadays, when developing JS-programs based on modern standards, it is quite possible to completely abandon varand use only keywords letand const.

▍ Keyword const


Values ​​of variables declared using the keywords varor letcan be overwritten. If instead of these keywords is used const, then a new value cannot be assigned to a constant declared and initialized with its help.

const a = 'test'

In this example, the constant acannot be assigned a new value. But it should be noted that if ais not a primitive value, like a number, but an object, the use of a keyword constdoes not protect this object from changes.

When they say that an object is written to a variable, they actually mean that an object reference is stored in the variable. This link cannot be changed, and the object to which the link leads can be changed.

The keyword constdoes not make objects immutable. It simply protects against changes references to them, written in the corresponding constants. Here's what it looks like:

const obj = {}
console.log(obj.a)
obj.a = 1 //работает
console.log(obj.a)
//obj = 5 //вызывает ошибку

In a constant obj, during initialization, a new empty object is written. Attempting to access its property a, which does not exist, does not cause an error. In the console falls undefined. After that, we add a new property to the object and try to access it again. This time the value of this property gets to the console 1. If you uncomment the last line of the example, an attempt to execute this code will result in an error.

A keyword is constvery similar to let, in particular, it has a block scope.

In modern conditions it is quite acceptable to use for the declaration of all entities whose values ​​are not planned to change, the keyword const, resorting toletonly in special cases. Why? The thing is that it is best to strive to use the simplest available designs as possible in order not to complicate the program and avoid mistakes.

Data types


JavaScript is sometimes called "untyped" language, but this does not correspond to the real state of affairs. True, you can write values ​​of different types to variables, but there are data types in JavaScript, after all. In particular, we are talking about primitive and object data types.

In order to determine the data type of a certain value, you can use the operator typeof. It returns a string indicating the type of the operand.

Ри Primitive data types


Here is a list of primitive JavaScript data types:

  • number (number)
  • string (line)
  • boolean (logical value)
  • null(special value null)
  • undefined(special value undefined)
  • symbol (symbol, used in special cases, appeared in ES6)

Here, the data type names are given in the form in which the operator returns them typeof.

Let's talk about the most commonly used data types from this list.

Type number


Type values numberin JavaScript are represented as 64-bit double-precision floating-point numbers.

In the code, numeric literals are represented as integers and fractional numbers in the decimal number system. To write numbers you can use other methods. For example, if at the beginning of a numeric literal there is a prefix 0x- it is perceived as a number written in hexadecimal notation. Numbers can also be written in the exponential representation (you can find a letter in such numbers e).

Here are examples of writing integers:

10
5354576767321
0xCC // шестнадцатеричное число

Here are fractional numbers.

3.14
.1234
5.2e4 //5.2 * 10^4

Numeric literals (this behavior is also characteristic of some other primitive types), when attempting to refer to them as objects, automatically, for the duration of the operation, are transformed into corresponding objects, which are called “object wrappers”. In this case, we are talking about the object wrapper Number.

Here, for example, looks like an attempt to access a variable athat contains a numeric literal as an object in the Google Chrome console.


Object wrapper hint Number

If, for example, you use the method of antoString()object of a typeNumber, it will return a string representation of the number. The corresponding command that can be executed in the browser console (and in the usual code) looks like this:

a.toString()

Notice the double brackets after the method name. If you do not put them, the system will not give an error, but instead of the expected output, the console will have something completely different from the string representation of the number 5. The

global object Numbercan be used as a constructor, creating new numbers with it (though in this form it is almost never used), it can be used as an independent entity, without creating instances of it (that is, some numbers represented with its help). For example, its property Number.MAX_VALUEcontains the maximum numeric value that can be represented in JavaScript.

Type string


Type values stringare sequences of characters. Such values ​​are specified as string literals enclosed in single or double quotes.

'A string'
"Another string"

String values ​​can be broken down into multiple parts using the backslash (backslash) character.

"A \
string"

A string can contain so-called escape sequences interpreted when a string is output to the console. For example, a sequence \nmeans a newline character. The backslash character can also be used to add quotes to strings enclosed in the same quotes. Escaping the quotation character with the help of the system \leads to the fact that the system does not perceive it as a special character.

'I\'m a developer'

Strings can be concatenated using an operator +.

"A " + "string"

Pattern Literals


In ES2015, the so-called patterned literals, or patterned strings, appeared. They are strings enclosed in backquotes ( `) and have some interesting properties.

`a string`

For example, you can substitute certain values ​​in template literals that are the result of evaluating JavaScript expressions.

`a string with ${something}`
`a string with ${something+somethingElse}`
`a string with ${obj.something()}`

Using back quotes simplifies multi-line writing of string literals:

`a string
with
${something}`

Type boolean


In JavaScript, there are a couple of reserved words used when working with logical values ​​— this is true(true) and false(false). Comparison operations, such as ==, ===, <, >, recycled trueor false.

Logical expressions are used in constructions like ifand whileby helping to control the course of program execution.

It should be noted that where the expected value trueor false, you can use other values ​​that are automatically regarded by the language as true (truthy) or false (falsy).

In particular, the false values ​​are the following:

0
-0
NaN
undefined
null
'' //пустая строка

The remaining values ​​are true.

Type null


JavaScript has a special value nullthat indicates the absence of a value. Similar values ​​are used in other languages.

Type undefined


A value undefinedwritten to a variable indicates that the variable is not initialized and has no value for it.

This value is automatically returned from functions whose result is not explicitly returned, using a keyword return. If the function accepts a parameter, which, when called, is not specified, it is also set to undefined.

In order to check the value on undefined, you can use the following construction.

typeof variable === 'undefined'

▍Objects


All values ​​that are not primitive have an object type. We are talking about functions, arrays, what we call "objects", and many other entities. The basis of all these types of data is the type object, and they, although in many ways different from each other, have much in common.

Expressions


Expressions are fragments of code that can be processed and obtained on the basis of the performed calculations a certain value. There are several categories of expressions in JavaScript.

Arithmetic expressions


Expressions fall into this category, the result of which are the numbers.

1 / 2
i++
i -= 2
i * 2

String expressions


The result of evaluating such expressions is strings.

'A ' + 'string'
'A ' += 'string'

Primary expressions


Literals, constants, references to identifiers fall into this category.

2
0.02
'something'
true
false
this //контекст выполнения, ссылка на текущий объект
undefined
i //где i является переменной или константой

This also includes some key words and JavaScript constructs.

function
class
function* //генератор
yield //команда приостановки/возобновления работы генератора
yield* //делегирование другому итератору или генератору
async function* //асинхронное функциональное выражение 
await //организация ожидания выполнения асинхронной функции
/pattern/i //регулярное выражение
() //группировка

Array and Object Initialization Expressions


[] //литерал массива
{} //объектный литерал
[1,2,3]
{a: 1, b: 2}
{a: {b: 1}}

Boolean expressions


In logical expressions, logical operators are used, the result of their calculation is logical values.

a && b
a || b
!a

Property Access Expressions


These expressions allow you to access the properties and methods of objects.

object.property //обращение к свойству (или методу) объекта
object[property]
object['property']

Object creation expressions


new object()
new a(1)
new MyRectangle('name', 2, {a: 4})

Function Declaration Expressions


function() {}
function(a, b) { return a * b }
(a, b) => a * b
a => a * 2
() => { return 2 }

Call expressions


Such expressions are used to call functions or methods of objects.

a.x(2)
window.resize()

Work with objects


Above, we have already encountered objects, talking about object literals, calling their methods, accessing their properties. Here we will talk about objects in more detail, in particular, we will consider the mechanism of prototype inheritance and the use of a keyword class.

Рот Prototype inheritance


JavaScript stands out among modern programming languages ​​in that it supports prototype inheritance. Most object-oriented languages ​​use a class-based inheritance model.

Each JavaScript object has a special property ( __proto__) that points to another object that is its prototype. The object inherits the properties and methods of the prototype.

Suppose we have an object created using an object literal.

const car = {}

Or we created an object using a constructor Object.

const car = new Object()

In any of these cases, the prototype of the object carwill be Object.prototype.

If you create an array, which is also an object, its prototype will be an object Array.prototype.

const list = []
//или так
const list = new Array()

You can check this as follows.

car.__proto__ == Object.prototype //true
car.__proto__ == new Object().__proto__ //true
list.__proto__ == Object.prototype //false
list.__proto__ == Array.prototype //true
list.__proto__ == new Array().__proto__ //true

Here we used the property __proto__, it does not have to be available to the developer, but you can usually access it. It should be noted that a more reliable way to obtain a prototype of an object is to use the method of a getPrototypeOf()global object Object.

Object.getPrototypeOf(new Object())

All properties and methods of the prototype are available to the object that has this prototype. Here, for example, how their list for an array looks.


Array Hint

The basic prototype for all objects isObject.prototype.

Array.prototype.__proto__ == Object.prototype

The Object.prototypeprototype does not.

What we saw above is an example of a chain of prototypes.

When trying to access a property or a method of an object, if there is no such property or method of the object itself, they are searched in its prototype, then in the prototype prototype, and so on until the required one is found, or until the prototype chain is not over.

In addition to creating objects using the operator newand applying object literals or array literals, you can create an instance of an object using a method Object.create(). The first argument passed to this method is the object that will become the prototype of the object created with it.

const car = Object.create(Object.prototype)

You can check if a certain object is in the prototype chain of another object using the method isPrototypeOf().

const list = []
Array.prototype.isPrototypeOf(list)

Constructor functions


Above, we created new objects using the constructor functions already existing in the language (when they are called, the keyword is used new). Such functions can be created independently. Consider an example.

function Person(name) {
  this.name = name
}
Person.prototype.hello = function() {
  console.log(this.name)
}
let person = new Person('Flavio')
person.hello()
console.log(Person.prototype.isPrototypeOf(person))

Here we create a constructor function. When it is called, a new object is created, to which the keyword points thisin the body of the constructor. We add a property to this object nameand write into it what is passed to the constructor. This object is returned from the constructor automatically. With the help of the constructor function, you can create a set of objects, the properties of namewhich will contain what is passed when they are created to the constructor.

After creating the constructor, we add a function to its prototype, which will output to the console the value of the property of an nameobject created using this function. All objects created using this constructor will have the same prototype, and therefore use the same function.hello(). It is easy to check this by creating another object of the type Personand comparing its function hello()with the function of the object already in the example (the name of the function in this case is written without brackets).

▍Classes


In the ES6 standard in JavaScript came such a thing as "class".

Prior to that, JavaScript could only use the above-described prototype inheritance mechanism. This mechanism looked unusual for programmers who came to JS from other languages. Therefore, classes appeared in the language, which, in essence, are “syntactic sugar” for the prototype mechanism of inheritance. That is, objects created in the traditional way, and objects created using classes, have prototypes.

Class declaration


This is what the class declaration looks like.

class Person {
  constructor(name) {
    this.name = name
  }
  hello() {
    return 'Hello, I am ' + this.name + '.'
  }
}

The class has an identifier that can be used to create new objects using the construct new ClassIdentifier().

When creating a new object, a method is called constructorand parameters are passed to it.

In a class, you can declare methods. In our case hello(), this is the method that all objects created on the basis of the class can call. This is how a new object is created using a class Person.

const flavio = new Person('Flavio')
flavio.hello()

Class Based Inheritance


Classes can extend other classes. Objects created on the basis of such classes will inherit both the methods of the original class and the methods defined in the extended class.

If a class that extends another class (the successor of this class) has a method whose name matches that of the parent class, this method takes precedence over the original one.

class Programmer extends Person {
  hello() {
    return super.hello() + ' I am a programmer.'
  }
}
const flavio = new Programmer('Flavio')
flavio.hello()

When calling a method hello()in the above example, the string will be returned Hello, I am Flavio. I am a programmer.

The classes do not provide for the presence of variables (properties), the properties created using the classes of objects must be configured in the constructor.

Inside a class, you can access the parent class using a keyword super.

Static methods


The methods described in the class can be invoked by referring to objects created on the basis of this class, but not to the class itself. Static ( static) methods can be called by referring directly to the class.

Private methods


There is no built-in mechanism in JavaScript that allows declaring private (private, private) methods. This limitation can be circumvented, for example, by using closures.

Getters and Setters


In a class, you can describe methods by prefixing them with keywords getor set. This allows you to create so-called getters and setters - functions that are used to control access to the properties of objects created on the basis of the class. The getter is called when trying to read the value of a pseudo-property, and the setter is called when trying to write a new value to it.

class Person {
    constructor(name) {
      this.userName = name
    }
    set name(value) {
      this.userName = value
    }
    get name() {
      return this.userName
    }
  }

Results


In this article we talked about variables, data types, expressions, and working with objects in JavaScript. The topic of our next material will be features.

Dear readers! If you have been writing to JS for a long time, please tell us how you feel about the appearance of the keyword class in the language.


Also popular now: