1

1.

Рекурсия

function pow(x, n) {
 if (n != 1) {
  return x * pow(x, n - 1);
 } else {
  return x;
 }
}

console.log( pow(2, 3) );

Обычная рекурсия. Во время вызова функции создается контекст выполнения. При любом вложенном вызове JavaScript запоминает текущий контекст выполнения в специальной внутренней структуре данных – стеке контекстов. Для нового вызова создаётся свой контекст выполнения, и управление переходит в него, а когда он завершён – старый контекст достаётся из стека и выполнение внешней функции возобновляется. На картинке видны стеки и по ним можно перемещаться, смотреть какие у них были значение в переменных, this. Тут вроде все понятно. Определения брал отсюда: Современный учебник Javascript - Рекурсия, стек.

2.

Рекурсия async

function pow(x, n) {
  if (n != 1) {
    return x * setTimeout(pow, 1000, x, n - 1);
  } else {
    return x;
  }
}

pow(2, 3);

  1. Вызываем функцию pow с аргументами x = 2, n = 3.
  2. Функция pow через return вызывает метода setTimeout с аргументом pow(рекурсия), который возвращает свой id = 1 и по идеи вызов функции должен почиститься. Возможно есть правило, которое предотвращает зачишения функции, и в следствии в консоли будут отображаться стеки, но я ни где не нашел информации по этому поводу.

2.1

async

setTimeout(function pow(x, n) {
  if (n != 1) {
    return x * setTimeout(pow, 1000, x, n - 1);
  } else {
    return x;
  }
}, 2000, 2, 3);

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

Итог:

1. В первом пункте вполне понятно зачем нужны стеки и в принципе как это работает. Стеки принадлежат вызову pow?

2. Тут не понятно почему стеки остаются, так как по идеи вызов pow должен вернуть id и удалиться. Я не утверждаю что это должно быть именно так, но информации я об это не нашел, а с английским все плохо как и с русским(предотвращаю сразу шутки про мою орфографию). Возможно в спецификации об этом что - то сказано W3C или же в API Google Chrome Console. Стеки принадлежат вызову pow?

2.1. Дополнение ко второму пункту. Стеки принадлежат вызову setTimeout?

Хочу разъяснить вопрос по поводу кому принадлежат стеки?. setTimeout это метод (функция), и я осмелился себе предположить что вызов проходит внутри нее.

Вот пример:

пример

function func() {
    function pow(x, n) {
        if (n != 1) {
            return x * pow(x, n - 1);
        } else {
            return x;
        }
    }
 return pow(2, 3);
}

func();

В этом примере рекурсия происходит внутри вызова func и значит стек принадлежит этому же вызову(func). Если внимательно сравнить скриншот вызова через setTimeout, то видно что функция pow которая вызывается асинхронно, как будто вызывается в основном потоке, а не внутри метода setTimeout. Это все мои личные догадки на основе знаний, но так как я не знаю что под капотом, надеюсь вы мне поможете в этом разобраться. И в дополнение хочу еще добавить, что вроде как setTimeout просто создает массив в которой просто храниться очередь, и потом из нее(из очереди) идет уже вызов той функции, которую я туда передал.

Пример:

function func() {
  return 1;
}

setTimeout(func, 2000);

setTimeout(func, 3000)

////////////

var queue = [ { func: function func() { return 1; }, start: new Date, delay: 2000, id: 1 }, { func: function func() { return 1; }, start: new Date, delay: 3000, id: 2 } ];

P.S: До этого я задал похожий вопрос и его сделали дубликатом. Я ознакомился с этим ответом, но он мне не помог. Возможно там объясняется основные понятия асинхронности, которые поменяю всю картину, но я ничего не понял из того что там написано, и в следствии не получил ответ на свой вопрос.

  • кааак мнооого теееекста – Grundy Nov 13 '17 at 08:24
  • Можешь как-то выделить что именно ты спрашиваешь? – Grundy Nov 13 '17 at 08:25
  • Посмотри что именно возвращает setTimeout. – Grundy Nov 13 '17 at 08:27
  • 1
    @Grundy не понимаю почему в консоли стеки. Разве плохо, то что я хочу разобраться? – Виталик Черный Nov 13 '17 at 08:31
  • тоже не понял, что именно он хотел узнать – IC_ Nov 13 '17 at 08:32
  • @виталик где в консоли стеки? – IC_ Nov 13 '17 at 08:33
  • @ВиталикЧерный, то, что хочешь разобраться, не плохо. Просто во втором примере у тебя код возвращает совсем не то, что ты думаешь, поэтому у тебя получаются странные выводы. Посмотри ссылку на дубликат, там написано про асинхронные функции и как получать из них значения, а так же ссылку на описание setTimeout в комментарии выше, чтобы стало понятно, что в твоем коде происходит что-то странное – Grundy Nov 13 '17 at 08:36
  • @Grundy я не нашел что возвращает setTimeout. В дубликате я тоже ничего не нашел. Может вы перестанете мой вопрос делать дубликатом или просто человеческим языком ответите почему так происходит. И хочу заметить, что это были домысли, а не выводы. Прежде чем выносить вердикт, нужно было попробовать прочитать вопрос полностью. – Виталик Черный Nov 13 '17 at 10:04
  • @ВиталикЧерный я не нашел что возвращает setTimeout - var timeoutID = window.setTimeout(code, delay);, timeoutID - это числовой ID, который может быть использован позже с window.clearTimeout(). - надо читать информацию по ссылками, которые дают. – Grundy Nov 13 '17 at 10:05
  • @Grundy я прочитал это и что? Функция pow через return вызывает метода setTimeout с аргументом pow(рекурсия), который возвращает свой id = 1 и по идеи вызов функции должен почиститься. Возможно есть правило, которое предотвращает зачишения функции, и в следствии в консоли будут отображаться стеки, но я ни где не нашел информации по этому поводу. – Виталик Черный Nov 13 '17 at 10:08
  • я прочитал это и что? - то, что ты это значение умножаешь потом на переданный x. – Grundy Nov 13 '17 at 10:14
  • У тебя полностью неверные рассуждения, потому что ты думаешь, что ты можешь попасть внутрь setTimeout – Grundy Nov 13 '17 at 10:16
  • Собственно в случае с setTimeout даже рекурсии нет, потому что setTimeout не вызывает функцию, которую ей передают – Grundy Nov 13 '17 at 10:18
  • @Grundy по поводу попасть внутрь (там есть пример) ...И в дополнение хочу еще добавить, что вроде как setTimeout просто создает "массив" в которой просто храниться очередь, и потом из нее(из очереди) идет уже вызов той функции, которую я туда передал. По воду pow(2, 3); return x * setTimeout(pow, 1000, x, n - 1);: return 2 * 1 = 2 и функция должна очиститься, но на скрине стеки есть, а значит контекст вызова не очистился и ждет возврата значения, ну или я хз как это работает ибо я для этого создал вопрос, и написал свои мысли по этому поводу, что бы было легче объяснять где я не прав. – Виталик Черный Nov 13 '17 at 10:22

0 Answers0