Полезным будет присмотреться к тому, как порядок выполнения работает с функциями. Вот простая программа с несколькими вызовами функций:
>function greet(who) {
> console.log("Привет, " + who);
>}
>greet("Семён");
>console.log("Покеда");
Обрабатывается она примерно так: вызов >greet
заставляет проход прыгнуть на начало функции. Он вызывает встроенную функцию >console.log
, которая перехватывает контроль, делает своё дело и возвращает контроль. Потом он доходит до конца greet, и возвращается к месту, откуда его вызвали. Следующая строчка опять вызывает >console.log
.
Схематично это можно показать так:
>top
> greet
> console.log
> greet
>top
> console.log
>top
Поскольку функция должна вернуться на то место, откуда её вызвали, компьютер должен запомнить контекст, из которого была вызвана функция. В одном случае, >console.log
должна вернуться обратно в >greet
. В другом, она возвращается в конец программы.
Место, где компьютер запоминает контекст, называется стеком. Каждый раз при вызове функции, текущий контекст помещается наверх стека. Когда функция возвращается, она забирает верхний контекст из стека и использует его для продолжения работы.
Хранение стека требует места в памяти. Когда стек слишком сильно разрастается, компьютер прекращает выполнение и выдаёт что-то вроде “stack overflow” или “too much recursion”. Следующий код это демонстрирует – он задаёт компьютеру очень сложный вопрос, который приводит к бесконечным прыжкам между двумя функциями. Точнее, это были бы бесконечные прыжки, если бы у компьютера был бесконечный стек. В реальности стек переполняется.
>function chicken() {
> return egg();
>}
>function egg() {
> return chicken();
>}
>console.log(chicken() + " came first.");
>// → ??
Следующий код вполне разрешён и выполняется без проблем:
>alert("Здрасьте", "Добрый вечер", "Всем привет!");
Официально функция принимает один аргумент. Однако, при таком вызове она не жалуется. Она игнорирует остальные аргументы и показывает «Здрасьте».
JavaScript очень лоялен по поводу количества аргументов, передаваемых функции. Если вы передадите слишком много, лишние будут проигнорированы. Слишком мало – отсутствующим будет назначено значение >undefined
.
Минус этого подхода в том, что возможно – и даже вероятно – передать функции неправильное количество аргументов, и вам никто на это не пожалуется.
Плюс в том, что вы можете создавать функции, принимающие необязательные аргументы. К примеру, в следующей версии функции power её можно вызывать как с двумя, так и с одним аргументом. В последнем случае экспонента будет равна двум, и функция работает как квадрат.