Expressive JavaScript: Values, Types, and Operators

Original author: Marijn Haverbeke
  • Transfer

Content




A program moves below the surface of the machine. Without effort, it expands and contracts. Being in great harmony, the electrons scatter and collect. The forms on the monitor are just ripples in the water. The essence remains hidden inside ...

Master Ewan-Ma, Programming Book


In the computer world there is only data. You can read data, change data, create new ones - but there is nothing besides data. All data is stored as long sequences of bits, which is why they are similar to each other.

Bits are entities with two states, usually described as zeros and ones. In a computer, they live in the form of high and low electric charges, a strong or weak signal, or a shiny and matte area on the surface of a CD. Each piece of information can be represented as a sequence of zeros and ones, that is, a bit.

For example, number 13. Instead of a decimal system consisting of 10 digits, you have a binary system with two digits. The value of each position of the number doubles when moving from right to left. The bits making up the number 13, together with their weights:

0   0   0   0 1 1 0 1
128 64 32  16 8 4 2 1


It turns out the binary number 00001101, or 8 + 4 + 1, which is 13.

Quantities.


Imagine an ocean of bits. A typical modern computer stores more than 30 billion bits in RAM. Permanent memory (hard disk) is usually a couple more orders of magnitude larger.


To work with them and not get lost, you can divide them into pieces representing units of information. In JavaScript, these units are called quantities. All their values ​​consist of bits, but play different roles. Each quantity has a type that determines its role. There are six main types in total: numbers, strings, Boolean values, objects, functions, and indefinite values.

To create a value, you need to specify its name. It's comfortable. You do not need to collect building materials or pay for them. You just need to call - and op-pa, you're done. They are not created from the air - each value is stored somewhere, and if you want to use a huge number of them, you may run out of bits. Fortunately, this is only if you all need them at the same time. When you do not need a quantity, it dissolves, and the bits used by it are sent to processing as building material for new quantities.

In this chapter, we introduce the atoms of JavaScript programs — the simple types of variables and the operators that apply to them.

The numbers


Values ​​of numerical types, this is a surprise - numbers. In a JavaScript program, they are written as

13


Use this entry in a program and it will invoke a string of bits representing 13 in computer memory.

JavaScript uses a fixed number of bits (64) to store numerical values. The number of quantities that can be expressed using 64 bits is limited - that is, the numbers themselves are also limited. For N decimal digits, the number of numbers that they can be written is 10 to the power of N. Similarly, 64 bits can be expressed 2 to 64 degrees of numbers. This is quite a lot.

Previously, computers had less memory, and then groups of 8 or 16 bits were used to store numbers. It was easy to accidentally exceed the maximum number for such small numbers - that is, use a number that did not fit in this set of bits. Today, computers have a lot of memory, you can use pieces of 64 bits, and so you need to worry about this only if you work with astronomical numbers.

True, not all numbers less than 2 ^ 64 fit into a JavaScript number. Negative numbers are also stored in these bits - therefore, one bit stores the sign of the number. In addition, we need to be able to store fractions. To do this, part of the bit is used to store the position of the decimal point. The real maximum for numbers is approximately 10 ^ 15, which in general is still pretty much.

Fractions are recorded using a dot.

9.81


Very large or small numbers are written in scientific notation with the letter “e” (exponent), followed by the degree:

2.998e8


This is 2.998 × 10 ^ 8 = 299800000.

Calculations with integers (also called integer) less than 10 ^ 15 are guaranteed to be accurate. Fraction calculations are usually not. Just as the number π (pi) cannot be represented exactly with a finite number of digits, so many fractions cannot be represented in the case when we have only 64 bits. Bad, but it gets in the way in very specific cases. It is important to keep this in mind and treat fractions as approximate values.

Arithmetic


The main thing that can be done with numbers is arithmetic calculations. Additions and multiplications use two numbers and give out the third. How this is written in JavaScript:

100 + 4 * 11


The symbols + and * are called operators. The first is addition, the second is multiplication. We place the operator between two quantities and get the value of the expression.

But in the example it turns out “add 4 and 100 and then multiply the result by 11” or is the multiplication performed first? As you might have guessed, multiplication is done first. But as in mathematics, this can be changed using brackets:

(100 + 4) * 11


The operator - is used for subtraction, and - / for division -

When operators are used without parentheses, the order of their execution is determined by their priority. The * and / operators have the same priority, higher than the + and - operators, which are equal in priority. When calculating operators with equal priority, they are calculated from left to right:

1 - 2 + 1

calculated as (1 - 2) + 1

So far, no worries about priorities. If in doubt, use parentheses.

There is another operator that you will not immediately recognize. The% symbol is used to get the remainder. X% Y is the remainder of dividing X by Y. 314% 100 gives 14, and 144% 12 gives 0. The operator has the same priority as multiplication and division. It is often called “modulo division”, although more correctly “with remainder”.

Special numbers


JavaScript has three special meanings that are considered numbers, but do not behave like regular numbers.

These are Infinityand -Infinitywhich represent positive and negative infinities. Infinity - 1 = Infinity, and so on. Do not rely heavily on calculations with infinities; they are not too strict.

The third number: NaN. Denotes “not a number”, although this is a value of a numeric type. You can get it after calculations like 0/0, Infinity - Infinity, or other operations that do not lead to accurate meaningful results.

Lines


The next basic data type is strings. They are used to store text. They are written in quotation marks:

“Что посеешь, то из пруда”
‘Баба с возу, потехе час’


You can use both double and single quotes - the main thing is to use them together. You can enclose almost everything in quotation marks and make a string out of it. But some characters cause problems. For example, it is difficult to enclose quotation marks in quotation marks. A line feed cannot also be simply enclosed in them - a line must go on one line.

To enclose special characters, use the backslash \. It means that the character following it has a special meaning - this is called "escape character" (escape character). \ ”Can be enclosed in double quotes. \ n stands for line feed, \ t stands for tabulation.

The line “Between the first and second \ n the character will be small” will actually look like this:

Между первой и второй
символ будет небольшой


If you need to include a backslash in the string, you also need to escape it: \\. The instruction “A newline character is“ \ n ”” will need to be written like this:

"Символ новой строки – это \"\\n\""


Lines cannot be divided, multiplied, or added. However, you can use the + operator with them, which will connect them to each other. The following expression will produce the word “connection”:

"сое" + "ди" + "н" + "ение"


There are many ways to manipulate strings, which we will discuss in chapter 4.

Unary operators


Not all operators are written in characters - some in words. One such operator is typeofone that gives the name of the type of quantity to which it is applied.

console.log(typeof 4.5)
// → number
console.log(typeof "x")
// → string


We will use the call console.login the examples when we want to see the result on the screen. How exactly the result will be returned depends on the environment in which you run the script.

Previous operators worked with two values, however typeof uses only one. Operators working with two quantities are called binary, and with one - unary. Minus (subtraction) can be used both as unary and as binary.

console.log(- (10 - 2))
// → -8


Boolean values


Often you need a value that simply shows one of two possibilities - such as “yes” and “no”, or “on” and “off”. To do this, JavaScript has a Boolean type, which has only two values ​​- trueand false(true and false).

Comparisons


One way to get Boolean values:

console.log(3 > 2)
// → true
console.log(3 < 2)
// → false


The signs <and> traditionally mean less and more. These are binary operators. As a result of their use, we get a Boolean value that shows whether the inequality is true.

Strings can be compared in the same way:

console.log("Арбуз" <  "Яблоко")
// → true


Strings are compared alphabetically: upper case letters are always “less” than lower case letters. The comparison is based on the Unicode standard. This standard assigns a number to almost any character from any language. When comparing strings, JavaScript goes through their characters from left to right, comparing the number codes of these characters.

Other similar operators are> = (greater than or equal to), <= (less than or equal to), == (equal to),! = (Not equal).

console.log("Хочется" != "Колется")
// → true


JavaScript has only one value that is not equal to itself - NaN("not a number").

console.log(NaN == NaN)
// → false


NaN is the result of any meaningless calculation, so it is not equal to the result of some other meaningless calculation.

There are operations that can be performed with the Boolean values ​​themselves. JavaScript supports three logical operators: and, or, no.

The && operator is a logical "and." It is binary, and its result is true only if both quantities to which it is applied are also true.

console.log(true && false)
// → false
console.log(true && true)
// → true


Operator || - logical "or". Returns true if one of the values ​​is true.

console.log(false || true)
// → true
console.log(false || false)
// → false


“No” is written using the exclamation mark “!”. This is a unary operator that reverses a given value. ! true is false,! false is true.

When using logical and arithmetic operators, it is not always clear when parentheses are needed. In practice, you can handle this by knowing that || priority is lower than everyone, then comes &&, then comparison operators, then everyone else. This order was chosen so that in expressions like the following one could use brackets to a minimum:

1 + 1 == 2 && 10 * 10 > 50


The last logical operator is not unary or binary - it is triple. It is written using a question mark and a colon:

console.log(true ? 1 : 2);
// → 1
console.log(false ? 1 : 2);
// → 2


This is a conditional operator in which the value to the left of the question mark selects one of two values ​​separated by a colon. When the value on the left is true, select the first value. When false, the second.

Undefined Values


There are two special values, null and undefined, which are used to indicate the absence of a meaningful value. By themselves, they carry no information.

Many statements that do not return values ​​return undefined simply to return something. The difference between undefined and null appeared in the language by accident, and usually does not matter.

Automatic type conversion


Earlier, I mentioned that JavaScript allows you to execute any, sometimes very strange programs. For example:

console.log(8 * null)
// → 0
console.log("5" - 1)
// → 4
console.log("5" + 1)
// → 51
console.log("пять" * 2)
// → NaN
console.log(false == 0)
// → true


When an operator is applied to the “wrong” type of values, JavaScript silently converts the value to the desired type using a set of rules that do not always meet your expectations. This is called coercion. In the first expression, null turns into 0, and “5” becomes 5 (from a string to a number). However, in the third expression, + concatenates (concatenates) the strings, which is why 1 is converted to “1 '(from a number to a string).

When something non-obvious turns into a number (for example, “five” or undefined), the value NaN is returned. Subsequent arithmetic operations with NaN again receive NaN. If you get this value, look for where the random type conversion happened.

When comparing values ​​of the same type with ==, it is easy to predict that you should get true if they are the same (except in the case of NaN). But when the types are different, JavaScript uses a complex and confusing set of rules for comparisons. Usually he tries to convert the type of one of the quantities into the type of the other. When null or undefined occurs on one side of the statement, it returns true if both sides are null or undefined.

console.log(null == undefined);
// → true
console.log(null == 0);
// → false


The last example demonstrates a useful trick. When you need to check if a value has a real value instead of null or undefined, you simply compare it with null with == or! =.

But what if you need to compare something with the exact value? The rules for converting types to Boolean values ​​say that 0, NaN, and the empty string “” are considered false, and all others are true. Therefore, 0 == false and “” == false. In cases where you do not need automatic type conversion, you can use two more operators: === and! ==. The first verifies that the two values ​​are absolutely identical, the second - vice versa. And then the comparison “” === false returns false.

I recommend using the three-character comparison operators to protect against unexpected type conversions, which can lead to unpredictable consequences. If you are sure that the types of compared values ​​will match, you can safely use short operators.

Short calculation of logical operators


Logical operators && and || work with quantities of different types in a very strange way. They convert the value on the left side of the operator to the Boolean one to understand what to do next, but depending on the operator and the result of this conversion, they either return the original value from the left or right side.

For example, || will return the value on the left side, when it can be converted to true - otherwise it will return the right side.

console.log(null || "user")
// → user
console.log("Karl" || "user")
// → Karl


Such an operator || allows you to use it as a rollback to the default value. If you give it an expression that can return an empty value on the left, then the value on the right will serve as a replacement for this case.

The && operator works in a similar way, but vice versa. If the value on the left is converted to false, it returns that value, and otherwise, the value on the right.

Another important property is that the expression on the right side is calculated only if necessary. In case of true || X does not matter what X is equal to. Even if it is some kind of terrible expression. The result is always true and X is not calculated. False && X also works - X is simply ignored. This is called short calculation.

The condition statement works the same way. The first expression is always calculated, and from the second and third values ​​- only the one that is selected as a result.

Total


We looked at four types of JavaScript values: numbers, strings, Boolean, and undefined.

These values ​​are obtained when we write their names (true, null) or values ​​(13, “eprst”). They can be combined and modified using operators. For arithmetic, there are binary operators (+, -, *, /, and%), string concatenation (+), comparison (==,! =, ===,! ==, <,>, <=,> =) , and logical operators (&&, ||), as well as several unary operators (- for a negative value ,! for logical negation, and typeof for determining the type of quantity).

This knowledge allows you to use JavaScript as a calculator, but nothing more. In the next chapter, we will bind these simple meanings together to make simple programs.

Also popular now: