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

Структуры данных стека следуют принципу «Последним пришел — первым ушел» (или «Первым пришел — последним ушел», в зависимости от того, что поможет вам легче запомнить), что означает, что элементы, вставленные в структуру последними, удаляются первыми. Думайте об этом как о своей любимой банке Pringles; те, что наверху, должны быть обработаны (или съедены) в первую очередь, даже если первыми были добавлены нижние чипсы. Эта аналогия также работает со стопкой тарелок, банкой с теннисными мячами и, честно говоря, со всем, что ставится друг на друга.

Push, pop — это основные функции стека. Когда мы вставляем элемент на вершину стека, это называется операцией push. С другой стороны, если мы удаляем элемент из вершины стека, мы используем операцию pop. Мы также должны проверить состояние стека, и это делается с помощью следующих функций:

  • Peek(): возвращает элемент наверху стека, не удаляя его.
  • isFull(): возвращает true, если стек заполнен. Это гарантирует, что мы не находимся в состоянии переполнения, которое происходит, когда мы вызываем операцию push с полным массивом.
  • isEmpty(): возвращает true, если стек заполнен. Это гарантирует, что мы не находимся в состоянии аннулирования, возникающем, когда мы вызываем операцию извлечения с пустым массивом.

В приведенном ниже примере мы можем увидеть это в действии. Мы помещаем три элемента в стек, и когда мы пытаемся удалить элемент, первый элемент, который он принимает, будет последним, который мы добавили в стек.

Использование кнопок отмены и повтора в любом программном обеспечении для редактирования — отличный пример стеков, которые мы используем в нашей повседневной жизни. В этой ситуации у нас есть два стека — стек Undo и стек Redo. Когда пользователь выполняет действия, мы помещаем каждую операцию в стек отмены. Когда мы делаем ошибку, мы можем вызвать функцию Undo, и это извлечет операцию из стека Undo, а затем поместит ее в стек Redo. Использовали кнопку отмены слишком много раз? Мы можем вызвать нашу функцию повтора, которая извлекает операцию из стека повторов и помещает ее в стек отмены. Выполнение любых новых действий очищает стек повторов.

JavaScript и стек вызовов

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

В нашем примере мы ищем площадь треугольника. У нас есть вспомогательная функция product, и она вызывается внутри нашей функции areaOfTriangle. Наш стек вызовов будет следующим:

  1. Когда интерпретатор JavaScript запускает код, он создает функцию main() и помещает ее в начало стека вызовов. Это обозначает глобальный контекст выполнения.
  2. Затем он запускает вызов нашей функции areaOfTriangle(3, 5), и контекст выполнения функции для этой функции области помещается в стек вызовов.
  3. Движок выполняет нашу функцию areaOfTriangle(), и это вызывает нашу функцию product(). Затем это создает еще один контекст выполнения функции для нашей функции product().
  4. Эта функция product() выполняется, возвращая произведение двух входных данных, переданных в areaOfTriangle. Затем он удаляется из стека вызовов.
  5. Наша функция AreaOfTriangle() выполняется, затем движок извлекает ее из стека вызовов.
  6. Наконец, скрипт завершает выполнение, потому что в нашем стеке вызовов ничего не осталось.

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

Если это все еще не совсем ясно, это нормально; Я был в таком же положении не так давно. Просто продолжайте кодировать, и все в конечном итоге соберется воедино. Практика делает совершенным, и эта идиома, хотя и очень клише, наиболее актуальна для такого навыка, как программирование. Удачи и удачного кодирования!