JavaScript. Подробное руководство, 6-е издание, стр. 102

Вызываемые объекты, не являющиеся функциями, встречаются в современных реализациях JavaScript в двух ситуациях. Во-первых, веб-броузер IE (версии 8 и ниже) реализует клиентские методы, такие как

<b>Window.alert()</b>
и
<b>Document.getElementsByld(),</b>
используя вызываемые объекты, а не объекты класса
<b>Function</b>
. Эти методы действуют в IE точно так же, как в других броузерах, но они не являются объектами
<b>Function</b>
. В IE9 был выполнен переход на использование настоящих функций, поэтому со временем эта разновидность вызываемых объектов будет использоваться все меньше и меньше.

Другой типичной разновидностью вызываемых объектов являются объекты

<b>RegExp</b>
- во многих броузерах предоставляется возможность напрямую вызывать объект
<b>RegExp</b>
, как более краткий способ вызова его метода
<b>ехес().</b>
Эта возможность не предусматривается стандартом JavaScript. В свое время она была реализована компанией Netscape и подхвачена другими производителями для обеспечения совместимости. Старайтесь не писать программы, опирающиеся на возможность вызова объектов
<b>RegExp</b>
: данная особенность, скорее всего, будет объявлена нерекомендуемой и будет ликвидирована в будущем. Оператор
<b>typeof</b>
не во всех броузерах одинаково распознает вызываемые объекты
<b>RegExp</b>
. В одних броузерах он возвращает строку «function», а в других - «object».

Если в программе потребуется определить, является ли объект настоящим объектом функции (и обладает методами функций), сделать это можно, определив значение атрибута class (раздел 6.8.2), использовав прием, продемонстрированный в примере 6.4:

<b>function isFunction(x) {</b>

<b>return Object.prototype.toString.call(x) === &quot;[object Function]&quot;;</b>

<b>}</b>

Обратите внимание, насколько эта функция

<b>isFunction()</b>
похожа на функцию
<b>isArray(),</b>
представленную в разделе 7.10.

8.8. Функциональное программирование

JavaScript не является языком функционального программирования, как

<b>Lisp</b>
или
<b>Haskell</b>
, но тот факт, что программы на языке JavaScript могут манипулировать функциями как объектами означает, что в JavaScript можно использовать приемы функционального программирования. Масса методов в ECMAScript 5, таких как
<b>mар()</b>
и
<b>reduce(),</b>
сами по себе способствуют использованию функционального стиля программирования. В следующих разделах демонстрируются приемы функционального программирования на языке JavaScript. Их цель - не подтолкнуть вас к использованию этого замечательного стиля программирования, а показать широту возможностей функций в языке JavaScript. 15

8.8.1. Обработка массивов с помощью функций

Представим, что у нас имеется массив чисел и нам необходимо найти среднее значение и стандартное отклонение для этих значений. Эту задачу можно было бы решить без использования приемов функционального программирования, как показано ниже:

<b>var data = [1,1,3,5,5]; // Массив чисел</b>

<b>// Среднее - это сумма значений элементов, деленная на их количество </b>

<b>var total = 0;</b>

<b>for(var і = 0; і &lt; data.length; і++) total += data[i]; </b>

<b>var mean = total/data.length; // Среднее значение равно З</b>

<b>// Чтобы найти стандартное отклонение, необходимо вычислить сумму квадратов </b>

<b>// отклонений элементов от среднего, </b>

<b>total = 0;</b>

<b>for(var і = 0; і &lt; data.length; i++) {</b>

<b>  var deviation = data[i] - mean; </b>

<b>  total += deviation * deviation;</b>

<b>}</b>

<b>var stddev = Math.sqrt(total/(data.length-1)); // Стандартное отклонение = 2</b>

Те же вычисления можно выполнить в более кратком функциональном стиле, задействовав методы массивов

<b>mар()</b>
и
<b>reduce(),</b>
как показано ниже (краткое описание этих методов приводится в разделе 7.9):

<b>// Для начала необходимо определить две простые функции </b>

<b>var sum = function(x,у) { return х+у; }; </b>

<b>var square = function(x) { return x*x; };</b>

<b>// Затем использовать их совместно с методами класса Array для вычисления</b>

<b>// среднего и стандартного отклонения</b>

<b>var data = [1,1,3,5,5];</b>

<b>var mean = data.reduce(sum)/data.length;</b>

<b>var deviations = data.map(function(x) {return x-mean;});</b>

<b>var stddev = Math.sqrt(deviations.map(square).reduce(sum)/(data.length-1));</b>

A как быть, если в нашем распоряжении имеется только реализация ЕСМА-Script 3, где отсутствуют эти новейшие методы массивов? Можно определить собственные функции mар() и reduce(), которые будут использовать встроенные методы при их наличии:

<b>// Вызывает функцию f для каждого элемента массива и возвращает массив результатов.</b>

<b>// Использует метод Array.prototype.mар, если он определен, </b>

<b>var mар = Array.prototype.тар</b>

<b>    ? function(a, f) { return a.map(f); } // Если метод map() доступен </b>

<b>    : function(a,f) { // Иначе реализовать свою версию</b>