Skip to content

Commit ac01740

Browse files
feyclaude
andcommitted
feat(45-logic): port theory from Python, add string-comparison lesson
- 10-bool-type: расширена теория (операции сравнения, ===/!==, предикаты isInfant/isNegative); - 28-logical-negation: добавлены комбинирование с &&/||, приоритет, скобки, пример canDrive, законы де Моргана (not→!, and→&&, or→||); - НОВЫЙ урок 17-bool-strings («Сравнение строк», из Python 45/15): лексикографическое сравнение, charCodeAt вместо ord, предикаты строк startsWith/endsWith/includes; JS-урок «Предикаты» (15) сохранён. Новый урок пока только в RU-локали (en/es — на этапе перевода, как и остальные уроки). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent fdc905b commit ac01740

8 files changed

Lines changed: 194 additions & 21 deletions

File tree

Lines changed: 45 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,63 @@
1-
В JavaScript есть специальный тип данных — **boolean** (булев тип). Он содержит только два значения: `true` (истина) и `false` (ложь).
1+
Кроме арифметических операций, в математике есть операции сравнения, например `5 > 4` или `3 < 1`. Они есть и в программировании. Сравнения часто применяются в реальных задачах. Например, когда мы оформляем покупку в интернет-магазине, система проверяет, хватает ли у пользователя денег на счёте: если сумма на счёте больше или равна цене товара, заказ подтверждается, иначе появляется сообщение о нехватке средств.
22

3-
## Операторы сравнения
3+
## Сравнение в программировании
44

5-
Операторы сравнения возвращают булево значение:
5+
Начнём с примера, в котором сравниваются два числа:
66

77
```javascript
8-
console.log(5 > 3); // => true
9-
console.log(5 < 3); // => false
10-
console.log(5 === 5); // => true
11-
console.log(5 !== 3); // => true
8+
console.log(5 > 4); // => true
9+
console.log(4 > 4); // => false
1210
```
1311

12+
Результатом сравнения является значение типа **boolean** (булев тип). У него всего два возможных значения: `true` (истина) и `false` (ложь). Это специальные значения языка, их можно использовать напрямую:
13+
14+
```javascript
15+
console.log(true);
16+
console.log(false);
17+
```
18+
19+
На практике так их используют редко, но на их основе строится вся логика поведения программы. Мы сталкиваемся с этим каждый день: вводим пин-коды и пароли, выполняем действия, результат которых может быть разным. Программа рассуждает примерно так: *если так — делай раз, если иначе — делай два*.
20+
21+
В JavaScript доступны следующие операции сравнения:
22+
1423
| Оператор | Смысл |
1524
|----------|-------|
16-
| `>` | больше |
1725
| `<` | меньше |
18-
| `>=` | больше или равно |
1926
| `<=` | меньше или равно |
27+
| `>` | больше |
28+
| `>=` | больше или равно |
2029
| `===` | строго равно |
2130
| `!==` | строго не равно |
2231

23-
## Функции, возвращающие boolean
32+
Языки программирования переняли математические операции сравнения почти без изменений, кроме равенства и неравенства. В математике используется обычное `=`, но в программировании символ `=` уже занят — он присваивает переменным значения. Поэтому для сравнения на равенство в JavaScript используют `===`, а на неравенство — `!==` (тройной и с восклицательным знаком — это «строгое» сравнение, к которому мы ещё вернёмся).
33+
34+
```javascript
35+
console.log(5 >= 3); // => true
36+
console.log(7 < 0); // => false
37+
console.log(5 > 5); // => false
38+
console.log(5 >= 5); // => true
39+
console.log(2 === 5); // => false
40+
console.log(2 !== 5); // => true
41+
```
42+
43+
Когда в сравнении используют конкретные значения, операция кажется бессмысленной: результат и так известен и всегда одинаков. Но всё меняется, когда значения могут быть разными. Напишем простую функцию, которая принимает возраст ребёнка и определяет, младенец ли он. Младенцами считаются дети до двух лет (два не включается):
44+
45+
```javascript
46+
const isInfant = (age) => age < 2;
47+
48+
console.log(isInfant(3)); // => false
49+
console.log(isInfant(2)); // => false
50+
console.log(isInfant(1)); // => true
51+
console.log(isInfant(0)); // => true
52+
```
53+
54+
## Предикаты
2455

25-
Функции, возвращающие `true` или `false`, называют **предикатами**. По соглашению их называют с приставкой `is`, `has`, `can`:
56+
Когда функции возвращают результат сравнения, они обычно отвечают на вопрос «да» или «нет». Такие функции называют **предикатами**. Их легко узнать: они возвращают логическое значение `true` или `false`, а в их названии часто есть проверяемое утверждение (`is`, `has`, `can`). Вот функция, проверяющая, является ли число отрицательным:
2657

2758
```javascript
28-
function isPensioner(age) {
29-
return age >= 60;
30-
}
59+
const isNegative = (number) => number < 0;
3160

32-
console.log(isPensioner(65)); // => true
33-
console.log(isPensioner(30)); // => false
61+
console.log(isNegative(-5)); // => true
62+
console.log(isNegative(7)); // => false
3463
```
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
test:
2+
@ test.sh
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// BEGIN
2+
const isLongWord = (word) => word.length > 5;
3+
// END
4+
5+
export default isLongWord;
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
При регистрации на сайте программа проверяет, что пароль достаточно длинный — больше 5 символов. Напишите функцию `isLongWord()`, которая возвращает `true`, если длина переданного слова больше 5 символов, и `false` в противном случае.
2+
3+
Пример работы:
4+
5+
```javascript
6+
isLongWord('apple'); // => false
7+
isLongWord('banana'); // => true
8+
```
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
Операции сравнения работают не только с числами, но и со строками. В JavaScript строки сравниваются лексикографически: посимвольно слева направо по числовым кодам символов (Unicode).
2+
3+
```javascript
4+
console.log('apple' < 'banana'); // => true
5+
console.log('cat' > 'dog'); // => false
6+
console.log('abc' === 'abc'); // => true
7+
console.log('hello' !== 'world'); // => true
8+
```
9+
10+
Здесь `'apple' < 'banana'`, потому что код символа `a` (97) меньше кода `b` (98), и именно первый различающийся символ решает исход сравнения. Узнать код символа можно методом `charCodeAt()`:
11+
12+
```javascript
13+
console.log('a'.charCodeAt(0)); // => 97
14+
console.log('b'.charCodeAt(0)); // => 98
15+
```
16+
17+
Сравнение чувствительно к регистру: код `'Z'` (90) меньше кода `'a'` (97). Несколько примеров, где первые буквы в разном регистре:
18+
19+
```javascript
20+
console.log('Zebra' < 'apple'); // => true — 'Z'(90) < 'a'(97)
21+
console.log('apple' < 'Banana'); // => false — 'a'(97) > 'B'(66)
22+
console.log('Apple' < 'apple'); // => true — 'A'(65) < 'a'(97)
23+
```
24+
25+
Напишем функцию, которая проверяет, начинается ли слово с заданной буквы. Для этого возьмём первый символ строки и сравним его с нужной буквой:
26+
27+
```javascript
28+
const startsWithLetter = (word, letter) => word[0] === letter;
29+
30+
console.log(startsWithLetter('apple', 'a')); // => true
31+
console.log(startsWithLetter('banana', 'a')); // => false
32+
```
33+
34+
Операции сравнения — такие же выражения, как и арифметические. В них можно подставлять готовые значения и другие выражения, например `word[0]` выше. Можно использовать и свойство `.length`:
35+
36+
```javascript
37+
console.log('apple'.length > 3); // => true, потому что длина равна 5
38+
console.log('hi'.length > 3); // => false, потому что длина равна 2
39+
```
40+
41+
Сначала вычисляется `'apple'.length` (получается число `5`), а потом это число сравнивается с `3`. То есть сначала считаются операнды выражения, а затем выполняется сравнение.
42+
43+
## Полезные предикаты
44+
45+
У строк в JavaScript есть встроенные методы-предикаты. Они возвращают `true` или `false` и помогают проверять разные свойства строки:
46+
47+
```javascript
48+
console.log('hello'.startsWith('he')); // => true — строка начинается с 'he'
49+
console.log('hello'.endsWith('lo')); // => true — строка заканчивается на 'lo'
50+
console.log('hello'.includes('ell')); // => true — строка содержит 'ell'
51+
```
52+
53+
Такие методы позволяют проверять строки на нужные условия прямо в коде, без написания дополнительных функций.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
name: Сравнение строк
3+
tips:
4+
- >
5+
[Сравнение строк в
6+
JavaScript](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Operators/Less_than)
7+
definitions:
8+
- name: Лексикографическое сравнение
9+
description: >-
10+
сравнение строк посимвольно слева направо по числовым кодам символов
11+
(Unicode).
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// @ts-check
2+
3+
import { expect, test } from 'vitest';
4+
import f from './index.js';
5+
6+
test('test', () => {
7+
expect(f('apple')).toBe(false);
8+
expect(f('banana')).toBe(true);
9+
expect(f('pineapple')).toBe(true);
10+
});
Lines changed: 60 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1+
Наряду с логическими операторами **И** (`&&`) и **ИЛИ** (`||`), часто используется операция «**отрицание**». Она меняет логическое значение на противоположное. В JavaScript отрицанию соответствует унарный оператор `!`:
12

2-
Наряду с конъюнкцией (И) и дизъюнкцией (ИЛИ), часто используется операция «отрицание». Отрицание меняет логическое значение на противоположное. В программировании ему соответствует унарный оператор `!`.
3+
```javascript
4+
!true; // false
5+
!false; // true
6+
```
37

4-
Если есть функция, проверяющая чётность числа, то с помощью отрицания можно выполнить проверку нечётности:
8+
Например, если есть функция, проверяющая чётность числа, то с помощью отрицания можно выполнить проверку нечётности:
59

610
```javascript
711
const isEven = (number) => number % 2 === 0;
@@ -10,14 +14,65 @@ isEven(10); // true
1014
!isEven(10); // false
1115
```
1216

13-
То есть мы просто добавили `!` слева от вызова функции и получили обратное действие.
17+
Мы просто добавили `!` слева от вызова функции и получили обратное действие. Отрицание позволяет выражать задуманные правила в коде без написания новых функций.
1418

15-
Отрицание — мощный инструмент, который позволяет лаконично выражать задуманные правила в коде без необходимости писать новые функции.
19+
## Двойное отрицание
1620

17-
А что если написать так `!!isEven(10)`? Внезапно, но код сработает. В логике двойное отрицание подобно отсутствию отрицания вообще.
21+
А что, если написать `!!isEven(10)`? Внезапно, но код сработает. В логике двойное отрицание равносильно отсутствию отрицания:
1822

1923
```javascript
2024
isEven(10); // true
2125
!isEven(10); // false
2226
!!isEven(10); // true
2327
```
28+
29+
## Комбинирование с && и ||
30+
31+
`!` можно комбинировать с `&&` и `||`. Среди логических операторов у отрицания наивысший приоритет, поэтому оно применяется первым:
32+
33+
```javascript
34+
!true || true; // (!true) || true => false || true => true
35+
!true && false; // (!true) && false => false && false => false
36+
```
37+
38+
Скобки меняют порядок вычисления:
39+
40+
```javascript
41+
!(true || true); // !true => false
42+
!(true && false); // !false => true
43+
```
44+
45+
Практический пример — функция проверяет, может ли водитель сесть за руль: нужны права и трезвость:
46+
47+
```javascript
48+
const canDrive = (hasLicense, isDrunk) => hasLicense && !isDrunk;
49+
50+
console.log(canDrive(true, false)); // => true (есть права, трезвый)
51+
console.log(canDrive(true, true)); // => false (есть права, но пьяный)
52+
console.log(canDrive(false, false)); // => false (нет прав)
53+
```
54+
55+
## Законы де Моргана
56+
57+
При работе со сложными логическими выражениями бывает нужно инвертировать их или переписать в эквивалентную, более читаемую форму. Для этого существуют **законы де Моргана** — два правила, описывающих, как отрицание распределяется по составному выражению:
58+
59+
```javascript
60+
!(a && b) === !a || !b
61+
!(a || b) === !a && !b
62+
```
63+
64+
Первый закон: отрицание конъюнкции равно дизъюнкции отрицаний. Проверим:
65+
66+
```javascript
67+
!(true && false); // !false => true
68+
!true || !false; // false || true => true
69+
```
70+
71+
Второй закон: отрицание дизъюнкции равно конъюнкции отрицаний:
72+
73+
```javascript
74+
!(true || false); // !true => false
75+
!true && !false; // false && true => false
76+
```
77+
78+
На практике законы де Моргана помогают упрощать условия. Например, вместо `!(isAdmin || isModerator)` можно написать `!isAdmin && !isModerator` — читается как «не администратор и не модератор».

0 commit comments

Comments
 (0)