-
Notifications
You must be signed in to change notification settings - Fork 687
Добавляет доку "Базовые операторы в JS" #5709
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
anton-fomichev
wants to merge
16
commits into
doka-guide:main
Choose a base branch
from
anton-fomichev:article/operators
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 11 commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
755b70a
Добавит /people/anton-fomichev
anton-fomichev 2e0d412
Добавит черновик статьи
anton-fomichev 6d9338e
Отредактирует статью, сократит размер до 7 минут
anton-fomichev 0553dd8
Удалит комментарий из статьи
anton-fomichev a55f864
Отредактирует статью, расставит акценты
anton-fomichev f056adb
Изменит description
anton-fomichev 6d09904
Уберет упоминание объектов, добавит секцию "Приведение к числу"
anton-fomichev 1907f5d
Добавит скрытую секцию "Как работают операторы по спецификации ECMASc…
anton-fomichev eeec9d9
Пофиксит стиль написания
anton-fomichev 53a55db
Переместит "Как работают операторы по спецификации ECMAScript"
anton-fomichev f8e9e88
Покажет на примере, как `+` работает по спеке ECMAScript
anton-fomichev 53425ad
Перепишет "Как выполнение операторов описывает спецификация ECMAScript"
anton-fomichev c563822
Объединит секции внутри "Не только математика"
anton-fomichev b62530a
Добавляет доку в индекс JS
vitya-ne a29b48e
Ставит точку в дискришине
vitya-ne f3008a9
Добавит "related" и удалит "keywords"
anton-fomichev File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,320 @@ | ||
--- | ||
title: "Базовые операторы в JS" | ||
description: "Обзор ключевых операторов JavaScript: арифметика, приоритет, инкремент и декремент, присваивание" | ||
authors: | ||
- anton-fomichev | ||
keywords: | ||
- | ||
related: | ||
- | ||
tags: | ||
- doka | ||
--- | ||
|
||
## Кратко | ||
|
||
В JavaScript есть несколько базовых операторов, с которыми разработчики сталкиваются постоянно в ходе своей работы. Они позволяют выполнять арифметические действия, изменять значения переменных, а также помогают разработчику упростить некоторые операции в коде. | ||
|
||
## Кто такие: «оператор», «операнд»? | ||
|
||
- **Оператор** — символ (или ключевое слово), говорящий движку, какую операцию совершить | ||
|
||
- **Операнд** — это то, над чем оператор выполняет действие (например: число, строка, переменная) | ||
|
||
## Типы операторов | ||
|
||
### Унарные операторы | ||
|
||
Унарные операторы зависят от одного операнда. Другими словами, они действуют только на один объект. | ||
|
||
Пример — _унарный минус_ `-`: | ||
|
||
```js | ||
anton-fomichev marked this conversation as resolved.
Show resolved
Hide resolved
|
||
let x = 5 | ||
console.log(-x) | ||
// -5 | ||
``` | ||
|
||
### Бинарные операторы | ||
|
||
Бинарные операторы применяются к двум операндам. | ||
|
||
Например, оператор `+` применяется к операндам `x` и `y`: | ||
|
||
```js | ||
const x = 5, y = 2 | ||
console.log(x + y) | ||
// 7 | ||
``` | ||
|
||
Рассмотрим другой пример: оператор `>` сравнивает числа и возвращает значение логического типа: | ||
|
||
```js | ||
const user = { age: 19 } | ||
console.log(user.age > 18) | ||
// true | ||
``` | ||
|
||
## Математика | ||
|
||
JavaScript поддерживает стандартные арифметические операторы, которые помогают складывать, вычитать, умножать и делить числа. Ниже перечислены самые популярные из них: | ||
|
||
### Сложение, вычитание, умножение и деление | ||
|
||
```js | ||
console.log(10 + 3) | ||
// 13 | ||
console.log(10 - 3) | ||
// 7 | ||
console.log(10 * 3) | ||
// 30 | ||
console.log(10 / 3) | ||
// 3.3333... | ||
console.log(10 - 'blablabla') | ||
// NaN | ||
``` | ||
|
||
### Остаток от деления | ||
|
||
```js | ||
console.log(10 % 3) | ||
// 1 | ||
console.log(8 % 2) | ||
// 0 | ||
``` | ||
|
||
### Возведение в степень | ||
|
||
```js | ||
console.log(2 ** 2) | ||
// 4 | ||
console.log(2 ** 5) | ||
// 32 | ||
``` | ||
|
||
## Не только математика | ||
|
||
anton-fomichev marked this conversation as resolved.
Show resolved
Hide resolved
|
||
JavaScript позволяет применять операторы не только к числам — на практике можно встретить ситуации, когда один или оба операнда оказываются строками, булевыми значениями или даже объектами. | ||
|
||
<details> | ||
<summary>Как JavaScript обрабатывает оператор <code>+</code> по спецификации ECMAScript</summary> | ||
anton-fomichev marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
Рассмотрим принцип работы операции [ApplyStringOrNumericBinaryOperator()](https://tc39.es/ecma262/multipage/ecmascript-language-expressions.html#sec-applystringornumericbinaryoperator) на примере оператора `+`: | ||
anton-fomichev marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
**1. Приведение к примитивам** | ||
Оба операнда последовательно приводятся к примитивам с помощью [ToPrimitive()](https://tc39.es/ecma262/multipage/abstract-operations.html#sec-toprimitive). | ||
anton-fomichev marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
**2. Проверка на строку** | ||
Если хотя бы один из операндов — строка, то второй операнд будет приведён к строке и результатом операции будет конкатенация: | ||
|
||
```js | ||
console.log(5 + '2') | ||
// '52' | ||
``` | ||
|
||
В противном случае операция рассматривается как арифметическая. | ||
|
||
**3. Приведение к Number или BigInt** | ||
JavaScript применяет [ToNumeric()](https://tc39.es/ecma262/multipage/abstract-operations.html#sec-tonumeric) к обоим операндам. | ||
|
||
**4. Проверка на несовместимость** | ||
Если один операнд оказался Number, а другой — BigInt, будет выброшена ошибка TypeError: | ||
|
||
```js | ||
42n + 1 // TypeError: Cannot mix BigInt and other types, use explicit conversions | ||
``` | ||
|
||
**5. Арифметические действия** | ||
Если оба операнда — Number, используется [Number::add](https://tc39.es/ecma262/multipage/ecmascript-data-types-and-values.html#sec-numeric-types-number-add). Если оба операнда оказываются BigInt, вызывается [BigInt::add](https://tc39.es/ecma262/multipage/ecmascript-data-types-and-values.html#sec-numeric-types-bigint-add): | ||
|
||
```js | ||
console.log(2 + 3) | ||
// 5 | ||
console.log(2n + 3n) | ||
// 5n | ||
``` | ||
|
||
</details> | ||
|
||
anton-fomichev marked this conversation as resolved.
Show resolved
Hide resolved
|
||
### Конкатенация строк | ||
|
||
Если хотя бы один операнд у оператора `+` — строка, в результате получится склейка (конкатенация). Например: | ||
|
||
```js | ||
console.log('Hello' + ' ' + 'world') | ||
// 'Hello world' | ||
console.log('5' + 2) | ||
// '52' | ||
``` | ||
|
||
### Сравнение строк | ||
|
||
Операторы сравнения, такие как `>` или `<`, могут применяться к строкам. При этом строки сравниваются _лексикографически_ — посимвольно в порядке символов, а не по их «числовому» содержанию. | ||
|
||
Следующее выражение возвращает `true` после сравнения первых символов строк `'2'` и `'15'` — `'2'` и `'1'`: | ||
|
||
```js | ||
console.log('2' > '15') | ||
// true | ||
``` | ||
|
||
Каждому символу соответствует код из [UTF-16](https://ru.wikipedia.org/wiki/UTF-16), с помощью которого и происходит сравнение двух символов. | ||
|
||
### Приведение к числу | ||
|
||
Во время выполнения арифметических операций JavaScript пытается преобразовать операнды к числу. | ||
|
||
Например, при использовании оператора `-` со строкой: | ||
|
||
```js | ||
let x = '10' | ||
console.log(x - 1) | ||
// 9, строка '10' привелась к числу 10 | ||
``` | ||
|
||
Также существует унарный плюс `+`, который явно превращает строку в число: | ||
|
||
```js | ||
console.log(+'42') | ||
// 42 | ||
``` | ||
|
||
Подробнее о том, как JavaScript преобразует строки, объекты и другие типы данных, можно посмотреть в статье [преобразование типов](/js/typecasting/). | ||
|
||
### Преобразование объектов | ||
|
||
При попытке использовать арифметические операторы вроде `+`, `-` или `*` с объектами или массивами, JavaScript попытается привести их к примитиву через метод `toString()` или `valueOf()`. Иногда это приводит к результатам, которые сложно предсказать, если не знать механизма преобразований: | ||
|
||
```js | ||
console.log({} + {}) | ||
// '[object Object][object Object]' | ||
|
||
// В массиве по умолчанию toString() склеивает элементы: | ||
console.log([1, 2, 3] + [4, 5]) | ||
// '1,2,34,5' | ||
``` | ||
|
||
### Булевые значения | ||
anton-fomichev marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
В арифметическом контексте `true` приводится к `1`, а `false` — к `0`. Однако при конкатенации строк (`+`) булевые значения не будут автоматически превращаться в числа: | ||
|
||
```js | ||
console.log(true + 1) | ||
// 2 | ||
console.log(false + 10) | ||
// 10 | ||
console.log(true + '1') | ||
// 'true1' | ||
``` | ||
|
||
## Приоритет операторов | ||
|
||
В JavaScript у операторов есть определённый порядок выполнения. Это означает, что некоторые операции будут выполняться раньше других, если в выражении нет дополнительных скобок. | ||
|
||
Приоритет _унарных_ операторов выше, чем приоритет _бинарных_ (за некоторыми исключениями: оператор группировки, вызов функции, доступ к свойствам и т. п.). Подробнее можно посмотреть в [таблице приоритетов](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Operators/Operator_precedence#таблица). | ||
|
||
На практике запоминать приоритет всех операторов не нужно: в спорных случаях всегда лучше проставить скобки явно. | ||
|
||
### Присваивание | ||
|
||
Оператор присваивания `=` в JavaScript находится почти в самом низу приоритетов. Его суть проста: взять значение выражения справа и присвоить переменной слева. Например: | ||
|
||
```js | ||
const result = 10 | ||
``` | ||
|
||
Важно, что оператор присваивания возвращает значение, которое было присвоено переменной: | ||
|
||
```js | ||
let a | ||
console.log(a = 'Hello world!') | ||
// 'Hello world!' | ||
``` | ||
|
||
Оператор присваивания выполняется справа налево. В примере ниже, сначала выполнится `b = 5`, вернётся `5`, а затем значение присвоится `a`. В итоге `a` и `b` оба станут равны `5`: | ||
|
||
```js | ||
let a, b | ||
console.log(a = b = 5) | ||
// 5 | ||
console.log(a, b) | ||
// 5 5 | ||
``` | ||
|
||
#### Как делать не надо | ||
|
||
Иногда можно увидеть слишком хитрые конструкции, где в одном выражении смешиваются разные операторы, в том числе присваивания. Например: | ||
|
||
```js | ||
const a = 2 + (b = 3 * 5) // a = 17, b = 15 | ||
``` | ||
|
||
Такой код работает, но его сложно читать и поддерживать, особенно если в нём участвуют более сложные вычисления. В большинстве случаев лучше разбить логику на несколько строк — так понятнее и надёжнее: | ||
|
||
```js | ||
const b = 3 * 5 // 15 | ||
const a = 2 + b // 17 | ||
``` | ||
|
||
### Инкрементное присваивание | ||
|
||
Помимо обычного оператора `=`, в JavaScript есть целая группа _сокращённых операторов присваивания_. Они позволяют одновременно выполнить арифметическую операцию и присвоить результат переменной. Например: | ||
|
||
- `x += 1` эквивалентно `x = x + 1`; | ||
- `x -= 2` эквивалентно `x = x - 2`; | ||
- `x *= 3` эквивалентно `x = x* 3`; | ||
- `x /= 4` эквивалентно `x = x / 4`; | ||
- `x %= 5` эквивалентно `x = x % 5`; | ||
- `x **= 6` эквивалентно `x = x ** 6`. | ||
|
||
Зачем это нужно? | ||
|
||
1. **Короткая запись**. Вместо `x = x + 10` можно использовать `x += 10`; | ||
1. **Удобство при изменении счётчика**. В циклах или при пошаговом изменении переменной такие записи упрощают код и делают его немного выразительнее. | ||
|
||
vitya-ne marked this conversation as resolved.
Show resolved
Hide resolved
|
||
## Инкремент и декремент | ||
|
||
Инкремент и декремент — это унарные операторы, которые увеличивают или уменьшают значение переменной на `1`. Выглядят они так: | ||
|
||
- **Инкремент**: `++`, | ||
- **Декремент**: `--`. | ||
|
||
При этом существует две формы — _префиксная_ и _постфиксная_. Они отличаются моментом, когда переменная меняет своё значение. | ||
|
||
### Постфиксная форма | ||
|
||
Постфиксные операторы (`x++`, `x--`) сначала **возвращают старое значение**, а лишь затем меняют переменную: | ||
|
||
```js | ||
let x = 5 | ||
console.log(x++) | ||
// 5 (возвращаем старое значение) | ||
console.log(x) | ||
// 6 (теперь переменная увеличена) | ||
``` | ||
|
||
### Префиксная форма | ||
|
||
Префиксные операторы (`++x`, `--x`) сначала изменяют переменную, а затем **возвращают новое значение**: | ||
|
||
```js | ||
let count = 5 | ||
console.log(++count) | ||
// 6 (значение уже увеличено) | ||
console.log(count) | ||
// 6 (значение остаётся увеличенным) | ||
``` | ||
|
||
### Когда использовать | ||
|
||
Инкремент и декремент нередко применяют в циклах `for` или `while`, чтобы удобнее управлять переменными-счётчиками. Вывод чисел от 0 до 4 (включительно) в консоль может выглядеть так: | ||
|
||
```js | ||
for (let i = 0; i < 5; i++) { | ||
console.log(i) | ||
} | ||
``` | ||
|
||
### Подводные камни | ||
|
||
Чаще всего проблемы в использовании инкремента или декремента в JavaScript связаны с особенностями постфиксной или префиксной формы. Если не помните, когда возвращается старое значение, а когда новое, лучше используйте отдельные инструкции присваивания. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
--- | ||
name: 'Антон Фомичев' | ||
url: https://github.com/anton-fomichev | ||
photo: photo.jpeg | ||
--- | ||
|
||
Разрабатываю и оптимизирую фронтенд с 2021 года. Уделяю особое внимание UX. Для меня важно не стоять на месте: экспериментирую с технологиями, делюсь знаниями в open source сообществе 🤝 |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Может быть, второе слово "разработчик" убрать? мне кажется, по контексту понятно, что речь идёт о разработчике.