Функция в JavaScript может как иметь имя, так и быть безымянной. Безымянная функция может быть назначена переменной или передана методу.
function named() {}
var handler = function() {}
Множество безымянных функций можно видеть в коде jQuery:
$(document).ready(function() {});
$("a").click(function() {});
$.ajax({
url: "someurl.php",
success: function() {}
});
Тип функции — «function».
Аргументы
Внутри функции всегда доступна специальная переменная «arguments». Переменная подобна массиву, таким образом она имеет свойство длины, но не имеет встроенных методов, которые присущи массиву. Элементы псевдо-массива являются аргументом вызова функции.
function log(x) {
console.log(typeof x, arguments.length);
}
log(); // "undefined", 0
log(1); // "number", 1
log("1", "2", "3"); // "string", 3
Объект аргументов также имеет свойство «callee», что ссылается на функцию в пределах которой Вы находитесь. Например:
var awesome = function() { return arguments.callee }
awesome() == awesome // true
Контекст, Call и Apply
В JavaScript переменная «this» всегда ссылается на текущий контекст. По умолчанию «this» ссылается на объект window. В зависимости от того, как вызвана функция, контекст в пределах функции может изменяться.
Все обработчики событий в jQuery вызываются с управляющим элементом в качестве контекста.
$(document).ready(function() {
// this refers to window.document
});
$("a").click(function() {
// this refers to an anchor DOM element
});
Вы можете указать контекст для вызова функции используя встроенные методы call и apply. Различие между этими двумя методами заключаются в способе передачи аргументов. Call передает все аргументы в качестве аргументов функции, тогда как apply принимает массив в качестве аргументов.
function scope() {
console.log(this, arguments.length);
}
scope() // window, 0
scope.call("foobar", [1,2]); // "foobar", 1
scope.apply("foobar", [1,2]); // "foobar", 2
Пространство функции
В JavaScript переменные, которые определены внутри функции, доступны только в пространстве самой функции. Рассмотрим следующий пример:
// global
var x = 0;
(function() {
// private
var x = 1;
console.log(x); // 1
})();
console.log(x); // 0
Объявляется глобальная переменная х, затем создается безымянная функция и немедленно выполняется (дополнительные скобки необходимы для немедленного выполнения). Внутри функции была объявлена другая переменная х с другим значением. Внутренняя переменная х видна только в пределах функции и не изменяет глобальной переменной.
Привязки
Привязки создаются всякий раз, когда внутри функции необходимо получить доступ к переменной, объявленной вне текущего пространства функции. В приведенном примере ниже переменная counter видима в пределах функций create, increment и print, но не за их пределами.
function create() {
var counter = 0;
return {
increment: function() {
counter++;
},
print: function() {
console.log(counter);
}
}
}
var c = create();
c.increment();
c.print(); // 1
Модель позволяет создавать объекты с помощью методов, которые оперируют над данными, не видимыми извне. Основа объектно-ориентированного программирования.
Модель proxy
Сочетание всех вышеизложенных знаний дает Вам, как разработчику JavaScript, достаточно много возможностей. Одним из способов этого сочетания является внедрение модели proxy в JavaScript, реализуя тем самым основы аспектно-ориентированного программирования (АОР):
(function() {
// log all calls to setArray
var proxied = jQuery.fn.setArray;
jQuery.fn.setArray = function() {
console.log(this, arguments);
return proxied.apply(this, arguments);
};
})();
Структура выше заключает свой код в функцию для того, чтобы скрыть «проксируемую» переменную. Предоставляемый jQuery метод setArray сохраняется в привязке и перезаписывается. Прокси в дальнейшем регистрирует все вызовы к методу и передает их подлинному методу. Использование apply(this, arguments) дает гарантию, что вызывающий не заметит разницы между подлинным и проксируемым методом.

