renovation
This commit is contained in:
parent
087875b29b
commit
0712ddc698
3 changed files with 31 additions and 9 deletions
|
@ -1,4 +1,4 @@
|
|||
# Оператор typeof и утиная типизация
|
||||
# Полиморфизм, typeof и утиная типизация
|
||||
|
||||
В этой главе мы рассмотрим, как создавать *полиморфные* функции, то есть такие, которые по-разному обрабатывают аргументы, в зависимости от их типа. Например, функция вывода может по-разному форматировать числа и даты.
|
||||
|
||||
|
@ -119,6 +119,23 @@ if (x.getTime) {
|
|||
|
||||
Но как раз в этом и есть смысл утиной типизации: если объект похож на массив, у него есть методы массива, то будем работать с ним как с массивом (какая разница, что это на самом деле).
|
||||
|
||||
[smart header="Метод `Array.isArray()`"]
|
||||
Для массивов есть специальный метод проверки: `Array.isArray(arr)`, который возвращает `true` только если `arr` -- массив:
|
||||
```js
|
||||
//+ run
|
||||
alert( Array.isArray([1,2,3]) ); // true
|
||||
alert( Array.isArray("not array")); // false
|
||||
```
|
||||
|
||||
Этот метод уникален в своём роде, других аналогичных (типа `Object.isObject`, `Date.isDate`) -- нет.
|
||||
|
||||
Если нужно удостовериться, что мы получили именно массив, а не нечто похожее на него -- можно использовать `Array.isArray`. Но при этом нужно отдавать себе отчёт, что этим мы одновременно ограничиваем применимость кода: "похожие на массив" данные теперь обрабатываться не будут. Решение зависит от конкретной ситуации.
|
||||
[/smart]
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## Полиморфизм
|
||||
|
||||
Пример полиморфной функции -- `sayHi(who)`, которая будет говорить "Привет" своему аргументу, причём если передан массив -- то "Привет" каждому:
|
||||
|
@ -127,7 +144,7 @@ if (x.getTime) {
|
|||
//+ run
|
||||
function sayHi(who) {
|
||||
|
||||
if (who.forEach) { // проверка на массив (или что-то похожее)
|
||||
if (Array.isArray(who)) {
|
||||
who.forEach(sayHi);
|
||||
} else {
|
||||
alert( 'Привет, ' + who );
|
||||
|
@ -140,13 +157,16 @@ sayHi("Вася"); // Привет, Вася
|
|||
// Вызов с массивом
|
||||
sayHi(["Саша", "Петя"]); // Привет, Саша... Петя
|
||||
|
||||
// Вызов с вложенными массивами
|
||||
// Вызов с вложенными массивами - тоже работает!
|
||||
sayHi(["Саша", "Петя", ["Маша", "Юля"]]); // Привет Саша..Петя..Маша..Юля
|
||||
```
|
||||
|
||||
Здесь вместо `splice` проверяется наличие `forEach`. Так надёжнее, поскольку именно его мы собираемся использовать.
|
||||
|
||||
Обратите внимание, получилась даже поддержка вложенных массивов. Да здравствует рекурсия!
|
||||
Здесь используется не "duck typing", а "жёсткая" проверка на массив. Можно было бы и поступить мягче -- проверить только наличие метода `forEach`:
|
||||
```js
|
||||
if (who.forEach) {
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
## Итого
|
||||
|
||||
|
|
|
@ -101,16 +101,17 @@ if (NaN === NaN) alert( "===" ); // не сработает
|
|||
```
|
||||
|
||||
</li>
|
||||
<li>Значение `NaN` можно проверить специальной функцией `isNaN(n)`, которая возвращает `true` если аргумент -- `NaN` и `false` для любого другого значения.
|
||||
<li>Значение `NaN` можно проверить специальной функцией `isNaN(n)`, которая преобразует аргумент к числу и возвращает `true`, если получилось `NaN`, и `false` -- для любого другого значения.
|
||||
|
||||
```js
|
||||
//+ run
|
||||
var n = 0 / 0;
|
||||
|
||||
alert( isNaN(n) ); // true
|
||||
alert( isNaN("12") ); // false, строка преобразовалась к обычному числу 12
|
||||
```
|
||||
|
||||
[smart]
|
||||
[smart header="Забавный способ проверки на `NaN`"]
|
||||
Отсюда вытекает забавный способ проверки значения на `NaN`: можно проверить значение на равенство самому себе, если не равно -- то `NaN`:
|
||||
|
||||
```js
|
||||
|
@ -122,6 +123,7 @@ if (n !== n) alert( 'n = NaN!' );
|
|||
|
||||
Это работает, но для наглядности лучше использовать `isNaN(n)`.
|
||||
[/smart]
|
||||
|
||||
</li>
|
||||
<li>Значение `NaN` "прилипчиво". Любая операция с `NaN` возвращает `NaN`.
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue