diff --git a/1-js/4-data-structures/12-typeof-duck-typing/article.md b/1-js/4-data-structures/12-typeof-duck-typing/article.md index 733bf476..7815b69c 100644 --- a/1-js/4-data-structures/12-typeof-duck-typing/article.md +++ b/1-js/4-data-structures/12-typeof-duck-typing/article.md @@ -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) { + ... +} +``` ## Итого diff --git a/1-js/4-data-structures/2-number/article.md b/1-js/4-data-structures/2-number/article.md index 825263f7..b25a936b 100644 --- a/1-js/4-data-structures/2-number/article.md +++ b/1-js/4-data-structures/2-number/article.md @@ -101,16 +101,17 @@ if (NaN === NaN) alert( "===" ); // не сработает ``` -