Руководство по javascript, часть 4: функции

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

В функцию могут входить и локальные переменные (объявляются через 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 Declaration».

  • Function Declaration – функция, объявленная в основном потоке кода.
  • Function Expression – объявление функции в контексте какого-либо выражения, например присваивания.

Несмотря на немного разный вид, по сути две эти записи делают одно и то же:

Оба этих объявления говорят интерпретатору: «объяви переменную , создай функцию с указанными параметрами и кодом и сохрани её в «.

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

Поэтому их можно вызвать до объявления, например:

А если бы это было объявление Function Expression, то такой вызов бы не сработал:

Это из-за того, что JavaScript перед запуском кода ищет в нём Function Declaration (их легко найти: они не являются частью выражений и начинаются со слова ) и обрабатывает их.

А Function Expression создаются в процессе выполнения выражения, в котором созданы, в данном случае – функция будет создана при операции присваивания

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

Можно расположить функции внизу, а их вызов – сверху или наоборот.

В некоторых случаях «дополнительное удобство» Function Declaration может сослужить плохую службу.

Например, попробуем, в зависимости от условия, объявить функцию по-разному:

Function Declaration при видны только внутри блока, в котором объявлены. Так как код в учебнике выполняется в режиме , то будет ошибка.

А что, если использовать Function Expression?

Или даже так:

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

Взглянем ещё на один пример – функцию с тремя параметрами:

Строка-вопрос
Функция
Функция

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

Какой-то очень простой код, не правда ли? Зачем, вообще, может понадобиться такая ?

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

Здесь же обратим внимание на то, что то же самое можно написать более коротко:

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

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

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

Такого рода код возникает естественно, он соответствует «духу» JavaScript.

8) getElementsByClass()

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

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

if(document.getElementsByClassName) {

	getElementsByClass = function(classList, node) {    
		return (node || document).getElementsByClassName(classList)
	}

} else {

	getElementsByClass = function(classList, node) {			
		var node = node || document,
		list = node.getElementsByTagName('*'), 
		length = list.length,  
		classArray = classList.split(/\s+/), 
		classes = classArray.length, 
		result = [], i,j
		for(i = 0; i < length; i++) {
			for(j = 0; j < classes; j++)  {
				if(list.className.search('\\b' + classArray + '\\b') != -1) {
					result.push(list)
					break
				}
			}
		}
	
		return result
	}
}
classList
Список классов, разделенный пробелами, элементы с которыми нужно искать.
node
Контекст поиска, внутри какого узла искать

Например:

var div = document.getElementById("mydiv")
elements = getElementsByClass('class1 class2', div)

Ссылки в JS

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

Самый простой метод, позволяющий осуществлять вызов — вывод alert в ссылке. Пример такой ссылки (ссылку можно запустить без проблем из любого браузера):

<a href = "javascript:alert('Привет Мир!');">Вызов ссылки</a> 

Второй метод вызова ссылки имеет более сложную конструкцию. В этом случае ссылку можно сделать с помощью функции document.write(). А оформить такую ссылку можно следующим образом:

<script type="text/javascript">document.write('<a href="http://otus.ru/">текст ссылки</a>');</script>

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

<script type="text/javascript">
desiredText = desiredLink =    'http://otus.ru/';
document.write('<a href="'+desiredLink+'">'+desiredText+'</a>');
</script>

Кроме того, можно вызывать ссылку через таблицу, div, ячейку таблицы и путём использования другого метода. Собственно говоря, использование этих методов для передачи ссылок — довольно странное занятие, если вспомнить, что у нас есть простые, эффективные и всем понятные решения с html и php.

Функции-генераторы в «ES6»

Еще одно новое определение функции из стандарта «ES6» — функция-генератор. Она способна остановить и продолжить выполнение.

function *function_name(){}

Функция-генератор создаёт итератор (повторитель). Метод итератора «next» используется для выполнения кода внутри функции-генератора до тех пор, пока не будет достигнуто ключевое слово «yield». Затем значение после слова «yield» возвращается и выполнение приостанавливается.

Если ключевое слово «yield» не достигается, то происходит возврат значения «undefined» и выполнение итератора дальше не происходит.

function *randomIncrement(i) {
 yield i + 3;
 yield i + 5;
 yield i + 10;
 yield i + 6;
}
var itr = randomIncrement(4);
console.log(itr.next().value); //7
console.log(itr.next().value); //9
console.log(itr.next().value); //14

Функции-генераторы полезны если требуется перебрать значения один за другим в разных точках кода, приостанавливая перебор.

Свойства функции

Функция в JavaScript является объектом, поэтому можно присваивать свойства прямо к ней, вот так:

Свойства функции не стоит путать с переменными и параметрами. Они совершенно никак не связаны. Переменные доступны только внутри функции, они создаются в процессе её выполнения. Это – использование функции «как функции».

А свойство у функции – доступно отовсюду и всегда. Это – использование функции «как объекта».

Если хочется привязать значение к функции, то можно им воспользоваться вместо внешних переменных.

В качестве демонстрации, перепишем пример со счётчиком:

При запуске пример работает также.

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

Например, можно взять и поменять счётчик из внешнего кода:

Статические переменные

Иногда свойства, привязанные к функции, называют «статическими переменными».

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

Лексическое окружение

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

Мы будем называть этот объект «лексическое окружение» или просто «объект переменных».

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

В отличие от , объект является внутренним, он скрыт от прямого доступа.

Посмотрим пример, чтобы лучше понимать, как это работает:

При вызове функции:

  1. До выполнения первой строчки её кода, на стадии инициализации, интерпретатор создаёт пустой объект и заполняет его.

    В данном случае туда попадает аргумент и единственная переменная :

  2. Функция выполняется.

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

  3. В конце выполнения функции объект с переменными обычно выбрасывается и память очищается. В примерах выше так и происходит. Через некоторое время мы рассмотрим более сложные ситуации, при которых объект с переменными сохраняется и после завершения функции.

Тонкости спецификации

Если почитать спецификацию ECMA-262, то мы увидим, что речь идёт о двух объектах: и .

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

Более формальное описание находится в спецификации ECMA-262, секции 10.2-10.5 и 13.

Рекурсивная функция javascript

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

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

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

Для организации рекурсии необходимо наличие нескольких условий:

  • начальное условие (известное значение для переменной, отправной момент рекурсии);
  • рекурсивное правило;
  • условие окончания рекурсии.

Рекурсия javascript рассмотрена ниже на примере возведения числа в степень.Для начала рассмотрим итерационный вариант возведения в степень, т.е. с использованием :

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

Показать решение:

1
2
3
4
5
6
7
8
var chislo,stepen;
function degree(chislo,stepen) { 
	for(var result = 1; stepen > ; stepen--) {
 		result *= chislo; 
	} 
return  result;
} 
document.write(degree(2,4)); // выводит 16

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

2 в степени 4 = 16

Решение: 

  • Объявите глобальные переменные для числа и степени и запросите их:
var chislo,stepen;
chislo = parseInt(prompt('число: '));
stepen = parseInt(prompt('степень: '));

Создайте функцию с двумя аргументами для числа и степени:

function degree(chislo,stepen) { 
}

Поскольку известно, что любое число в степени 0 равно единице, то сделаем это начальным условием. То есть если степень = 0, то функция возвращает 1:

function degree(chislo,stepen) { 
	if(stepen) { 
…
	} 
	return 1; // если степень равна нулю то возвращаем 1
}

Создадим рекуррентное правило: если степень не равна 0, то нужно число умножить на число в степени на единицу меньше (вызов функции со степенью на единицу меньше):

function degree(chislo,stepen) { 
	if(stepen) { 
		return chislo*degree(chislo,stepen-1); 
	} 
	return 1; 
}

Вызовите функцию, оформив вывод:

document.write(chislo,' в степени ', stepen, ' = ', degree(chislo,stepen));

Протестируйте результат в браузере.

Задание js4_11. Что выведет на экран следующий код?

1
2
3
4
5
6
7
8
function f(counter) {
  counter--;
  document.write(counter + "<br/>");
  if (counter != )
    f(counter);
  document.write(counter + "<br/>");
}
f(2);

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

Пример: Вычисление факториала числа итерационным методом с использованием :

Показать решение:

1
2
3
4
5
6
7
8
9
10
11
var m = 2;
x = factorial(m);
document.write(x);
function factorial(n){
 if(n <= 1) return 1;
 rezult = 2; // result - переменная для результата
 for (i = 3; i <=n; i++) {
	rezult = rezult*i;
 }
return result;
}

Вопросы для самоконтроля:

  1. Что такое рекурсия?
  2. Назовите основные условия организации рекурсии, как вы их понимаете?

Области видимости

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

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

В отличие от ряда языков, блоки не задают отдельную область видимости. Без разницы — определена переменная внутри блока или вне его. Так что эти два фрагмента совершенно эквивалентны:

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

Например:

function a() {
	z = 5 // поменяет z локально.. 

	// .. т.к z объявлена через var
	var z
}

// тест
delete z // очистим на всякий случай глобальную z
a()

alert(window.z)  // => undefined, т.к z была изменена локально

Внутренняя реализация: Ссылочный тип

Продвинутая возможность языка

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

Если вы хотите продвигаться быстрее, его можно пропустить или отложить.

Некоторые хитрые способы вызова метода приводят к потере значения , например:

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

Затем метод тут же вызывается с помощью скобок . Но вызов не работает как положено!

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

Так работает (доступ к методу объекта через точку):

Так уже не работает (вызываемый метод вычисляется):

Почему? Если мы хотим понять, почему так происходит, давайте разберёмся (заглянем под капот), как работает вызов методов ().

Присмотревшись поближе, в выражении можно заметить две операции:

  1. Сначала оператор точка возвращает свойство объекта – его метод ().
  2. Затем скобки вызывают этот метод (исполняется код метода).

Итак, каким же образом информация о передаётся из первой части во вторую?

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

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

Для работы вызовов типа , JavaScript использует трюк – точка возвращает не саму функцию, а специальное значение «ссылочного типа», называемого .

Этот ссылочный тип (Reference Type) является внутренним типом. Мы не можем явно использовать его, но он используется внутри языка.

Значение ссылочного типа – это «триплет»: комбинация из трёх значений , где:

  • – это объект.
  • – это имя свойства объекта.
  • – это режим исполнения. Является true, если действует строгий режим ().

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

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

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

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

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

Параметры, которые можно вызвать функцией

При вызове function ей можно отправить данные для обработки. Например, нижеследующий код выведет 2 сообщения:

 function showMessage(from, text) { // параметры from, text
 from = "** " + from + " **"; // здесь вставляем сложный код оформления
 alert(from + ': ' + text);
}
showMessage('Петя', 'Привет!');
showMessage('Петя', 'Как дела?');

Помните, что когда код будет передан, параметры скопируются в локальные переменные. Также функцию можно вызвать практически с любым количеством аргументов, а если при вызове параметр не будет передан, он считается равным undefined. К примеру, функцию отображения сообщений showMessage(from, text) можно без проблем вызвать, используя один аргумент:

showMessage("Петя");

super

В ES-2015 появилось новое ключевое слово . Оно предназначено только для использования в методах объекта.

Вызов позволяет из метода объекта получить свойство его прототипа.

Например, в коде ниже наследует от .

Вызов из метода объекта обращается к :

Как правило, это используется в классах, которые мы рассмотрим в следующем разделе, но важно понимать, что «классы» здесь на самом деле ни при чём. Свойство работает через прототип, на уровне методов объекта

При обращении через используется текущего метода, и от него берётся . Поэтому работает только внутри методов.

В частности, если переписать этот код, оформив как обычное свойство-функцию, то будет ошибка:

Ошибка возникнет, так как теперь обычная функция и не имеет . Поэтому в ней не работает .

Исключением из этого правила являются функции-стрелки. В них используется внешней функции. Например, здесь функция-стрелка в берёт внешний :

Ранее мы говорили о том, что у функций-стрелок нет своего , : они используют те, которые во внешней функции. Теперь к этому списку добавился ещё и .

Свойство – не изменяемое

При создании метода – он привязан к своему объекту навсегда. Технически можно даже скопировать его и запустить отдельно, и продолжит работать:

В примере выше метод запускается отдельно от объекта, но всё равно, благодаря , сохраняется доступ к его прототипу через .

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Named Function Expression

Named Function Expression или NFE – это термин для Function Expression, у которого есть имя.

Например, давайте объявим Function Expression:

И присвоим ему имя:

Чего мы здесь достигли? Какова цель этого дополнительного имени ?

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

Добавление такого имени ничего не ломает.

Функция все ещё доступна как :

Есть две важные особенности имени , ради которого оно даётся:

  1. Оно позволяет функции ссылаться на себя же.
  2. Оно не доступно за пределами функции.

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

Почему мы используем ? Почему просто не использовать для вложенного вызова?

Вообще, обычно мы можем так поступить:

Однако, у этого кода есть проблема, которая заключается в том, что значение может быть изменено. Функция может быть присвоена другой переменной, и тогда код начнёт выдавать ошибки:

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

Необязательное имя, которое можно вставить в Function Expression, как раз и призвано решать такого рода проблемы.

Давайте используем его, чтобы исправить наш код:

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

Внешний код все ещё содержит переменные и , но теперь – это «внутреннее имя функции», таким образом она может вызвать себя изнутри.

Это не работает с Function Declaration

Трюк с «внутренним» именем, описанный выше, работает только для Function Expression и не работает для Function Declaration. Для Function Declaration синтаксис не предусматривает возможность объявить дополнительное «внутреннее» имя.

Зачастую, когда нам нужно надёжное «внутреннее» имя, стоит переписать Function Declaration на Named Function Expression.

В интернете кто-то не прав

Все началось с простого вопроса в канале Telegram для изучающих JavaScript, в котором, помимо всего прочего, появился вопрос касательно обработчиков событий в браузере. Вопрос был в том, как они «навешиваются» и «снимаются» с DOM-элемента. Среди ответов от вполне опытного разработчика был следующий:

Далее ответ был подкреплен блоком кода похожим на этот:

element.addEventListener('click', function() { /* .. */ })element.removeEventListener('click', function() { /* .. */ })

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

const handleClick = () => { /* */ }element.addEventListener('click', handleClick)element.removeEventListener('click', handleClick)

Arrow Functions

Arrow functions allows a short syntax for writing function expressions.

You don’t need the keyword, the keyword, and the
curly brackets.

// ES5
var x = function(x, y) {
 
return x * y;
}
// ES6
const x = (x, y) => x * y;

Arrow functions do not have their own .
They are not well suited for defining object methods.

Arrow functions are not hoisted. They must be defined before they are used.

Using
is safer than using , because a function expression is
always constant value.

You can only omit the keyword and the curly brackets if the function is a single statement.
Because of this, it might be a good habit to always keep them:

JavaScript Функции

Функция (function) – это самостоятельный фрагмент кода, решающий определенную задачу. Каждой функции присваивается уникальное имя, по которому ее можно идентифицировать и «вызвать» в нужный момент.

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

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

Проблема «несуществующего свойства»

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

Например, рассмотрим объекты для пользователей . У большинства пользователей есть адрес с улицей , но некоторые адрес не указали.

В этом случае при попытке получить свойство будет ошибка:

Это нормальный результат, так работает JavaScript, но во многих реальных ситуациях удобнее было бы получать не ошибку, а просто («нет улицы»).

Или ещё пример. В веб-разработке нам бывает нужно получить данные об HTML-элементе, который иногда может отсутствовать на странице:

До появления в языке для решения подобных проблем использовался оператор .

Например:

Использование логического И со всей цепочкой свойств гарантирует, что все они существуют (а если нет – вычисление прекращается), но это довольно длинная и громоздкая конструкция.

Добавить комментарий

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

Adblock
detector