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.
function pow(x, n) {
if (n != 1) {
return x * setTimeout(pow, 1000, x, n - 1);
} else {
return x;
}
}
pow(2, 3);
- Вызываем функцию pow с аргументами
x = 2,n = 3. - Функция
powчерез return вызывает методаsetTimeoutс аргументомpow(рекурсия), который возвращает свойid = 1и по идеи вызов функции должен почиститься. Возможно есть правило, которое предотвращает зачишения функции, и в следствии в консоли будут отображатьсястеки, но я ни где не нашел информации по этому поводу.
2.1
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: До этого я задал похожий вопрос и его сделали дубликатом. Я ознакомился с этим ответом, но он мне не помог. Возможно там объясняется основные понятия асинхронности, которые поменяю всю картину, но я ничего не понял из того что там написано, и в следствии не получил ответ на свой вопрос.




setTimeout. – Grundy Nov 13 '17 at 08:27setTimeoutв комментарии выше, чтобы стало понятно, что в твоем коде происходит что-то странное – Grundy Nov 13 '17 at 08:36setTimeout. В дубликате я тоже ничего не нашел. Может вы перестанете мой вопрос делать дубликатом или просто человеческим языком ответите почему так происходит. И хочу заметить, что это были домысли, а не выводы. Прежде чем выносить вердикт, нужно было попробовать прочитать вопрос полностью. – Виталик Черный Nov 13 '17 at 10:04Функция pow через return вызывает метода setTimeout с аргументом pow(рекурсия), который возвращает свой id = 1 и по идеи вызов функции должен почиститься. Возможно есть правило, которое предотвращает зачишения функции, и в следствии в консоли будут отображаться стеки, но я ни где не нашел информации по этому поводу.– Виталик Черный Nov 13 '17 at 10:08x. – Grundy Nov 13 '17 at 10:14setTimeout– Grundy Nov 13 '17 at 10:16...И в дополнение хочу еще добавить, что вроде как setTimeout просто создает "массив" в которой просто храниться очередь, и потом из нее(из очереди) идет уже вызов той функции, которую я туда передал.По водуpow(2, 3); return x * setTimeout(pow, 1000, x, n - 1);: return 2 * 1 = 2 и функция должна очиститься, но на скрине стеки есть, а значит контекст вызова не очистился и ждет возврата значения, ну или я хз как это работает ибо я для этого создал вопрос, и написал свои мысли по этому поводу, что бы было легче объяснять где я не прав. – Виталик Черный Nov 13 '17 at 10:22