up
This commit is contained in:
parent
98a5df9c55
commit
15019c18d6
8 changed files with 167 additions and 165 deletions
|
@ -1,25 +1,21 @@
|
||||||
JS-код:
|
JavaScript-code:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
//+ demo run
|
//+ demo run
|
||||||
var name = prompt("Ваше имя?", "");
|
var name = prompt("What is your name?", "");
|
||||||
alert( name );
|
alert( name );
|
||||||
```
|
```
|
||||||
|
|
||||||
Полная страница:
|
The full page:
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
var name = prompt("Ваше имя?", "");
|
var name = prompt("What is your name?", "");
|
||||||
alert( name );
|
alert( name );
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
# Простая страница
|
# A simple page
|
||||||
|
|
||||||
[importance 4]
|
[importance 4]
|
||||||
|
|
||||||
Создайте страницу, которая спрашивает имя и выводит его.
|
Create a web-page which asks for a name and outputs it.
|
||||||
|
|
||||||
[demo /]
|
[demo /]
|
||||||
|
|
||||||
|
|
|
@ -60,7 +60,7 @@ Run this code in Internet Explorer to see that:
|
||||||
var test = prompt("Test");
|
var test = prompt("Test");
|
||||||
```
|
```
|
||||||
|
|
||||||
So, for IE looking good, it's recommended to always provide the second argument:
|
So, to look good in IE, it's recommended to always provide the second argument:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
//+ run
|
//+ run
|
||||||
|
@ -77,34 +77,33 @@ var test = prompt("Test", ''); // <-- for IE
|
||||||
result = confirm(question);
|
result = confirm(question);
|
||||||
```
|
```
|
||||||
|
|
||||||
`confirm` выводит окно с вопросом `question` с двумя кнопками: OK и CANCEL.
|
Function `confirm` shows a modal window with a `question` and two buttons: OK and CANCEL.
|
||||||
|
|
||||||
**Результатом будет `true` при нажатии OK и `false` - при CANCEL([key Esc]).**
|
The result is `true` if OK is pressed and `false` otherwise.
|
||||||
|
|
||||||
Например:
|
For example:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
//+ run
|
//+ run
|
||||||
var isAdmin = confirm("Вы - администратор?");
|
var isBoss = confirm("Are you the boss?");
|
||||||
|
|
||||||
alert( isAdmin );
|
alert( isBoss ); // true is OK is pressed
|
||||||
```
|
```
|
||||||
|
|
||||||
## Особенности встроенных функций
|
## The limitations
|
||||||
|
|
||||||
Конкретное место, где выводится модальное окно с вопросом -- обычно это центр браузера, и внешний вид окна выбирает браузер. Разработчик не может на это влиять.
|
There are two limitations shared by all the methods:
|
||||||
|
<ol>
|
||||||
|
<li>The exact location of the modal window is determined by the browser. Usually it's in the center.</li>
|
||||||
|
<li>The exact look of the window also depends on the browser. We can't modify it.</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
С одной стороны -- это недостаток, так как нельзя вывести окно в своем, особо красивом, дизайне.
|
That is the price for simplicity. There are other means to show windows and interact with the visitor, but if the "bells and whistles" do not matter much, these methods are just fine.
|
||||||
|
|
||||||
С другой стороны, преимущество этих функций по сравнению с другими, более сложными методами взаимодействия, которые мы изучим в дальнейшем -- как раз в том, что они очень просты.
|
## Summary
|
||||||
|
|
||||||
Это самый простой способ вывести сообщение или получить информацию от посетителя. Поэтому их используют в тех случаях, когда простота важна, а всякие "красивости" особой роли не играют.
|
|
||||||
|
|
||||||
|
|
||||||
## Резюме
|
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>`alert` выводит сообщение.</li>
|
<li>`alert` shows a message.</li>
|
||||||
<li>`prompt` выводит сообщение и ждёт, пока пользователь введёт текст, а затем возвращает введённое значение или `null`, если ввод отменён (CANCEL/[key Esc]).</li>
|
<li>`prompt` shows a message asking the user to input text. It returns the text or, if CANCEL or [key Esc] is clicked, all browsers except Safari return `null`.</li>
|
||||||
<li>`confirm` выводит сообщение и ждёт, пока пользователь нажмёт "OK" или "CANCEL" и возвращает `true/false`.</li>
|
<li>`confirm` shows a message and waits the user to press "OK" or "CANCEL". It returns `true` for OK and `false` for CANCEL/[key Esc].</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
**Да, выведется,** т.к. внутри `if` стоит строка `"0"`.
|
**Yes, it will.**
|
||||||
|
|
||||||
Любая строка, кроме пустой (а здесь она не пустая), в логическом контексте является `true`.
|
Any string except an empty one (and `"0"` is not empty) becomes `true` in the logical context.
|
||||||
|
|
||||||
Можно запустить и проверить:
|
We can run and check:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
//+ run
|
//+ run
|
||||||
if ("0") {
|
if ("0") {
|
||||||
alert( 'Привет' );
|
alert( 'Hello' );
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
# Проверка стандарта
|
# The name of JavaScript
|
||||||
|
|
||||||
[importance 2]
|
[importance 2]
|
||||||
|
|
||||||
Используя конструкцию `if..else`, напишите код, который будет спрашивать: "Каково "официальное" название JavaScript?".
|
Using the `if..else` construct, write the code which asks: 'What is the "official" name of JavaScript?'
|
||||||
|
|
||||||
Если посетитель вводит "EcmaScript", то выводить "Верно!", если что-то другое -- выводить "Не знаете? "EcmaScript"!".
|
If the visitor enters "EcmaScript", then output "Right!", otherwise -- output: "Didn't know? EcmaScript!"
|
||||||
|
|
||||||
Блок-схема:
|
|
||||||
|
|
||||||
<img src="ifelse_task2.png">
|
<img src="ifelse_task2.png">
|
||||||
|
|
||||||
|
|
|
@ -1,233 +1,242 @@
|
||||||
# Условные операторы: if, '?'
|
# Conditional operators: if, '?'
|
||||||
|
|
||||||
|
Sometimes we need to perform different actions basing on a condition. There's an `if` operator for that and also the "question mark" `?` operator for conditional evaluation.
|
||||||
|
|
||||||
Иногда, в зависимости от условия, нужно выполнить различные действия. Для этого используется оператор `if`.
|
|
||||||
[cut]
|
[cut]
|
||||||
Например:
|
|
||||||
|
## The "if" operator
|
||||||
|
|
||||||
|
The "if" operator gets a condition, evaluates it and -- if the result is `true` -- executes the code.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
//+ run
|
//+ run
|
||||||
var year = prompt('В каком году появилась спецификация ECMA-262 5.1?', '');
|
var year = prompt('In which year was ECMAScript-2015 specification published?', '');
|
||||||
|
|
||||||
if (year != 2011) alert( 'А вот и неправильно!' );
|
*!*
|
||||||
|
if (year == 2015) alert( 'You are right!' );
|
||||||
|
*/!*
|
||||||
```
|
```
|
||||||
|
|
||||||
## Оператор if
|
In the example above, the condition is a simple equality: `year == 2015`, but it can be much more complex.
|
||||||
|
|
||||||
Оператор `if` ("если") получает условие, в примере выше это `year != 2011`. Он вычисляет его, и если результат -- `true`, то выполняет команду.
|
If there's more than one command to execute -- we can use a code block in figure brackets:
|
||||||
|
|
||||||
Если нужно выполнить более одной команды -- они оформляются блоком кода в фигурных скобках:
|
|
||||||
|
|
||||||
```js
|
```js
|
||||||
if (year != 2011) {
|
if (year == 2015) {
|
||||||
alert( 'А вот..' );
|
alert( 'You're so smart!' );
|
||||||
alert( '..и неправильно!' );
|
alert( 'Exactly so!' );
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
**Рекомендуется использовать фигурные скобки всегда, даже когда команда одна.**
|
It is recommended to use figure brackets every time with `if`, even if there's only one command. That improves readability.
|
||||||
|
|
||||||
Это улучшает читаемость кода.
|
## Boolean conversion
|
||||||
|
|
||||||
|
The `if (…)` operator evaluates the condition in brackets and converts it to boolean type.
|
||||||
|
|
||||||
## Преобразование к логическому типу
|
In the logical context:
|
||||||
|
|
||||||
Оператор `if (...)` вычисляет и преобразует выражение в скобках к логическому типу.
|
|
||||||
|
|
||||||
В логическом контексте:
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>Число `0`, пустая строка `""`, `null` и `undefined`, а также `NaN` являются `false`,</li>
|
<li>A number `0`, an empty string `""`, `null`, `undefined` and `NaN` are `false`,</li>
|
||||||
<li>Остальные значения -- `true`.</li>
|
<li>Other values -- `true`.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
Например, такое условие никогда не выполнится:
|
So, the code under this condition would never execute:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
if (0) { // 0 преобразуется к false
|
if (0) { // 0 is falsy
|
||||||
...
|
...
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
...А такое -- выполнится всегда:
|
...And this condition -- always works out:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
if (1) { // 1 преобразуется к true
|
if (1) { // 1 is truthy
|
||||||
...
|
...
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Можно и просто передать уже готовое логическое значение, к примеру, заранее вычисленное в переменной:
|
We can also pass a pre-evaluated logical value to `if`. For example, in a variable like here:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
var cond = (year != 2011); // true/false
|
var cond = (year == 2015); // equality evaluates to true or false
|
||||||
|
|
||||||
if (cond) {
|
if (cond) {
|
||||||
...
|
...
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Неверное условие, else
|
## The "else" clause
|
||||||
|
|
||||||
Необязательный блок `else` ("иначе") выполняется, если условие неверно:
|
The `if` operator may contain an optional "else" block. It executes when the condition is wrong.
|
||||||
|
|
||||||
|
For example:
|
||||||
```js
|
```js
|
||||||
//+ run
|
//+ run
|
||||||
var year = prompt('Введите год появления стандарта ECMA-262 5.1', '');
|
var year = prompt('In which year was ECMAScript-2015 specification published?', '');
|
||||||
|
|
||||||
if (year == 2011) {
|
if (year == 2015) {
|
||||||
alert( 'Да вы знаток!' );
|
alert( 'You guessed it right!' );
|
||||||
} else {
|
} else {
|
||||||
alert( 'А вот и неправильно!' ); // любое значение, кроме 2011
|
alert( 'How can you be so wrong?' ); // any value except 2015
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Несколько условий, else if
|
## Several conditions: "else if"
|
||||||
|
|
||||||
Бывает нужно проверить несколько вариантов условия. Для этого используется блок `else if ...`. Например:
|
Sometimes we'd like to test several variants of a condition. There's an `else if` clause for that.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
//+ run
|
//+ run
|
||||||
var year = prompt('В каком году появилась спецификация ECMA-262 5.1?', '');
|
var year = prompt('In which year was ECMAScript-2015 specification published?', '');
|
||||||
|
|
||||||
if (year < 2011) {
|
if (year < 2015) {
|
||||||
alert( 'Это слишком рано..' );
|
alert( 'Too early...' );
|
||||||
} else if (year > 2011) {
|
} else if (year > 2015) {
|
||||||
alert( 'Это поздновато..' );
|
alert( 'Too late' );
|
||||||
} else {
|
} else {
|
||||||
alert( 'Да, точно в этом году!' );
|
alert( 'Exactly!' );
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
В примере выше JavaScript сначала проверит первое условие, если оно ложно -- перейдет ко второму -- и так далее, до последнего `else`.
|
In the code above JavaScript first checks `year < 2015`, if it is falsy then goes to the next condition `year > 2015`. Any number of `else if` may follow with an optional last `else`.
|
||||||
|
|
||||||
|
|
||||||
## Оператор вопросительный знак '?'
|
## Ternary operator '?'
|
||||||
Иногда нужно в зависимости от условия присвоить переменную. Например:
|
|
||||||
|
Sometimes we need to assign a variable depending on a condition.
|
||||||
|
|
||||||
|
For instance:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
//+ run no-beautify
|
//+ run no-beautify
|
||||||
var access;
|
var hasAccess;
|
||||||
var age = prompt('Сколько вам лет?', '');
|
var age = prompt('How old are you?', '');
|
||||||
|
|
||||||
*!*
|
*!*
|
||||||
if (age > 14) {
|
if (age > 14) {
|
||||||
access = true;
|
hasAccess = true;
|
||||||
} else {
|
} else {
|
||||||
access = false;
|
hasAccess = false;
|
||||||
}
|
}
|
||||||
*/!*
|
*/!*
|
||||||
|
|
||||||
alert(access);
|
alert(hasAccess);
|
||||||
```
|
```
|
||||||
|
|
||||||
Оператор вопросительный знак `'?'` позволяет делать это короче и проще.
|
The so called "ternary" or "question mark" operator allows to do that shorter and simpler.
|
||||||
|
|
||||||
Он состоит из трех частей:
|
The operator is represented by a question mark `"?"`. The formal term "ternary" means that the operator has 3 arguments. It is actually the one and only operator in JavaScript which has 3 arguments.
|
||||||
|
|
||||||
|
The syntax is:
|
||||||
|
```
|
||||||
|
var result = condition ? value1 : value2
|
||||||
|
```
|
||||||
|
|
||||||
|
The `condition` is evaluated, if it's truthy then `value1` is returned, otherwise -- `value2`.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
условие ? значение1 : значение2
|
var hasAccess = (age > 14) ? true : false;
|
||||||
```
|
```
|
||||||
|
|
||||||
Проверяется условие, затем если оно верно -- возвращается `значение1`, если неверно -- `значение2`, например:
|
We can omit brackets around `age > 14`, because the question mark operator has a low precedence. It executes after comparisons, so:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
access = (age > 14) ? true : false;
|
// the same
|
||||||
|
var hasAccess = age > 14 ? true : false;
|
||||||
```
|
```
|
||||||
|
|
||||||
Оператор `'?'` выполняется позже большинства других, в частности -- позже сравнений, поэтому скобки можно не ставить:
|
...But brackets make the code more readable. So it's recommended to put them.
|
||||||
|
|
||||||
```js
|
|
||||||
access = age > 14 ? true : false;
|
|
||||||
```
|
|
||||||
|
|
||||||
...Но когда скобки есть -- код лучше читается. Так что рекомендуется их писать.
|
|
||||||
|
|
||||||
[smart]
|
[smart]
|
||||||
В данном случае можно было бы обойтись и без оператора `'?'`, т.к. сравнение само по себе уже возвращает `true/false`:
|
In the described case it is possible to evade the question mark operator, because the comparison by itself returns `true/false`:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
access = age > 14;
|
// the same
|
||||||
|
var hasAccess = age > 14;
|
||||||
```
|
```
|
||||||
[/smart]
|
[/smart]
|
||||||
|
|
||||||
[smart header="\"Тернарный оператор\""]
|
As we can see, the question mark operator has indeed 3 arguments: a condition and two values.
|
||||||
Вопросительный знак -- единственный оператор, у которого есть аж три аргумента, в то время как у обычных операторов их один-два.
|
## Multiple '?'
|
||||||
Поэтому его называют *"тернарный оператор"*.
|
|
||||||
[/smart]
|
|
||||||
|
|
||||||
|
A sequence of question mark `"?"` operators allows to return a value depending on more than one condition.
|
||||||
|
|
||||||
## Несколько операторов '?'
|
For instance:
|
||||||
|
|
||||||
Последовательность операторов `'?'` позволяет вернуть значение в зависимости не от одного условия, а от нескольких.
|
|
||||||
|
|
||||||
Например:
|
|
||||||
```js
|
```js
|
||||||
//+ run
|
//+ run
|
||||||
var age = prompt('возраст?', 18);
|
var age = prompt('age?', 18);
|
||||||
|
|
||||||
var message = (age < 3) ? 'Здравствуй, малыш!' :
|
var message = (age < 3) ? 'Hi, baby!' :
|
||||||
(age < 18) ? 'Привет!' :
|
(age < 18) ? 'Hello!' :
|
||||||
(age < 100) ? 'Здравствуйте!' :
|
(age < 100) ? 'Greetings!' :
|
||||||
'Какой необычный возраст!';
|
'What an unusual age!';
|
||||||
|
|
||||||
alert( message );
|
alert( message );
|
||||||
```
|
```
|
||||||
|
|
||||||
Поначалу может быть сложно понять, что происходит. Однако, внимательно приглядевшись, мы замечаем, что это обычная последовательная проверка!
|
It may be difficult at first to grasp what's going on. But looking more carefully we note that it's just an ordinary sequence of tests.
|
||||||
|
|
||||||
Вопросительный знак проверяет сначала `age < 3`, если верно -- возвращает `'Здравствуй, малыш!'`, если нет -- идет за двоеточие и проверяет `age < 18`. Если это верно -- возвращает `'Привет!'`, иначе проверка `age < 100` и `'Здравствуйте!'`... И наконец, если ничего из этого не верно, то `'Какой необычный возраст!'`.
|
The question mark first tests `age < 3`, if true -- returns `'Hi, baby!'`, otherwise -- goes beyound the colon `":"` and tests `age < 18`. If that's true -- returns `'Hello!'`, otherwise tests `age < 100` and `'Greetings!' if that is so`... At last, if all tests are falsy, the `message` becomes `'What an unusual age!'`.
|
||||||
|
|
||||||
То же самое через `if..else`:
|
The same with `if..else`:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
if (age < 3) {
|
if (age < 3) {
|
||||||
message = 'Здравствуй, малыш!';
|
message = 'Hi, baby!';
|
||||||
} else if (a < 18) {
|
} else if (a < 18) {
|
||||||
message = 'Привет!';
|
message = 'Hello!';
|
||||||
} else if (age < 100) {
|
} else if (age < 100) {
|
||||||
message = 'Здравствуйте!';
|
message = 'Greetings!';
|
||||||
} else {
|
} else {
|
||||||
message = 'Какой необычный возраст!';
|
message = 'What an unusual age!';
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Нетрадиционное использование '?'
|
## Non-traditional use of '?'
|
||||||
|
|
||||||
Иногда оператор вопросительный знак `'?'` используют как замену `if`:
|
Sometimes the question mark `'?'` is used as a replacement for `if`:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
//+ run no-beautify
|
//+ run no-beautify
|
||||||
var company = prompt('Какая компания создала JavaScript?', '');
|
var company = prompt('Which company created JavaScript?', '');
|
||||||
|
|
||||||
*!*
|
*!*
|
||||||
(company == 'Netscape') ?
|
(company == 'Netscape') ?
|
||||||
alert('Да, верно') : alert('Неправильно');
|
alert('Right!') : alert('Wrong.');
|
||||||
*/!*
|
*/!*
|
||||||
```
|
```
|
||||||
|
|
||||||
Работает это так: в зависимости от условия, будет выполнена либо первая, либо вторая часть после `'?'`.
|
Depending on the condition `company == 'Netscape'`, either the first or the second part after `"?"` gets evaluated and shows the alert.
|
||||||
|
|
||||||
Результат выполнения не присваивается в переменную, так что пропадёт (впрочем, `alert` ничего не возвращает).
|
We don't assign a result to a variable here, the `alert` doesn't return anything anyway.
|
||||||
|
|
||||||
**Рекомендуется не использовать вопросительный знак таким образом.**
|
**It is not recommended to use a question mark in this way.**
|
||||||
|
|
||||||
Несмотря на то, что с виду такая запись короче `if`, она является существенно менее читаемой.
|
The notation seem to be shorter than `if`, that appeals to some programmers. Although it is less readable.
|
||||||
|
|
||||||
Вот, для сравнения, то же самое с `if`:
|
Here's the same with `if` for comparison:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
//+ run no-beautify
|
//+ run no-beautify
|
||||||
var company = prompt('Какая компания создала JavaScript?', '');
|
var company = prompt('Which company created JavaScript?', '');
|
||||||
|
|
||||||
*!*
|
*!*
|
||||||
if (company == 'Netscape') {
|
if (company == 'Netscape') {
|
||||||
alert('Да, верно');
|
alert('Right!');
|
||||||
} else {
|
} else {
|
||||||
alert('Неправильно');
|
alert('Wrong.');
|
||||||
}
|
}
|
||||||
*/!*
|
*/!*
|
||||||
```
|
```
|
||||||
|
|
||||||
При чтении кода глаз идёт вертикально и конструкции, занимающие несколько строк, с понятной вложенностью, воспринимаются гораздо легче. Возможно, вы и сами почувствуете, пробежавшись глазами, что синтаксис с `if` более прост и очевиден чем с оператором `'?'`.
|
Our eyes browse the code vertically. The constructs which span several lines are easier to understand than a long horizontal reading here.
|
||||||
|
|
||||||
Смысл оператора `'?'` -- вернуть то или иное значение, в зависимости от условия. Пожалуйста, используйте его по назначению, а для выполнения разных веток кода есть `if`.
|
The idea of a question mark `'?'` is to return one or another value depending on the condition. Please use it for exactly that. There's `if` to execute different branches of the code.
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,7 @@ var prase = `can embed ${str}`;
|
||||||
In JavaScript, there are 3 types of quotes.
|
In JavaScript, there are 3 types of quotes.
|
||||||
|
|
||||||
<ol>
|
<ol>
|
||||||
<li>Double quotes and single quotes are essentially the same. Can use either.</li>
|
<li>Double quotes and single quotes are essentially the same.</li>
|
||||||
<li>Backtricks are "extended functionality" quotes. They allow to embed other variables or even expressions into the string wrapping them by `${…}`.</li>
|
<li>Backtricks are "extended functionality" quotes. They allow to embed other variables or even expressions into the string wrapping them by `${…}`.</li>
|
||||||
</ol>
|
</ol>
|
||||||
|
|
||||||
|
|
|
@ -147,22 +147,20 @@ The string equality is one character longer, but it's more obvious what's going
|
||||||
|
|
||||||
## Comparison with null and undefined
|
## Comparison with null and undefined
|
||||||
|
|
||||||
Проблемы со специальными значениями возможны, когда к переменной применяется операция сравнения `> < <= >=`, а у неё может быть как численное значение, так и `null/undefined`.
|
Thre's a non-intuitive behavior when `null` or `undefined` is compared with other values.
|
||||||
|
|
||||||
**Интуитивно кажется, что `null/undefined` эквивалентны нулю, но это не так.**
|
It may feel like `null/undefined` are equivalent to zero. But it is not so.
|
||||||
|
|
||||||
Они ведут себя по-другому.
|
|
||||||
|
|
||||||
<ol>
|
<ol>
|
||||||
<li>Значения `null` и `undefined` равны `==` друг другу и не равны чему бы то ни было ещё.
|
<li>For equality `==` the rule is simple: values `null` and `undefined` are equal `==` each other and non-equal to any other value.</li>
|
||||||
Это жёсткое правило буквально прописано в спецификации языка.</li>
|
<li>Comparisons like `< > >= <=` convert `null/undefined` to a number in the evaluation process. Upon the conversion `null` becomes `0`, while `undefined` becomes `NaN`.</li>
|
||||||
<li>При преобразовании в число `null` становится `0`, а `undefined` становится `NaN`.</li>
|
|
||||||
</ol>
|
</ol>
|
||||||
|
|
||||||
Посмотрим забавные следствия.
|
Let's see funny consequences.
|
||||||
|
|
||||||
### Некорректный результат сравнения null с 0
|
### Incorrect result of comparing null with 0
|
||||||
Сравним `null` с нулём:
|
|
||||||
|
Let's compare `null` with a zero:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
//+ run
|
//+ run
|
||||||
|
@ -170,24 +168,28 @@ alert( null > 0 ); // false
|
||||||
alert( null == 0 ); // false
|
alert( null == 0 ); // false
|
||||||
```
|
```
|
||||||
|
|
||||||
Итак, мы получили, что `null` не больше и не равен нулю. А теперь...
|
Okay, from the code above we may decide that `null` is not greater and not equal to zero.
|
||||||
|
|
||||||
|
But...
|
||||||
|
|
||||||
```js
|
```js
|
||||||
//+ run
|
//+ run
|
||||||
alert(null >= 0); // *!*true*/!*
|
alert(null >= 0); // *!*true*/!*
|
||||||
```
|
```
|
||||||
|
|
||||||
Как такое возможно? Если нечто *"больше или равно нулю"*, то резонно полагать, что оно либо *больше*, либо *равно*. Но здесь это не так.
|
How can that be possible? If `null` is "not greater than zero and not equal to zero" then how `null >= 0` can be true?
|
||||||
|
|
||||||
Дело в том, что алгоритмы проверки равенства `==` и сравнения `>= > < <=` работают по-разному.
|
Yeah, mathematically that's strange. The reason is that an equality check `==` and comparisons `> < >= <=` work differently.
|
||||||
|
|
||||||
Сравнение честно приводит к числу, получается ноль. А при проверке равенства значения `null` и `undefined` обрабатываются особым образом: они равны друг другу, но не равны чему-то ещё.
|
Comparisons convert `null` to a number, hence treat it as `0`. That's why `null >= 0` is true and `null > 0` is false.
|
||||||
|
|
||||||
В результате получается странная с точки зрения здравого смысла ситуация, которую мы видели в примере выше.
|
From the other hand, equality has a rule that a "sweet couple" `undefined` and `null` match with each other and no other value.
|
||||||
|
|
||||||
### Несравнимый undefined
|
That's why we have a strange-looking situation above.
|
||||||
|
|
||||||
Значение `undefined` вообще нельзя сравнивать:
|
### An uncomparable undefined
|
||||||
|
|
||||||
|
The value `undefined` shouldn't participate in comparisons at all:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
//+ run
|
//+ run
|
||||||
|
@ -196,24 +198,22 @@ alert( undefined < 0 ); // false (2)
|
||||||
alert( undefined == 0 ); // false (3)
|
alert( undefined == 0 ); // false (3)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Formally, it works like this:
|
||||||
<ul>
|
<ul>
|
||||||
<li>Сравнения `(1)` и `(2)` дают `false` потому, что `undefined` при преобразовании к числу даёт `NaN`. А значение `NaN` по стандарту устроено так, что сравнения `==`, `<`, `>`, `<=`, `>=` и даже `===` с ним возвращают `false`.</li>
|
<li>Comparisons `(1)` and `(2)` return `false` because `undefined` gets converted to `NaN`. And `NaN` is a special numeric value which returns `false` for all comparisons.</li>
|
||||||
<li>Проверка равенства `(3)` даёт `false`, потому что в стандарте явно прописано, что `undefined` равно лишь `null` и ничему другому.</li>
|
<li>The equality check `(3)` returns `false`, because `undefined` only equals `null` and no other value.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
**Conclusion: any comparison with `undefined/null` except the exact equality `===` should be done with care.**
|
||||||
|
|
||||||
**Вывод: любые сравнения с `undefined/null`, кроме точного `===`, следует делать с осторожностью.**
|
For clarity it is preferable not to use comparisons `>= > < <=` with a variable which may be `null/undefined`. We can always make a separate check for `null` or add an explicit type conversion.
|
||||||
|
|
||||||
Желательно не использовать сравнения `>= > < <=` с ними, во избежание ошибок в коде.
|
## Summary
|
||||||
|
|
||||||
|
|
||||||
## Итого
|
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>В JavaScript есть логические значения `true` (истина) и `false` (ложь). Операторы сравнения возвращают их.</li>
|
<li>JavaScript has logical values `true` and `false`. Comparison operators return one of those.</li>
|
||||||
<li>Строки сравниваются побуквенно.</li>
|
<li>Strings are compared letter-by-letter in dictionary order.</li>
|
||||||
<li>Значения разных типов приводятся к числу при сравнении, за исключением строгого равенства `===` (`!==`).</li>
|
<li>When values of different types are compared, they get converted to numbers, with the exclusion of a string equality check `===` (`!==`).</li>
|
||||||
<li>Значения `null` и `undefined` равны `==` друг другу и не равны ничему другому. В других сравнениях (с участием `>`,`<`) их лучше не использовать, так как они ведут себя не как `0`.</li>
|
<li>Values `null` and `undefined` equal `==` each other and do not equal any other value. It's better not to use them in comparisons with `>` or `<`, because the result may be unexpected.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
Мы ещё вернёмся к теме сравнения позже, когда лучше изучим различные типы данных в JavaScript.
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue