renovation

This commit is contained in:
Ilya Kantor 2015-03-21 13:20:51 +03:00
parent 087875b29b
commit 0712ddc698
3 changed files with 31 additions and 9 deletions

View file

@ -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) {
...
}
```
## Итого ## Итого

View file

@ -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`.

View file

@ -1,4 +1,4 @@
# Окно внутри ифрейма # Общение между окнами и фреймами
Элемент `iframe` является обычным узлом DOM, как и любой другой. Существенное отличие -- в том, что с ним связан объект `window` внутреннего окна. Он доступен по ссылке `iframe.contentWindow`. Элемент `iframe` является обычным узлом DOM, как и любой другой. Существенное отличие -- в том, что с ним связан объект `window` внутреннего окна. Он доступен по ссылке `iframe.contentWindow`.