Выбрать главу

Эта строка создаст новую функцию, которая более или менее эквивалентна функции, объявленной с помощью более привычного синтаксиса:

var f = function(x, у) { return х*у; }

Конструктор Function() принимает произвольное число строковых аргументов. Последний аргумент должен содержать текст с телом функции; он может включать произвольное число инструкций на языке JavaScript, разделенных точкой с запятой. Все остальные аргументы конструктора интерпретируются как имена параметров функции. Чтобы создать функцию, не имеющую аргументов, достаточно передать конструктору всего одну строку - тело функции.

Примечательно, что конструктору Function() не передается никаких аргументов, определяющих имя создаваемой функции. Подобно литералам функций, конструктор Function() создает анонимные функции.

Есть несколько моментов, связанных с конструктором Function(), о которых следует упомянуть особо:

• Конструктор Function() позволяет динамически создавать и компилировать функции в процессе выполнения программы.

• При каждом вызове конструктор Function() выполняет синтаксический анализ тела функции и создает новый объект функции. Если вызов конструктора производится в теле цикла или часто вызываемой функции, это может отрицательно сказаться на производительности программы. Напротив, вложенные функции и выражения определения функций внутри циклов не компилируются повторно.

• И последний, очень важный момент: когда функция создается с помощью конструктора Function(), не учитывается лексическая область видимости - функции всегда компилируются как глобальные функции, что наглядно демонстрирует следующий фрагмент:

var scope = "глобальная";

function constructFunction() {

  var scope = "локальная";

  return new Function("return scope”); // Здесь не используется

  // локальная область видимости!

} ;

// Следующая строка вернет "глобальная", потому что функция, возвращаемая

// конструктором Function(), является глобальной.

constructFunction()(); // => "глобальная"

Точнее всего конструктор Function() соответствует глобальной версии eval() (раздел 4.12.2), которая определяет новые переменные и функции в своей собственной области видимости. Вам редко придется использовать этот конструктор в своих программах.

8.7.7. Вызываемые объекты

В разделе 7.11 мы узнали, что существуют объекты, «подобные массивам», которые не являются настоящими массивами, но во многих случаях могут интерпретироваться как массивы. Аналогичная ситуация складывается с функциями. Вызываемый объект - это любой объект, который может быть вызван в выражении вызова функции. Все функции являются вызываемыми объектами, но не все вызываемые объекты являются функциями.

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

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

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