Опубликован: 14.08.2003 | Уровень: для всех | Доступ: свободно
Лекция 3:

Функции и объекты

< Лекция 2 || Лекция 3: 1234 || Лекция 4 >
Аннотация: Рассматриваются функции как типы данных и как объекты. Рассмотрена в общих чертах объектная модель документа (DOM). Представлены способы описания пользовательских объектов.
Ключевые слова: функция, язык программирования, код программы, процедура, типы данных, класс объекта, объект, конструктор, очередь ввода, переменная, синоним, eval, последовательность операторов, операция присваивания, вычисление выражения, тип данных, wrapper, строка символов, %length, значение функции, аргумент функции, argument, имя функции, caller, прототип, prototyping, свойства объектов класса, тело функции, конструирование, rectangle, доступ, клиентский объект, DOM, 1-разбор, парсинг, Locate, navigation, серверный объект, клиент-сервер, project, client, встроенный объект, встроенные классы, boolean, math, пользовательский объект, , тип объекта, CAT, кроссбраузерная совместимость, блок операторов, поле ввода, special, submit, alerter, математическая функция, тело оператора, CoS, объектная модель документа, document object model, свойство, метод, событие, объектная модель, браузер, класс, иерархия, netscape, Internet Explorer, объектный язык, наследование, полиморфизм, history, точечная нотация, frameset, i-frame, коллекция, структура данных, фрейм, anchor, applet, апплет, IMG, href, area, element, S/MIME, атрибут, гиперссылка, скобочная нотация, protocol, отправка данных, intuitive, clicking, обработчик, Button, onClick, обработка событий, Клик, host, парсер, интерпретатор, переопределение, assign, литеры

Мы объединили описание функций и объектов в одной лекции по причине того, что они тесно взаимосвязаны. Каждая функция является не только именем для группы операторов, но одновременно и объектом. Объекты же (пользовательские) создаются с помощью функций (конструкторов).

Функции

Язык программирования не может обойтись без механизма многократного использования кода программы. Такой механизм обеспечивается процедурами или функциями. В JavaScript функция выступает в качестве одного из основных типов данных. Одновременно с этим в JavaScript определен класс объектов Function.

В общем случае любой объект JavaScript определяется через функцию. Для создания объекта используется конструктор, который в свою очередь вводится через Function. Таким образом, с функциями в JavaScript связаны следующие ключевые вопросы:

  • функция как тип данных;
  • функция как объект;
  • функция как конструктор объектов.

Именно эти вопросы мы и рассмотрим в данном разделе.

Функция как тип данных

Определяют функцию при помощи ключевого слова function:

function f(arg1,arg2,...)
{
/* тело функции */
}

Здесь следует обратить внимание на следующие моменты. Во-первых, function определяет переменную с именем f. Эта переменная имеет тип function:

document.write('Тип переменной f: '+ typeof(f));
// Будет выведено: Тип переменной f: function

Во-вторых, эта переменная, как и любая другая, имеет значение - свой исходный текст:

var i=5;

function f(a,b,c)
{
 if (a>b) return c;
}

document.write('Значение переменной i: '+ i.valueOf());

// Будет выведено:
// Значение переменной i: 5

document.write('Значение переменной f:<BR>'+ f.valueOf());

// Будет выведено:
// Значение переменной f:
// function f(a,b,c)
// {
//  if (a>b) return c;
// }

Как видим, метод valueOf() применим как к числовой переменной i, так и к переменной f, и возвращает их значение. Более того, значение переменной f можно присвоить другой переменной, тем самым создав "синоним" функции f:

function f(a,b,c)
{
 if (a>b) return c;
 else return c+8;
}

var g = f;
alert('Значение f(2,3,2): '+ f(2,3,2) );
alert('Значение g(2,3,2): '+ g(2,3,2) );

// Будет выведено:
// Значение f(2,3,2): 10
// Значение g(2,3,2): 10

Этим приемом удобно пользоваться для сокращения длины кода. Например, если нужно много раз вызвать метод document.write(), то можно ввести переменную: var W = document.write (обратите внимание - без скобок!), а затем вызывать: W('<H1>Лекция</H1>').

Коль скоро функцию можно присвоить переменной, то ее можно передать и в качестве аргумента другой функции.

function kvadrat(a)
{   return a*a;   }

function polinom(a,kvadrat)
{ return kvadrat(a)+a+5;}

alert(polinom(3,kvadrat));
// Будет выведено: 17

Все это усиливается при использовании функции eval(), которая в качестве аргумента принимает строку, которую рассматривает как последовательность операторов JavaScript (блок) и выполняет этот блок. В качестве иллюстрации приведем скрипт, который позволяет вычислять функцию f(f(...f(N)...)), где число вложений функции f() задается пользователем.

<SCRIPT>
function kvadrat(a)
{   return a*a;   }

function SuperPower()
{ var
 N = parseInt(document.f.n.value),
 K = parseInt(document.f.k.value),
 L = R = '';

 for(i=0; i<K; i++)
 {
  L+='kvadrat(';
  R+=')';
 }
 return eval(L+N+R);
}
</SCRIPT>

<FORM NAME=f>
 Введите аргумент (число):
 <INPUT NAME=n><BR>
 Сколько раз возвести его в квадрат?
 <INPUT NAME=k><BR>
 <INPUT TYPE=button value="Возвести" onClick="alert(SuperPower());">
</FORM>
3.1. Многократное вложение функции kvadrat() в себя

Обратите внимание на запись L=R=''. Она выполняется справа налево. Сначала происходит присваивание R=''. Операция присваивания выдает в качестве результата значение вычисленного выражения (в нашем случае - пустая строка). Она-то и присваивается далее переменной L.

Поясним работу скрипта в целом. В функции SuperPower() мы сначала считываем значения, введенные в поля формы, и преобразуем их из строк в целые числа функцией parseInt(). Далее с помощью цикла for мы собираем строку L, состоящую из K копий строки " kvadrat( ", и строку R, состоящую из K правых скобок " ) ". Теперь мы составляем выражение L+N+R, представляющее собой K раз вложенную в себя функцию kvadrat(), примененную к аргументу N. Наконец, с помощью функции eval() вычисляем полученное выражение. Таким образом, вычисляется функция (...((N)2)2...)2.

Функция как объект

У любого типа данных JavaScript существует объектовая "обертка" (wrapper), которая позволяет применять методы типов данных к переменным и литералам, а также получать значения их свойств. Например, длина строки символов определяется свойством length. Аналогичная "обертка" есть и у функций - это класс объектов Function.

Например, увидеть значение функции можно не только при помощи метода valueOf(), но и используя метод toString():

function f(x,y)
{
  return x-y;
}
document.write(f.toString());

Результат распечатки:

function f(x,y) { return x-y; }

Свойства же функции как объекта доступны программисту только тогда, когда они вызываются внутри этой функции. Наиболее часто используемыми свойствами являются: массив (коллекция) аргументов функции ( arguments[] ), его длина ( length ), имя функции, вызвавшей данную функцию ( caller ), и прототип ( prototype ).

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

function my_sort()
{
  a = new Array(my_sort.arguments.length);
  for(i=0;i<my_sort.arguments.length;i++)
     a[i] = my_sort.arguments[i];
  return a.sort();
}

b = my_sort(9,5,7,3,2);
document.write(b);
// Будет выдано: 2,3,5,7,9

Чтобы узнать, какая функция вызвала данную функцию, используется свойство caller. Возвращаемое ею значение имеет тип function. Пример:

function s()
{ document.write(s.caller+"<BR>"); }

function M()
{ s(); return 5; }

function N()
{ s(); return 7; }

M();   N();

Результат исполнения:

function M() { s(); return 5; }
function N() { s(); return 7; }

Еще одним свойством объекта класса Function является prototype. Но это - общее свойство всех объектов, не только функций, поэтому и обсуждать его мы будем в следующем разделе в контексте типа данных Object. Упомянем только о конструкторе объекта класса Function:

f = new Function(arg_1,...,arg_n, body)

Здесь f - это объект класса Function (его можно использовать как обычную функцию), arg_1, ..., arg_n - аргументы функции f, а body - строка, задающая тело функции f.

Данный конструктор можно использовать, например, для описания функций, которые назначают или переопределяют методы объектов. Здесь мы вплотную подошли к вопросу конструирования объектов. Дело в том, что переменные внутри функции можно рассматривать в качестве ее свойств, а функции - в качестве методов:

function Rectangle(a,b,c,d)
{
this.x0 = a;
this.y0 = b;
this.x1 = c;
this.y1 = d;

this.area = new Function(
 "return Math.abs((this.x1-this.x0)*(this.y1-this.y0))");
}

r = new Rectangle(0,0,30,50);

document.write("Площадь: "+r.area());

// Будет выведено:
// Площадь: 1500

Обратите внимание еще на одну особенность - ключевое слово this. Оно позволяет сослаться на текущий объект, в рамках которого происходит исполнение JavaScript-кода. В данном случае это объект класса Rectangle.

< Лекция 2 || Лекция 3: 1234 || Лекция 4 >
Валерий Банатин
Валерий Банатин
Видимость переменной
Дамир Кантюков
Дамир Кантюков
Не работают методы при обращении через переменную
Михаил Васильев
Михаил Васильев
Россия, г. Санкт-Петербург