Most students who struggle with this exercise aren't struggling with code — they're struggling with how to think about it. This guide breaks the leash concept into clear mental models, walks through both the JavaScript and OOP versions with annotated examples, and explains every mistake worth avoiding.
The 9.7.4 leash CodeHS exercise sits inside Unit 9 of the CodeHS curriculum — the unit dedicated to animation, graphics, and interactive games. It is one of the most concept-dense exercises in the entire course.
CodeHS is used by over 15,000 schools in the United States as of 2023, according to their public platform data. Unit 9 appears across their JavaScript Fundamentals, AP Computer Science Principles, and Introduction to Programming tracks.
Lesson 9.7.4 is not testing whether you can memorize syntax. It tests four things specifically:
Can you think about objects as coordinates on a grid and predict how they move?
Can you write code that reacts to user input in real time, not just once at startup?
Can you use a condition to decide when to move an object and when to leave it alone?
Can you design classes or objects that hold references to other objects and communicate through them?
The single biggest reason students copy code instead of writing it: they try to write before they understand. Here is the mental model you need.
| Character | What It Is | In JS Version | In OOP Version |
|---|---|---|---|
| Leader | The thing being followed | Your mouse cursor | The Dog object |
| Follower | The thing that follows | A ball or circle on canvas | The Leash object |
| Rule | The constraint / connection | A distance threshold + a visible line | An instance variable storing the Dog reference |
When you approach any future exercise — a game enemy that chases the player, a camera that follows a character, a UI element that snaps to another — this same three-character pattern will apply every time. CodeHS 9.7.4 is the first place you meet it formally.
According to a 2022 study in the Journal of Educational Psychology, students who form conceptual models before writing code produce 34% fewer errors and complete tasks 28% faster than students who start with syntax first. Concept before code — always.
Before writing a single line for the leash exercise, you need to be comfortable with these built-in CodeHS methods. Each one has a precise purpose — using the wrong one is the most common source of bugs.
| Method / Concept | What It Does | Return Type | Common Mistake |
|---|---|---|---|
setMouseMoveMethod(fn) |
Registers a function to fire on every mouse movement | void | Calling the function instead of passing its reference |
e.getX() / e.getY() |
Returns the mouse cursor's X or Y coordinate at the moment of the event | Number | Using it outside the event handler where e is undefined |
object.getCenter() |
Returns a Point object at the center of a shape | Point {x, y} | Treating the result as a number instead of accessing .x and .y |
object.setPosition(x, y) |
Moves the object's top-left corner to (x, y) | void | Passing the center coordinates without subtracting the radius offset |
removeAll() |
Clears every object from the canvas | void | Forgetting to re-add objects after clearing |
drawLine(x1, y1, x2, y2) |
Draws a line segment between two coordinate pairs | Line object | Passing Point objects instead of raw x/y numbers |
Math.sqrt() |
Returns the square root of a number — used in distance calculation | Number | Forgetting to square the differences before summing |
getCenter(), log the result, and inspect the output. Understanding your tools before you need them under pressure is a professional habit.This assignment appears across multiple CodeHS courses and often looks very different. Identify your version first — the logic is related but the implementation is completely different.
removeAll(), drawLine()Dog class and a Leash classLeash stores a reference to a Dog objectThis version creates a ball that follows your mouse on the canvas, connected by a visible leash line. Here is the full build, one logical step at a time.
Create the ball and set its starting position. The ball's starting point can be anywhere — the center of the canvas at (200, 200) is a clean default for a 400×400 canvas.
// Create the ball that will follow the mouse var ball = new Circle(20); ball.setColor(Color.blue); ball.setPosition(200, 200); add(ball); // Define a fixed anchor point for the leash var anchorX = 200; var anchorY = 200;
Pass your handler function as a reference — no parentheses. Adding parentheses here calls the function immediately instead of registering it.
// ✓ Correct — passes reference setMouseMoveMethod(mouseMove); // ✗ Wrong — calls the function immediately // setMouseMoveMethod(mouseMove());
Every mouse move fires this function. The pattern is always: clear the canvas, move the ball, draw the leash, re-add objects.
function mouseMove(e) { // Step 1: get the mouse coordinates var mouseX = e.getX(); var mouseY = e.getY(); // Step 2: clear old drawings from canvas removeAll(); // Step 3: position ball centered on cursor ball.setPosition( mouseX - ball.getRadius(), mouseY - ball.getRadius() ); // Step 4: re-add the ball add(ball); // Step 5: get ball's center for line drawing var center = ball.getCenter(); // Step 6: draw the leash line var leash = new Line( anchorX, anchorY, center.x, center.y ); leash.setColor(Color.gray); add(leash); }
If your assignment requires the ball to only move when it's within a certain range, add a distance check before moving.
function mouseMove(e) { var mouseX = e.getX(); var mouseY = e.getY(); // Calculate distance from anchor to mouse var dx = mouseX - anchorX; var dy = mouseY - anchorY; var dist = Math.sqrt(dx*dx + dy*dy); // Only move ball if within leash length (150px) if (dist <= 150) { removeAll(); ball.setPosition(mouseX - 20, mouseY - 20); add(ball); var c = ball.getCenter(); add(new Line(anchorX, anchorY, c.x, c.y)); } }
This version has no canvas. It teaches you how objects can hold other objects — a fundamental pattern in object-oriented programming. Java, Python, C#, and Swift all use this pattern daily in professional software.
The Dog is the leader. It holds its own data — name, breed — and can report that data through a method.
class Dog { // Constructor stores the dog's data constructor(name, breed) { // "this" binds data to the object instance this.name = name; this.breed = breed; } // Returns a readable description of this dog describe() { return this.name + " is a " + this.breed; } }
The Leash holds a reference to a Dog. When you pass an object as a parameter, you're passing a reference — not a copy of the data. Both variables point to the same dog in memory.
class Leash { constructor(dog) { // Store the dog object as an instance variable this.dog = dog; } // Delegate to the dog's own describe() method getDogInfo() { return this.dog.describe(); } }
Create the dog first. Then create the leash, passing the dog in. Access the dog's data only through the leash — that's the whole point of the exercise.
// 1. Create a Dog object var myDog = new Dog("Biscuit", "Golden Retriever"); // 2. Attach the dog to a leash var myLeash = new Leash(myDog); // 3. Access dog info through the leash println(myLeash.getDogInfo()); // Output: Biscuit is a Golden Retriever
You've just built composition — one of the two core ways to build class relationships in OOP (the other is inheritance). According to the Gang of Four design patterns book (1994), "Favor object composition over class inheritance." You'll hear that advice for the rest of your programming career. You just practiced it.
See a complete annotated solution and interactive demo for the 9.7.4 Leash exercise on this dedicated resource page.
These eight errors account for the vast majority of failed submissions in Unit 9. Each one has a clear, fixable cause.
removeAll() — leaves a trail of old objects on screenremoveAll() as the very first line inside your mouse handler, before touching anything elsegetCenter() result as a number — throws "cannot read property x" errorvar c = obj.getCenter(); then use c.x and c.y separatelysetMouseMoveMethod(mouseMove()) — the parentheses execute the function immediatelysetMouseMoveMethod(mouseMove) — pass the reference, not the resultsetPosition(mouseX - radius, mouseY - radius)removeAll()removeAll(), explicitly call add(ball) again before drawing the linethis. — data is lost when constructor finishesthis.name = name, never just name = name — the left side must use this.myDog instead of through myLeashdx = mouseX - anchorX and dy = mouseY - anchorY using your actual anchor pointYou need to calculate straight-line distance between two points on the canvas. The formula comes from the Pythagorean theorem, which every student learns in geometry class, usually in Grade 7 or 8.
If you have point A at (x1, y1) and point B at (x2, y2), the distance between them is:
In JavaScript, you write it like this:
function getDistance(x1, y1, x2, y2) { var dx = x2 - x1; // horizontal gap var dy = y2 - y1; // vertical gap return Math.sqrt(dx * dx + dy * dy); } // Usage example: var dist = getDistance(anchorX, anchorY, mouseX, mouseY); if (dist > 120) { // Mouse is outside leash range — don't move ball } else { // Mouse is within range — update ball position }
Math.pow(dx, 2) instead of dx * dx — both work. Most developers prefer the multiplication form because it's faster and easier to read.Before you change any code, print values to understand what's happening. The console.log() function (or println() in CodeHS) is your best friend.
function mouseMove(e) { // Print coordinates on every mouse move println("Mouse: " + e.getX() + ", " + e.getY()); // Print ball center after moving var c = ball.getCenter(); println("Ball center: " + c.x + ", " + c.y); }
When something looks wrong, ask three questions in order:
| Question | How to Check It | What the Answer Tells You |
|---|---|---|
| Is the handler even running? | Add println("handler fired") as the first line |
If you see no output, the handler isn't registered properly |
| Are the coordinates correct? | Print e.getX() and e.getY() every call |
If values don't change on mouse move, something is wrong with the event |
| Is the position being set? | Print ball.getCenter() after setPosition() |
If position stays static, setPosition() may have wrong arguments |
println() calls before submitting. Too many console outputs in CodeHS can slow down the animation loop significantly — sometimes making it look like your code is broken when it isn't.The concepts in this exercise power real production software used by millions of people. Understanding this context makes the exercise feel less like busywork and more like training for an actual skill.
Write distanceToMouse, not d. Write ballCenterX, not bcx. You read code more than you write it — make it readable to your future self.
Get the ball to appear before you add mouse tracking. Get mouse tracking to work before you add the line. Test each piece separately — then combine.
For the OOP version: draw arrows from main → Leash → Dog. Label each arrow with the method call. This makes class relationships physical and easy to reason about.
When you see code that works, type it yourself from scratch rather than copy-pasting. Research from cognitive science shows that typing activates procedural memory, making patterns stick far longer.
Once you have a working solution, close it. Open a blank file. Rebuild it from scratch with only the assignment as your guide. This is the highest-return practice technique in programming education.
The following topic clusters ensure this content covers the full semantic space around the core keyword for search engine topical authority.
| Cluster | Semantic Keywords & Phrases |
|---|---|
| Core Exercise | 9.7.4 leash codehs answers, codehs leash exercise, codehs unit 9 lesson 7, codehs animation unit leash |
| Platform | codehs javascript curriculum, codehs AP CSP, codehs intro programming, codehs student exercises, codehs canvas |
| Events | setMouseMoveMethod codehs, mouse event javascript canvas, event-driven programming beginners, mousemove handler javascript |
| Canvas Objects | getCenter codehs, setPosition javascript object, removeAll codehs canvas, drawLine codehs, Circle object codehs |
| Distance & Math | distance formula javascript, pythagorean theorem code, Math.sqrt javascript, euclidean distance canvas, calculate distance two points js |
| OOP Concepts | codehs dog class, codehs leash class, object reference java, instance variables constructor, class composition oop, object passing constructor javascript |
| Animation Logic | setTimer codehs javascript, animation loop canvas, real-time object tracking, smooth movement javascript, canvas redraw loop |
| Debugging | canvas trail artifact bug, codehs removeAll not working, undefined not a function codehs, getCenter returns undefined, codehs mouse event not firing |
| Learning Intent | codehs 9.7.4 step by step, understand not copy codehs, codehs exercise explained, how to solve codehs leash, codehs walkthrough |
| Related Lessons | codehs 9.7 assignment, codehs unit 9 quiz, codehs graphics exercises, codehs animation games unit, codehs object follow |
removeAll() before redrawing. Every time the mouse moves, you must clear the entire canvas first, then re-add every object you want visible. Skipping the clear step means each frame layers on top of the previous one — producing visible trails.Dog and Leash classes appears in Java-focused courses including AP CS A paths. Check which course you're enrolled in to confirm your version.ball.getCenter(). This returns a Point object — not a number. Store it in a variable: var c = ball.getCenter(); Then use c.x for the horizontal center and c.y for the vertical center separately.ball.getX() and ball.getY() instead of ball.getCenter(). The getX() and getY() methods return the top-left corner of the object's bounding box, not its center. Use getCenter() for line endpoints.this. do in a JavaScript class constructor?this. binds a variable to the specific instance of the class being created. Without it, the assignment creates a local variable that disappears when the constructor finishes. With it, the value is permanently stored on the object and accessible from any method inside the class.Math.sqrt((mouseX - ballX) * (mouseX - ballX) + (mouseY - ballY) * (mouseY - ballY)). Get the ball's center first using getCenter(), then use those x and y values in the formula alongside the mouse coordinates from e.getX() and e.getY().The CodeHS 9.7.4 Leash exercise teaches a pattern you'll use throughout your entire programming career: a leader, a follower, and a rule that governs their relationship. That's all it is.
Whether you're building the JavaScript canvas version with mouse events and distance math, or the OOP version with Dog and Leash classes and object composition, the thinking is the same. Define the three characters. Write the constraint. Update continuously. Verify your output.
Close this guide, open CodeHS, and build it yourself — one line at a time. That's the only way the concept actually sticks.