Банальный вопрос по функциям в js

function myFirstApp(name, age) {
  alert(`Привет, меня зовут ${name} и это моя первая программа`);

  function showSkills() {
    let skills = ['html', 'css', 'js'];
    for (let i = 0; i < skills.length; i++) {
      document.write(`Я владею ${skills[i]}`);
    }
  }

  function checkAge() {
    if (age > 18) {
      alert("У тебя отличные шансы!!!");
    } else {
      alert("Тоби !!!!!!!!");
    }
  }

  function calcPow(num) {
    console.log(Math.pow(num, num));
  }
}

myFirstApp("Garry", 48);

Начинаю только учить js. Непонятно, почему здесь вызвались только первая alert() остальные вложенные функции при этом не были выполнены?


Ответы (2 шт):

Автор решения: Павел Петров

function myFirstApp(name, age) {
    alert(`Привет, меня зовут ${name} и это моя первая программа`);

    function showSkills() {
        let skills = ['html', 'css', 'js'];
        for (let i = 0; i < skills.length; i++) {
            document.write(`Я владею ${skills[i]}`);
        }
    }

    function checkAge() {
        if (age > 18) {
            alert("У тебя отличные шансы!!!");
        } else {
            alert("Тоби всё!!!!!!!!");
        }
    }

    function calcPow(num) {
        console.log(Math.pow(num, num));
    }
    showSkills();
    checkAge();
    calcPow(4);
}

Для таких же темных как и я, на будущее)

→ Ссылка
Автор решения: Risto

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

function showSkills() {
    let skills = ['html', 'css', 'js'];
    for (let i = 0; i < skills.length; i++) {
        document.write(`Я владею ${skills[i]}`);
    }
}

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

showSkills();

Второй момент - избыточность вашего кода: функции нужны тогда, когда вы планируете выполнить одно и то же действие несколько раз или с разными параметрами. Однако если задача функции MyFirstApp в том, чтобы просто поочерёдно выполнить вложенные в неё функции, как вы, видимо, и ожидали, то функции там и не нужны. Этот код:

function myFirstApp(name, age) {
    alert(`Привет, меня зовут ${name} и это моя первая программа`);
    let skills = ['html', 'css', 'js'];
    for (let i = 0; i < skills.length; i++) {
        document.write(`Я владею ${skills[i]}`);
    }
    if (age > 18) {
        alert("У тебя отличные шансы!!!");
    } else {
        alert("Тоби всё!!!!!!!!");
    }
    console.log(Math.pow(4, 4));
}
myFirstApp("Garry", 48);

Сделает то же самое, но займёт меньше места.

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

function myFirstApp(name, age) {
    alert(`Привет, меня зовут ${name} и это моя первая программа`);
    showSkills();
    if (age > 18) {
        alert("У тебя отличные шансы!!!");
    } else {
        alert("Тоби всё!!!!!!!!");
    }
    console.log(Math.pow(4, 4));
}
function showSkills() {
    let skills = ['html', 'css', 'js'];
    for (let i = 0; i < skills.length; i++) {
        document.write(`Я владею ${skills[i]}`);
    }
}
myFirstApp("Garry", 48);

Но не так:

function myFirstApp(name, age) {
    alert(`Привет, меня зовут ${name} и это моя первая программа`);
    showSkills();
    console.log(skills[0]); //Ошибка: ReferenceError: skills is not defined
    if (age > 18) {
        alert("У тебя отличные шансы!!!");
    } else {
        alert("Тоби всё!!!!!!!!");
    }
    console.log(Math.pow(4, 4));
}
function showSkills() {
    let skills = ['html', 'css', 'js'];
    for (let i = 0; i < skills.length; i++) {
        document.write(`Я владею ${skills[i]}`);
    }
}
myFirstApp("Garry", 48);

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

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

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

→ Ссылка