Javascript reference

Функция jQuery(html,attributes)

Function служит для создания DOM-элемента с параметрами. Необходимый элемент указывается в первом аргументе с помощью HTML-строки. Атрибуты к нему указываются во втором аргументе с помощью объекта JavaScript (PlainObject).

Данный способ вызова функции имеет два параметра:
• html — обязательный параметр типа htmlString, содержит DOM-элемент;
• attributes — необязательный параметр типа PlainObject. Это объект, содержащий атрибуты, методы и события, которые нужно передать создаваемому элементу.

Примечание: необходимо, чтобы HTML-строка начиналась с <, а не с текстовых узлов. Что касается объекта PlainObject, то имя «class» необходимо заключить в кавычки (class — зарезервированное слово JavaScript). Имя «className» использовать тоже нельзя, ведь это имя относится к свойству, а не к атрибуту DOM.

Ключевое слово «this» в методах

Как правило, методу объекта необходим доступ к информации, которая хранится в объекте, чтобы выполнить с ней какие-либо действия (в соответствии с назначением метода).

Например, коду внутри может понадобиться имя пользователя, которое хранится в объекте .

Для доступа к информации внутри объекта метод может использовать ключевое слово .

Значение – это объект «перед точкой», который использовался для вызова метода.

Например:

Здесь во время выполнения кода значением будет являться (ссылка на объект ).

Технически также возможно получить доступ к объекту без ключевого слова , ссылаясь на него через внешнюю переменную (в которой хранится ссылка на этот объект):

…Но такой код будет ненадёжным. Если мы решим скопировать ссылку на объект в другую переменную, например, , и перезапишем переменную чем-то другим, тогда будет осуществлён доступ к неправильному объекту при вызове метода из .

Это показано ниже:

Если мы используем вместо внутри , тогда этот код будет работать.

Создание функций

Существует 3 способа создать функцию. Основное отличие в результате их работы — в том, что именованная функция видна везде, а анонимная — только после объявления:

function имя(параметры) {

}
var имя = function(параметры) {

}

var имя = new Function(параметры, ‘…’)
Именованные функции доступны везде в области видимости Анонимные — доступны только с момента объявления. Синтаксис используется редко, в основном для получения функции из текста, например, динамически загруженного с сервера в процессе выполнения скриптов.
/* функция sum 
определена ниже 
*/
var a = sum(2,2)

function sum(x,y) {
	return x+y
}
/* будет ошибка, 
т.к sum еще не существует
*/
var a = sum(2,2)

var sum = function(x,y) {
	return x+y
}

Functions are Objects

The operator in JavaScript returns «function» for
functions.

But, JavaScript functions can best be described as objects.

JavaScript functions have both properties and
methods.

The property returns the number of arguments received when
the function was invoked:

Example

function myFunction(a, b) {  return arguments.length;}

The method returns the function as a string:

Example

function myFunction(a, b) {  return a * b;}var txt = myFunction.toString();

A function defined as the property of an object, is called a method to the object.
A function designed to create new objects, is called an object constructor.

Остаточные параметры (…)

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

Например:

Лишние аргументы не вызовут ошибку. Но, конечно, посчитаются только первые два.

Остаточные параметры могут быть обозначены через три точки . Буквально это значит: «собери оставшиеся параметры и положи их в массив».

Например, соберём все аргументы в массив :

Мы можем положить первые несколько параметров в переменные, а остальные – собрать в массив.

В примере ниже первые два аргумента функции станут именем и фамилией, а третий и последующие превратятся в массив :

Остаточные параметры должны располагаться в конце

Остаточные параметры собирают все остальные аргументы, поэтому бессмысленно писать что-либо после них. Это вызовет ошибку:

должен всегда быть последним.

Функции-«колбэки»

Рассмотрим ещё примеры функциональных выражений и передачи функции как значения.

Давайте напишем функцию с тремя параметрами:

Текст вопроса
Функция, которая будет вызываться, если ответ будет «Yes»
Функция, которая будет вызываться, если ответ будет «No»

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

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

Аргументы функции ещё называют функциями-колбэками или просто колбэками.

Ключевая идея в том, что мы передаём функцию и ожидаем, что она вызовется обратно (от англ. «call back» – обратный вызов) когда-нибудь позже, если это будет необходимо. В нашем случае, становится колбэком’ для ответа «yes», а – для ответа «no».

Мы можем переписать этот пример значительно короче, используя Function Expression:

Здесь функции объявляются прямо внутри вызова . У них нет имён, поэтому они называются анонимными. Такие функции недоступны снаружи (потому что они не присвоены переменным), но это как раз то, что нам нужно.

Подобный код, появившийся в нашем скрипте выглядит очень естественно, в духе JavaScript.

Функция – это значение, представляющее «действие»

Обычные значения, такие как строки или числа представляют собой данные.

Функции, с другой стороны, можно воспринимать как «действия».

Мы можем передавать их из переменной в переменную и запускать, когда захотим.

Пара вопросов

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

  1. Функция использует внешнюю переменную . Какое значение будет использовать функция при выполнении?

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

    Итак, вопрос в том, получит ли она доступ к последним изменениям?

  2. Функция создаёт другую функцию и возвращает её. Новая функция может быть вызвана откуда-то ещё. Получит ли она доступ к внешним переменным из места своего создания или места выполнения или из обоих?

Объявление функции

Объявлением функции называется указание названия, параметров и исполняемого тела. Поместив объявление в JavaScript переменную оно становится выражением функции.

// Объявление
function function_name() {};
// Выражение
var function_name = function() {};

Все JavaScript объявления браузер обрабатывает до выполнения основного кода. Поэтому следующая запись вызова сработает.

function_name(); //вызов сработает
function function_name(){};

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

function_name(); //вызов НЕ сработает
var function_name = function(){};

Определение функций

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

Идентификатор, определяющий имя функции

Имя является обязательной частью инструкции объявления функции: оно будет использовано для создания новой переменной, которой будет присвоен объект новой функции. В выражениях определения функций имя может отсутствовать: при его наличии имя будет ссылаться на объект функции только в теле самой функции.

Пара круглых скобок вокруг списка из нуля или более идентификаторов, разделенных запятыми

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

Пара фигурных скобок с нулем или более инструкций JavaScript внутри

Эти инструкции составляют тело функции: они выполняются при каждом вызове функции.

В следующем примере показано несколько определений функций в виде инструкций и выражений

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

Инструкция объявления функции фактически объявляет переменную и присваивает ей объект функции

Обратите внимание, что в выражениях определения функций имя функции может отсутствовать. Инструкция объявления функции фактически объявляет переменную и присваивает ей объект функции

Выражение определения функции, напротив, не объявляет переменную. Однако в выражениях определения допускается указывать имя функции, как в функции вычисления факториала выше, которое может потребоваться в теле функции для вызова себя самой. Если выражение определения функции включает имя, данное имя будет ссылаться на объект функции в области видимости этой функции. Фактически имя функции становится локальной переменной, доступной только в теле функции. В большинстве случаев имя функции не требуется указывать в выражениях определения, что делает определения более компактными.

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

Если выражение в инструкции return отсутствует, она возвращает значение undefined. Если инструкция return отсутствует в функции, интерпретатор просто выполнит все инструкции в теле функции и вернет вызывающей программе значение undefined.

Большинство функций в примере вычисляют некоторое значение, и в них инструкция return используется для возврата этого значения вызывающей программе. Функция printprops() несколько отличается в этом смысле: ее работа заключается в том, чтобы вывести имена свойств объекта. Ей не нужно возвращать какое-либо значение, поэтому в функции отсутствует инструкция return. Функция printprops() всегда будет возвращать значение undefined. (Функции, не имеющие возвращаемого значения, иногда называются процедурами.)

Функция jQuery(html[,ownerDocument])

Эта function позволяет создавать DOM-узлы в памяти, что называется «на лету», используя HTML-строку, которую можно передать в качестве аргумента. Способ (метод) вызова функции даёт возможность запустить её с помощью двух параметров:
— html — относится к обязательному параметру типа htmlString. По сути, это строка, содержащая HTML-код;
— ownerDocument — относится к необязательным параметрам типа document.

Принцип работы функции:
— анализируется значение параметров;
— если он выглядит, как HTML-код, функция обрабатывает его с помощью метода $.parseHTML();
— после обработки запускается процесс создания DOM-узлов (применяется браузерный механизм .innerHTML);
— в конечном итоге функция возвращает объект jQuery, включающий созданные DOM-узлы.

Если пользоваться только одним параметром, элементы создаются для текущего документа. Если хотите создать элементы для другого документа, нужно передавать и 1-й, и 2-й параметры.

reduce/reduceRight

Метод «arr.reduce(callback)» используется для последовательной обработки каждого элемента массива с сохранением промежуточного результата.

Это один из самых сложных методов для работы с массивами. Но его стоит освоить, потому что временами с его помощью можно в несколько строк решить задачу, которая иначе потребовала бы в разы больше места и времени.

Метод используется для вычисления на основе массива какого-либо единого значения, иначе говорят «для свёртки массива». Чуть далее мы разберём пример для вычисления суммы.

Он применяет функцию по очереди к каждому элементу массива слева направо, сохраняя при этом промежуточный результат.

Аргументы функции :

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

Кроме , методу можно передать «начальное значение» – аргумент . Если он есть, то на первом вызове значение будет равно , а если у нет второго аргумента, то оно равно первому элементу массива, а перебор начинается со второго.

Проще всего понять работу метода на примере.

Например, в качестве «свёртки» мы хотим получить сумму всех элементов массива.

Вот решение в одну строку:

Разберём, что в нём происходит.

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

Сначала анонимная функция вызывается с этим начальным значением и первым элементом массива, результат запоминается и передаётся в следующий вызов, уже со вторым аргументом массива, затем новое значение участвует в вычислениях с третьим аргументом и так далее.

Поток вычислений получается такой

В виде таблицы где каждая строка – вызов функции на очередном элементе массива:

результат
первый вызов
второй вызов
третий вызов
четвёртый вызов
пятый вызов

Как видно, результат предыдущего вызова передаётся в первый аргумент следующего.

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

Посмотрим, что будет, если не указать в вызове :

Результат – точно такой же! Это потому, что при отсутствии в качестве первого значения берётся первый элемент массива, а перебор стартует со второго.

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

Метод arr.reduceRight работает аналогично, но идёт по массиву справа-налево.

Объявление и вызов функции

Существует три способа объявления функции: Function Declaration, Function Expression и Named Function Expression.

Function Declaration (сокращённо FD) – это «классическое» объявление функции. В JavaScript функции объявляются с помощью литерала функции. Синтаксис объявления FD:

function идентификатор (параметры) { инструкции }

Литерал функции состоит из следующих четырёх частей:

  1. Ключевое слово .
  2. Обязательный идентификатор, определяющий имя функции. В качестве имени функции обычно выбирают глагол, т. к. функция выполняет действие.
  3. Пара круглых скобок вокруг списка из нуля или более идентификаторов, разделяемых запятыми. Данные идентификаторы называются параметрами функции.
  4. Тело функции, состоящее из пары фигурных скобок, внутри которых располагаются инструкции. Тело функции может быть пустым, но фигурные скобки должны быть указаны всегда.

Простой пример:

function sayHi() {
  alert("Hello");
}

Встречая ключевое слово интерпретатор создаёт функцию и затем присваивает ссылку на неё переменной с именем sayHi (переменная с данным именем создаётся интерпретатором автоматически).

Обратившись к переменной можно увидеть, что в качестве значения там находится функция (на самом деле ссылка на неё):

alert(sayHi);   // function sayHi() { alert("Hello"); }

Function Expression (сокращённо FE) – это объявление функции, которое является частью какого-либо выражения (например присваивания). Синтаксис объявления FE:

function (параметры) { инструкции }

Простой пример:

var sayHi = function () {
  alert("Hello");
};

Функцию FE иначе ещё называют «анонимной функцией».

Named Function Expression (сокращённо NFE) – это объявление функции, которое является частью какого-либо выражения (например присваивания). Синтаксис объявления NFE:

function идентификатор (параметры) { инструкции }

Простой пример:

var sayHi = function foo() {
  alert("Hello");
};

Объявления FE и NFE обрабатываются интерпретатором точно так же, как и объявление FD: интерпретатор создаёт функцию и сохраняет ссылку на неё в переменной sayHi.

Программный код, расположенный в теле функции, выполняется не в момент объявления функции, а в момент её вызова. Для вызова функции используется оператор () ():

function sayHi() {
  alert("Hello");
}

var sayHi2 = function () {
  alert("Hello2");
};

var sayHi3 = function foo() {
  alert("Hello3");
};
sayHi();    // "Hello"
sayHi2();   // "Hello2"
sayHi3();   // "Hello3"

Разница между представленными тремя объявлениями заключается в том, что функции, объявленные как FD, создаются интерпретатором до начала выполнения кода (на этапе анализа), поэтому их можно вызывать (в той области видимости где они объявлены) до объявления:

// Вызов функции до её объявления в коде верхнего уровня
foo();

function foo() {
  alert("Вызов функции foo() в глобальной области видимости.");

  // Вызов функции до её объявления в области видимости функции
  bar();
  function bar() {
    alert("Вызов функции bar() в области видимости функции.");
  }
}

Функции, объявленные как FE или NFE, создаются в процессе выполнения кода, поэтому их можно вызывать только после того как они объявлены:

// sayHi();  // Ошибка. Функция sayHi ещё не существует

var sayHi = function () {
  alert("Hello!");
};

sayHi();

Функции, объявленные внутри блока, находятся в блочной области видимости:

// foo();   // Ошибка. Функция не объявлена.
{
  foo();   // 1
  function foo() {
    console.log(1);
  }
}

foo();    // Ошибка. Функция не объявлена.

В отличие от FE, функция, объявленная как NFE, имеет возможность обращаться к себе по имени при рекурсивном вызове. Имя функции доступно только внутри самой функции:

(function sayHi(str) {
  if (str) { return; }
  sayHi("hi");   // Имя доступно внутри функции
})();

sayHi();         // Ошибка. Функция не объявлена

Parameter Values

Parameter Description
functionName Required. Specifies the name of the function, which can be «saved for later use». Function names can contain letters, digits, underscores, and dollar signs (same rules as variables)
parameters Optional. Specifies a set of zero or more parameter names, separated by commas. Function parameters are the names listed in the function definition.Function arguments are the real values received by the function when it is invoked. Inside the function, the arguments are used as local variables.Note: If a function is called with a missing argument, the value of the missing argument is set to
undefined

«Поднятие» переменных и функций

Интерпретатор JavaScript всегда перемещает («поднимает») объявления функций и переменных в начало области видимости. Если переменная определена внутри функции, она поднимается к верхней части функции, а если переменная определена глобально — к верхней части глобального контекста. Рассмотрим, что это значит на примере:

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

В случае с функциями, поднимается вся функция целиком, если речь идет о функциях-объявлениях (declaration); функция-выражение (expression) не поднимается:

В этом этом примере поднимается только функция . Идентификатор «anomFunc» (переменная, которой присвоена функция) также поднимается, но сама анонимная функция при этом остаётся на месте (как и в случае с пременной).

«this» не является фиксированным

В JavaScript ключевое слово «this» ведёт себя иначе, чем в большинстве других языков программирования. Оно может использоваться в любой функции.

В этом коде нет синтаксической ошибки:

Значение вычисляется во время выполнения кода и зависит от контекста.

Например, здесь одна и та же функция назначена двум разным объектам и имеет различное значение «this» при вызовах:

Правило простое: при вызове значение внутри равно . Так что, в приведённом примере это или .

Вызов без объекта:

Мы даже можем вызвать функцию вовсе без использования объекта:

В строгом режиме () в таком коде значением будет являться . Если мы попытаемся получить доступ к , используя – это вызовет ошибку.

В нестрогом режиме значением в таком случае будет глобальный объект ( для браузера, мы вернёмся к этому позже в главе Глобальный объект). Это – исторически сложившееся поведение , которое исправляется использованием строгого режима ().

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

Последствия свободного

Если вы до этого изучали другие языки программирования, тогда вы, скорее всего, привыкли к идее «фиксированного » – когда методы, определённые внутри объекта, всегда сохраняют в качестве значения ссылку на свой объект (в котором был определён метод).

В JavaScript является «свободным», его значение вычисляется в момент вызова метода и не зависит от того, где этот метод был объявлен, а зависит от того, какой объект вызывает метод (какой объект стоит «перед точкой»).

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

Здесь мы не будем судить о том, является ли это решение в языке хорошим или плохим. Мы должны понимать, как с этим работать, чтобы получать выгоды и избегать проблем.

Решение 2: привязать контекст с помощью bind

В современном JavaScript у функций есть встроенный метод bind, который позволяет зафиксировать .

Базовый синтаксис :

Результатом вызова является особый «экзотический объект» (термин взят из спецификации), который вызывается как функция и прозрачно передаёт вызов в , при этом устанавливая .

Другими словами, вызов подобен вызову с фиксированным .

Например, здесь передаёт вызов в , фиксируя :

Здесь – это «связанный вариант» , с фиксированным .

Все аргументы передаются исходному методу как есть, например:

Теперь давайте попробуем с методом объекта:

В строке мы берём метод и привязываем его к . Теперь – это «связанная» функция, которая может быть вызвана отдельно или передана в (контекст всегда будет правильным).

Здесь мы можем увидеть, что исправляет только , а аргументы передаются как есть:

Удобный метод:

Если у объекта много методов и мы планируем их активно передавать, то можно привязать контекст для них всех в цикле:

Некоторые JS-библиотеки предоставляют встроенные функции для удобной массовой привязки контекста, например в lodash.

Локальные переменные функции

В функцию могут входить и локальные переменные (объявляются через var). Они видны только внутри функции:

function showMessage() {
  var message = 'Привет, моё имя — Петя!'; // это локальная переменная
  alert( message );
}
showMessage(); // 'Привет, моё имя — Петя!'
alert( message ); // <-- здесь ошибка, ведь переменная видна только внутри функции

Помните, что блоки while, switch, for, if/else, do..while никак не влияют на зону видимости переменных, то есть при объявлении переменных в данных блоках они будут видны во всей функции. Пример:

       function count() {
  // переменные i и j не будут удалены по окончании цикла
  for (var i = ; i < 3; i++) {
    var j = i * 2;
  }
  alert( i ); // i=3, последнее значение i, цикл при нём перестал работать
  alert( j ); // j=4, последнее значение j, которое цикл вычислил
}

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

function count() {
  var i, j; // здесь мы передвинули объявление var в начало
  for (i = ; i < 3; i++) {
    j = i * 2;
  }
  alert( i ); // i=3
  alert( j ); // j=4
}

Итого

  • Функции – это значения. Они могут быть присвоены, скопированы или объявлены в другом месте кода.
  • Если функция объявлена как отдельная инструкция в основном потоке кода, то это Function Declaration.
  • Если функция была создана как часть выражения, то считается, что эта функция объявлена при помощи Function Expression.
  • Function Declaration обрабатываются перед выполнением блока кода. Они видны во всём блоке.
  • Функции, объявленные при помощи Function Expression, создаются, только когда поток выполнения достигает их.

В большинстве случаев, когда нам нужно создать функцию, предпочтительно использовать Function Declaration, т.к. функция будет видима до своего объявления в коде. Это позволяет более гибко организовывать код, и улучшает его читаемость.

Таким образом, мы должны прибегать к объявлению функций при помощи Function Expression в случае, когда синтаксис Function Declaration не подходит для нашей задачи. Мы рассмотрели несколько таких примеров в этой главе, и рассмотрим их ещё больше в будущем.

Итого

Основные улучшения в функциях:

  • Можно задавать параметры по умолчанию, а также использовать деструктуризацию для чтения приходящего объекта.
  • Оператор spread (троеточие) в объявлении позволяет функции получать оставшиеся аргументы в массив: .
  • Тот же оператор spread в вызове функции позволяет передать в неё массив как список аргументов (вместо ).
  • У функции есть свойство , оно содержит имя, указанное при объявлении функции, либо, если его нет, то имя свойства или переменную, в которую она записана. Есть и некоторые другие ситуации, в которых интерпретатор подставляет «самое подходящее» имя.
  • Объявление Function Declaration в блоке видно только в этом блоке.
  • Появились функции-стрелки:
    • Без фигурных скобок возвращают выражение : .
    • С фигурными скобками требуют явного .
    • Не имеют своих и , при обращении получают их из окружающего контекста.
    • Не могут быть использованы как конструкторы, с .
Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Adblock
detector