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)`, которая будет говорить "Привет" своему аргументу, причём если передан массив -- то "Привет" каждому:
|
Пример полиморфной функции -- `sayHi(who)`, которая будет говорить "Привет" своему аргументу, причём если передан массив -- то "Привет" каждому:
|
||||||
|
@ -127,7 +144,7 @@ if (x.getTime) {
|
||||||
//+ run
|
//+ run
|
||||||
function sayHi(who) {
|
function sayHi(who) {
|
||||||
|
|
||||||
if (who.forEach) { // проверка на массив (или что-то похожее)
|
if (Array.isArray(who)) {
|
||||||
who.forEach(sayHi);
|
who.forEach(sayHi);
|
||||||
} else {
|
} else {
|
||||||
alert( 'Привет, ' + who );
|
alert( 'Привет, ' + who );
|
||||||
|
@ -140,13 +157,16 @@ sayHi("Вася"); // Привет, Вася
|
||||||
// Вызов с массивом
|
// Вызов с массивом
|
||||||
sayHi(["Саша", "Петя"]); // Привет, Саша... Петя
|
sayHi(["Саша", "Петя"]); // Привет, Саша... Петя
|
||||||
|
|
||||||
// Вызов с вложенными массивами
|
// Вызов с вложенными массивами - тоже работает!
|
||||||
sayHi(["Саша", "Петя", ["Маша", "Юля"]]); // Привет Саша..Петя..Маша..Юля
|
sayHi(["Саша", "Петя", ["Маша", "Юля"]]); // Привет Саша..Петя..Маша..Юля
|
||||||
```
|
```
|
||||||
|
|
||||||
Здесь вместо `splice` проверяется наличие `forEach`. Так надёжнее, поскольку именно его мы собираемся использовать.
|
Здесь используется не "duck typing", а "жёсткая" проверка на массив. Можно было бы и поступить мягче -- проверить только наличие метода `forEach`:
|
||||||
|
```js
|
||||||
Обратите внимание, получилась даже поддержка вложенных массивов. Да здравствует рекурсия!
|
if (who.forEach) {
|
||||||
|
...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## Итого
|
## Итого
|
||||||
|
|
||||||
|
|
|
@ -101,16 +101,17 @@ if (NaN === NaN) alert( "===" ); // не сработает
|
||||||
```
|
```
|
||||||
|
|
||||||
</li>
|
</li>
|
||||||
<li>Значение `NaN` можно проверить специальной функцией `isNaN(n)`, которая возвращает `true` если аргумент -- `NaN` и `false` для любого другого значения.
|
<li>Значение `NaN` можно проверить специальной функцией `isNaN(n)`, которая преобразует аргумент к числу и возвращает `true`, если получилось `NaN`, и `false` -- для любого другого значения.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
//+ run
|
//+ run
|
||||||
var n = 0 / 0;
|
var n = 0 / 0;
|
||||||
|
|
||||||
alert( isNaN(n) ); // true
|
alert( isNaN(n) ); // true
|
||||||
|
alert( isNaN("12") ); // false, строка преобразовалась к обычному числу 12
|
||||||
```
|
```
|
||||||
|
|
||||||
[smart]
|
[smart header="Забавный способ проверки на `NaN`"]
|
||||||
Отсюда вытекает забавный способ проверки значения на `NaN`: можно проверить значение на равенство самому себе, если не равно -- то `NaN`:
|
Отсюда вытекает забавный способ проверки значения на `NaN`: можно проверить значение на равенство самому себе, если не равно -- то `NaN`:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
|
@ -122,6 +123,7 @@ if (n !== n) alert( 'n = NaN!' );
|
||||||
|
|
||||||
Это работает, но для наглядности лучше использовать `isNaN(n)`.
|
Это работает, но для наглядности лучше использовать `isNaN(n)`.
|
||||||
[/smart]
|
[/smart]
|
||||||
|
|
||||||
</li>
|
</li>
|
||||||
<li>Значение `NaN` "прилипчиво". Любая операция с `NaN` возвращает `NaN`.
|
<li>Значение `NaN` "прилипчиво". Любая операция с `NaN` возвращает `NaN`.
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Окно внутри ифрейма
|
# Общение между окнами и фреймами
|
||||||
|
|
||||||
Элемент `iframe` является обычным узлом DOM, как и любой другой. Существенное отличие -- в том, что с ним связан объект `window` внутреннего окна. Он доступен по ссылке `iframe.contentWindow`.
|
Элемент `iframe` является обычным узлом DOM, как и любой другой. Существенное отличие -- в том, что с ним связан объект `window` внутреннего окна. Он доступен по ссылке `iframe.contentWindow`.
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue