How the Python Tutor visualizer can help students in your JavaScript courses

Summary: This article is for instructors who teach JavaScript, whether in high school classrooms (e.g., AP Computer Science Principles), university, or coding bootcamps. Despite its name, Python Tutor is a widely-used web-based visualizer for JavaScript that helps students to understand and debug their code step-by-step. The JavaScript visualizer will always remain free to use.

Read first: one-page quick-start guide for teachers


Python Tutor is a free tool that has been used by tens of millions of people since 2010 to visualize and debug code step-by-step. Despite its name, it visualizes more than just Python: I added JavaScript support back in 2015, and it also does Java and C/C++. This article shows instructors what the JavaScript visualizer can illustrate, from a student's first loop up through closures.

This tool teaches the JavaScript language, not web development. JavaScript is the language that runs in every web browser, and through Node.js it runs on more servers and command-line tools too, which probably makes it the most widely-run programming language in the world. Everything your students will eventually do with HTML, CSS, and the DOM depends on knowing the core language, which is what this tool helps with.

These visualizations also fit into high school AP Computer Science Principles (CSP) curriculum. AP CSP doesn't require any particular programming language (the exam presents code in pseudocode), but JavaScript is one of the most popular choices. Code.org's CSP and CodeHS's AP CSP course both teach using JavaScript.

If you think this tool may be helpful for your colleagues or students, share this direct link in relevant course materials, chat groups, mailing lists, discussion forums, or social media:

The Basics: Variables, Loops, and Conditionals

When students learn their first loops, teachers often have them trace code by hand, keeping a table of each variable's value at each step. Python Tutor does this automatically:

At the current step (Step 12), we're partway through the loop: day is 2 and total is 50.

Types and Coercion

The visualizer shows each value's type: strings display in quotes, numbers don't, and special values like null and undefined display by name. What value does each variable hold when this program ends?

Note how b is the string "12" since + concatenates when either side is a string, but c is the number 9 since - converts both sides to numbers. nothing is null while missing is undefined. And same is false: click "Next >" to run the last line and see that sum prints as 0.30000000000000004, not 0.3.

Functions and the Call Stack

Each function call gets its own frame that holds its parameters and local variables:

Here at Step 7, the second call to priceWithTax is running, and the first call's result (54) already sits in the global variable jeans. Step forward to see this call return 27 and its frame disappear.

Arrays and Aliasing

Here's a classic array aliasing example that trips up beginners:

b = a doesn't copy anything. Both variables now refer to the same array object, and the diagram shows it clearly. In contrast a.slice() creates a real copy, which appears as a second array in the visualization.

The same thing happens when arrays get passed to functions:

In the current step, replaceAll has just reassigned its parameter arr to a brand-new ["coffee"] array, and there are now two distinct arrays.

Objects, Maps, and Sets

Here's an array of two objects:

Map and Set data structures are rendered in a similar way:

Classes and Object-Oriented Programming

The visualizer draws classes, instances, and this inside of method calls:

Here at Step 10, alice.deposit(25) is executing, and the deposit frame's this points at Alice's object.

Here's an example of inheritance and polymorphism:

At Step 18 the loop is calling pets[i].speak() on Rex, so this points at the Dog instance and calls Dog's version of speak(). Step back to Step 12 to see that same call go to Animal's method.

Recursion

Recursion is shown by all active frames on the stack, each with its own copy of the local variables. Here's the classic ultra-cliched factorial:

Higher-Order Functions and Arrow Functions

Functions are values in JavaScript, so they can be passed to other functions. Here applyToEach takes an array and a function f, and applies f to every element:

At Step 14, the global double and the parameter f both point at the same arrow function object (x => x * 2), which is being called with x = 20.

The same kinds of frames appear for built-in array methods like map and filter:

At this step, map has already built a new [ 20, 40, 60 ] array, and filter is calling its arrow function with x = 20.

Closures

The visualizer also supports closures:

Right now makeCounter has already returned, but code can still access its local count variable. The global tickets points at the inner increment function, and each call to tickets() gets a frame with a slot labeled parent:count (this isn't an ideal way to display it, but the older JavaScript debugger we used didn't give more detailed info).

Hoisting and var vs. let

This example shows unexpected behavior if you use var instead of let or const to declare variables:

At the current step (Step 2), the code printed undefined rather than crashing since JavaScript hoists var declarations up to the top of their scope before running it. Click "Edit Code" and change var to let to get more predictable behavior.

What It Does Not Support

Please Help Spread The Word!

The JavaScript visualizer in Python Tutor can help your students see what their code actually does. It's free, it runs in the browser with nothing to install, and it has been used by tens of millions of people.

Feel free to share this direct link in relevant course materials, chat groups, mailing lists, discussion forums, social media, or anywhere else:

And if you also teach Python, Java, or C/C++, check out my companion articles on what the Python visualizer, Java visualizer, and C/C++ visualizer can do.