Введение
Во многих традиционных языках (C/C ++/Java/C#и т. Д.) Функции существуют в качестве граждан второго класса. Вы можете объявить функцию только с помощью ключевых слов языка, а затем назвать ее. Если вам необходимо передать функцию в качестве параметра другой функции, или присвоить значение локальной переменной или в качестве возвращаемого значения, вам необходимо сделать прорыв с помощью специальных методов, таких как указатель функции и прокси (делегат).
В мире JavaScript функции являются первоклассными гражданами. Они не только имеют все способы использования традиционных функций (объявления и вызовы), но также могут назначать значения, передавать параметры и возвращать как простые значения. Такие функции также называются первоклассными функциями. Мало того, что функции в JavaScript также действуют как конструкторы класса, а также являются случаями функционального класса. Такие многочисленные идентификаторы делают функции JavaScript очень важными.
1. Уровень начала Javascript
Как и обычные языки, функции JavaScript также сначала следуют принципу объявления, а затем затем используют. Имена функций могут содержать только буквы, числа, недостатки или $, и не могут начинаться с номеров. Есть два распространенных способа объявления функций:
Кода -копия выглядит следующим образом:
// объявить функцию myfunc напрямую
Функция myfunc (/ * аргументы */) {
}
// назначать анонимные функции локальной переменной myfunc
var myfunc = function (/ * аргументы */) {
}
Обратите внимание, что существуют тонкие различия в двух вышеуказанных методах объявления функций: первый метод - это названная функция при объявлении, независимо от того, является ли это объявленной функцией, после вызова или даже местоположения, где она не будет выполнена (например, после оператора возврата или в филиале, которое никогда не будет истинным), он доступен во всей области; Второй метод состоит в том, чтобы назначить анонимные функции переменным. Строго говоря, это не объявление функции, а выражение функции. Перед присвоением к этой функции не может быть доступна ни каким кодом, что означает, что назначение должно быть завершено до вызова, в противном случае ошибка появится при вызове: «TypeError: не определено не функция». Например:
Кода -копия выглядит следующим образом:
myfunc1 (); // можно назвать нормально, потому что MyFunc1 использует метод прямого объявления
функция myfunc1 () {
}
myfunc2 (); // Ошибка TypeError: неопределенная не является функцией
var myfunc2 = function () {
};
Основной метод вызова функций называется так же, как и на традиционных языках: myfunc (). Функции JavaScript также поддерживают прямые или косвенные рекурсивные вызовы. Например, классическая функция Fibonacci может быть реализована в JavaScript, как это:
Кода -копия выглядит следующим образом:
функция fib (n) {
if (n == 1 || n == 2) {
возврат 1;
} еще {
вернуть Fib (n - 2) + fib (n - 1);
}
}
Функции в JavaScript могут обрабатывать параметры переменной длины. Все они имеют локальную переменную, называемую аргументами внутри функции. Это массивоподобный объект, который содержит все параметры, передаваемые при вызове, и имеет атрибут длины для представления количества параметров. Например:
Кода -копия выглядит следующим образом:
функциональный тест () {
оповещение (Arguments.Length);
}
тест (1); // 1
тест (1, 'a'); // 2
тест (true, [], {}); // 3 Используйте аргументы для реализации функций, аналогичных printf на языке C, а также могут использоваться для реализации полиморфизма методов.
2. Усовершенствованные функции JavaScript
2.1 Анонимные и вложенные функции
В JavaScript вы можете объявить функцию без имени, называемой анонимной функцией (анонимная функция). В то же время JavaScript также позволяет объявлять функции внутри функций, называемых вложенными функциями, а объем вложенных функций является всей родительской функцией.
В предыдущей части объявления функции я увидел использование анонимных функций и вложенных функций. Поскольку анонимные функции не имеют имени, они не будут вводить новые переменные для загрязнения контекста и принесут новые переменные. Следовательно, анонимные функции часто используются для предотвращения глобального загрязнения окружающей среды.
В среде выполнения JavaScript есть специальный глобальный объект. Этот объект хранит глобальные функции и переменные. В реальной разработке часто используются несколько сторонних библиотек или несколько файлов JS. Если вы случайно введете дубликаты переменных или объявлений функций в глобальный объект, это приведет к путанице в выполнении кода. Например, два файла JS введены последовательно, а их собственное журнал функций определяется как внутреннее использование. Вторая представленная функция будет перезаписать определение первого и не бросит никаких ошибок. Вызов функции журнала в последующем выполнении может вызвать ошибку. В настоящее время использование анонимной функции для обертывания логики во всей JS может избежать этой ошибки. Этот метод использовался большинством библиотек JS с открытым исходным кодом.
Кода -копия выглядит следующим образом:
(function () {// анонимная функция
function log (msg) {
console.log (msg);
}
// другие коды
} ()); // выполнить немедленно
Приведенный выше код является простым примером. Объем функции журнала ограничена этой анонимной функцией. Анонимная функция включена в пару кронштейнов () снаружи, чтобы сформировать выражение функции. Значение выражения - это функция, за которой следует пара кронштейнов, чтобы указать, что функция выполняется немедленно, так что исходный код может быть выполнен нормально. Тем не менее, функции, объявленные таким образом, переменные, объявленные через VAR и т. Д., Имеются внутренними и не могут быть доступны каким -либо кодом, кроме анонимных функций. Если вам нужно разоблачить некоторые функции в качестве интерфейсов, есть несколько методов:
Кода -копия выглядит следующим образом:
var mylib = (function (global) {
function log (msg) {
console.log (msg);
}
log1 = log; // Метод 1: Используйте поведение декларации переменных по умолчанию без VAR, чтобы стать глобальной переменной в log1 (не рекомендуется)
Global.log2 = log; // Метод 2: непосредственно добавить атрибут log2 к глобальному объекту и назначить его функции журнала (рекомендуется)
return {// Метод 3: вернуть серию объектов сбора функций интерфейса через анонимные функции и назначить их глобальной переменной Mylib (рекомендуется)
Журнал: журнал
};
}(окно));
2.2 Функция высокого порядка
Если функция используется в качестве параметра или возвращаемого значения, она называется функцией высшего порядка. Функции в JavaScript могут использоваться в качестве функций высшего порядка, что также является функцией первого типа функций. Давайте проанализируем эти два метода использования ниже.
Кода -копия выглядит следующим образом:
функция отрицательно (n) {
возврат -n; // взять противоположное значение n
}
Функция Square (n) {
вернуть n*n; // квадрат n
}
Функциональный процесс (nums, callback) {
var result = [];
for (var i = 0, length = nums.length; i <length; i ++) {
результат [i] = обратный вызов (nums [i]); // Пропустите все элементы в массивах Nums для обратного вызова для обработки, и сохранить возвращаемое значение в результате
}
результат возврата;
}
var nums = [-3, -2, -1, 0, 1, 2, 3, 4];
var n_neg = process (nums, отрицательный);
// n_neg = [3, 2, 1, 0, -1, -2, -3, -4];
var n_square = process (nums, square);
// n_square = [9, 4, 1, 0, 1, 4, 9, 16];
Приведенный выше код показывает пример передачи функции в качестве параметра в другой вызов процесса функции. При реализации функции процесса обратный вызов рассматривается как черный ящик, ответственный за передачу параметра, а затем получение возврата. Конкретная реализация обратного вызова неясна перед вызовом. Только когда выполняется 20 и 22 строки, обратный вызов представлен отрицательным или квадратным, соответственно, и каждый элемент взят с противоположным значением или квадратным значением.
Кода -копия выглядит следующим образом:
функции генератора () {
var i = 0;
return function () {
вернуть i ++;
};
}
var gen1 = генератор (); // Получить натуральный генератор номеров
var gen2 = генератор (); // Получить еще один натуральный генератор номеров
var r1 = gen1 (); // r1 = 0
var r2 = gen1 (); // r2 = 1
var r3 = gen2 (); // r3 = 0
var r4 = gen2 (); // r4 = 1
Приведенный выше код показывает пример использования функции в качестве возвращаемого значения. Генератор является естественной функцией генератора чисел, а возвращаемое значение является функцией генератора естественных чисел. Каждый раз, когда генератор вызовет, анонимная функция будет возвращаться в результате. Эта анонимная функция возвращает каждое естественное число по очереди, когда она фактически вызывается. Переменная I в генераторе увеличится на 1 каждый раз, когда называется эта анонимная функция, что на самом деле является закрытием. Давайте введем закрытие ниже.
2.3 Закрытие
Закрытие не является новой концепцией, и многие функциональные языки используют закрытие. В JavaScript, когда вы используете переменные в области внешних функций во встроенной функции, вы используете закрытие. Используйте обычно используемую аналогию, чтобы объяснить взаимосвязь между закрытием и классом: класс - это данные с функциями, а закрытие - это функция с данными.
Переменные, используемые в закрытии, имеют характеристику, которую они не высвобождаются, когда родительская функция возвращается, но заканчивается концом жизненного цикла закрытия. Например, как в примере генератора в предыдущем разделе, Gen1 и Gen2 Используют независимые переменные I соответственно (когда Gen1's I увеличивается на 1, Gen2's I не буду затронуть, и наоборот). Пока две переменные Gen1 или Gen2 не являются мусором, собранным двигателем JavaScript, их соответствующие переменные, которые я не буду выпущен. В программировании JavaScript закрытие используется неосознанно. Эта особенность закрытия проста в использовании, но также легко приводит к проблемам утечки памяти. Например:
Кода -копия выглядит следующим образом:
var elem = document.getElementbyId ('test');
elem.addeventlistener ('click', function () {
Alert ('Вы нажали » + elem.tagname);
});
Цель этого кода - отображать имя его метки при нажатии на узел. Он регистрирует анонимную функцию в качестве функции обработки событий Click из узла DOM. Элем объекта DOM ссылается на функцию, которая образует закрытие. Это генерирует круговую ссылку, то есть: dom-> clossary-> dom-> clossary ... объект DOM не будет выпущен до того, как закрытие будет выпущено; И закрытие существует как функция обработки событий объекта DOM, поэтому закрытие не будет выпущено до выпуска объекта DOM. Даже если объект DOM удаляется в дереве DOM, из -за существования этой круглой ссылки, ни объект DOM, ни закрытие не будут выпущены. Эту утечки памяти можно избежать, используя следующие методы:
Кода -копия выглядит следующим образом:
var elem = document.getElementbyId ('test');
elem.addeventlistener ('click', function () {
Alert ('вы нажали' + this.tagname); // не более прямо ссылается на elem переменную
});
В приведенном выше коде это используется вместо ELEM (этот указатель указывает на сам элемент DOM в функции обработки событий DOM), так что время выполнения JS больше не считает, что функция использует переменные родительского класса, поэтому больше не формируется закрытие.
Закрытие также принесет много подобных проблем с утечкой памяти. Вы можете обратить внимание только на закрытие только при написании кода и стараться избегать таких проблем.
2.4 Классный конструктор
Функции JavaScript также используются в качестве конструкторов класса, поэтому вы можете использовать новое ключевое слово для создания экземпляра класса, если вы объявляете функцию.
Кода -копия выглядит следующим образом:
Функция человека (имя) {
this.name = name;
this.ToString = function () {
вернуть 'Привет,' + this.name + '!';
};
}
var p = новый человек ('ghosttheaven');
предупреждение (P); // Привет, Ghosttheaven! В приведенном выше примере функция человека используется в качестве конструктора класса. В настоящее время это указывает на недавно созданный объект экземпляра и может добавлять свойства и методы в экземпляр. Для получения подробного объектно-ориентированного программирования JavaScript, пожалуйста, обратитесь к этой статье. Что я хочу сказать здесь, так это проблема возвращаемого значения при использовании функций JavaScript в качестве конструкторов класса.
Кода -копия выглядит следующим образом:
Функция myClass (имя) {
this.name = name;
вернуть имя; // возвращаемое значение конструктора?
}
var obj1 = new myclass ('foo');
var obj2 = myclass ('foo');
var obj3 = new myclass ({});
var obj4 = myclass ({});
Вышеуказанный конструктор является очень особенным, с ответным заявлением, так на какие объекты указывают OBJ1 ~ obj4? Фактический результат заключается в следующем:
Кода -копия выглядит следующим образом:
obj1 = объект myclass
obj2 = 'foo'
obj3 = {}
obj4 = {}
Конкретные причины объясняются в этой статье, и я не буду повторять ее в этой статье. Поскольку конструкторы с возвращающими значениями дадут странные результаты, не вызовите возвратные операторы с возвращающими значениями в конструкторе (может быть сделано пустое возвращение).
3. JavaScript функционирует уровень монстра
Добро пожаловать в область обучения на уровне монстров, где вам будет дано, как спокойно и свободно столкнуться с старым монстром. Полем Полем
3.1 Функциональный класс
В среде выполнения JavaScript есть встроенный класс, называемый функцией. Объявление функции с ключевым словом функции на самом деле является аббревиатурой для создания объектов класса функций. Все функции имеют все методы класса функции, такие как вызов, применение, привязка и т. Д. Вы можете проверить это оператор по ключевым словам экземпляра.
Поскольку функция является классом, его конструктор является функцией (она сама является объектом класса функции), и объект функции должен генерироваться через новое ключевое слово. Первый монстр здесь, как построить функцию, используя класс функций. Синтаксис функции заключается в следующем:
Кода -копия выглядит следующим образом:
Новая функция ([arg1 [, arg2 [, ... argn]],] функция)
где arg1, arg2, ... argn - это строка, представляющая имя параметра, а функциональное тело также является строкой, представляющей корпус функции. Предыдущее имя параметра более или менее. Конструктор функции будет рассматривать последний параметр как корпус функции, а предыдущие - как параметры.
Кода -копия выглядит следующим образом:
var func1 = новая функция («имя», «вернуть» hello, » + name +"! "; ');
func1 ('Ghosttheaven'); // Привет, Ghosttheaven!
Приведенный выше метод создает функцию через функцию, которая точно такой же, как и другие функции, объявленные ключевым словом функции.
Видя это, многие люди могут спросить, почему такой монстр нужен? «То, что существует, разумно», класс функций имеет свою уникальную цель. Вы можете использовать его для динамического генерации различной функциональной логики или заменить функции функции Eval, а также предотвратить загрязнение текущей среды*.
3.2 Функция самостоятельной работы
Во многих языках, как только функция была объявлена, она не может снова объявить функцию с тем же именем, в противном случае возникнут ошибки синтаксиса. Функции в JavaScript можно не только неоднократно объявлять, но и обновлять себя. Монстр, которого я ем, здесь!
Кода -копия выглядит следующим образом:
function selfupdate () {
window.selfupdate = function () {
оповещение («Второй пробег!»);
};
оповещение («Первый забег!»);
}
SelfupDate (); // первый забег!
SelfupDate (); // Второй пробег! Эту функцию можно использовать для логики, которая запускается только один раз, и после первого запуска она заменяется новой логикой.
краткое содержание
Функции JavaScript очень мощные. Прекраснув много проблем, они также вызывают много негативных проблем. Функции уровня монстров обычно используются с малоизвестным использованием. Если это не особенно необходимо, это приведет к тому, что это затруднено чтение кода и повлияет на эффективность развития команды.
* В новой Ecmascript был введен строгий режим. В строгом режиме функция Eval значительно ограничена и может гарантировать, что среда не загрязнена.
Вы понимаете, это очень практично. Если есть какие -то недостающие места, пожалуйста, дайте мне несколько советов и сделайте прогресс вместе.