Backbone.js Explained — Lightweight JavaScript Framework Guide
Backbone.js gives structure to JavaScript-heavy web applications by providing Models with key-value binding, Collections with a rich API, Views with declarative event handling, and seamless RESTful API synchronization — all in about 7KB.
What You’ll Learn
- What Backbone.js is and why it’s called a “library” rather than a full framework
- How Models store data and sync with REST APIs automatically
- How Collections group Models and provide query utilities
- How Views render data and handle user events
- How Routers enable bookmarkable URLs in single-page apps
- How the event system connects all the pieces together
Why Backbone.js Matters
When Backbone.js was created in 2010, web applications were becoming increasingly interactive but most code was “spaghetti jQuery” — event handlers scattered everywhere, data updates manually syncing to the DOM. Backbone introduced a simple but powerful idea: separate your data (Models) from your display (Views) and let events connect them automatically. This pattern is still the foundation of modern frameworks like React and Vue. Understanding Backbone teaches you the architectural principles that power today’s tools. At DodaTech, the same separation of concerns powers Durga Antivirus Pro’s scanning dashboard — threat data lives in a model, the UI watches for changes, and neither needs to know about the other.
flowchart LR
A[JavaScript & jQuery Basics] --> B[Backbone.js Fundamentals]
B --> C[Models & Data]
B --> D[Views & UI]
C --> E[Collections]
D --> E
E --> F[Routers & History]
F --> G[Structured SPA]
style B fill:#4a90d9,color:#fff
Core Components — The Building Blocks
Backbone has four main components, each serving a specific role. Think of them as departments in a company: Models handle the data (accounting), Collections manage groups (HR), Views handle display (marketing), and Routers handle navigation (reception).
Models — The Data Layer
A Model represents a single piece of data — like one user, one task, or one product.
// Define a Model type with default values and behavior
const Task = Backbone.Model.extend({
// Default values for new instances
defaults: {
title: "",
completed: false
},
// Custom method — toggle the completed status
toggle() {
// get() reads a property, save() persists to the server
this.save({ completed: !this.get("completed") });
}
});
// Create a specific task instance
const myTask = new Task({ title: "Learn Backbone" });
console.log(myTask.get("title")); // "Learn Backbone"
myTask.toggle();Line by line: Backbone.Model.extend() creates a Model class. defaults sets initial values for new instances. toggle() reads the current completed value with get(), flips it, and calls save() which sends a PUT request to the server.
Collections — Grouped Models
A Collection is an ordered set of Models with powerful query methods.
const Tasks = Backbone.Collection.extend({
// Tell the collection which Model class to use
model: Task,
// The REST endpoint for this collection
url: "/api/tasks",
// Custom method — filter completed tasks
getCompleted() {
// where() filters models by attribute values
return this.where({ completed: true });
}
});
const todoList = new Tasks();
// Fetch all tasks from /api/tasks
todoList.fetch();
// Find a specific task by ID
const task = todoList.get(42);Line by line: The Collection knows its Model type and its API URL. fetch() sends a GET request to /api/tasks, creates Model instances from the JSON response, and stores them. getCompleted() uses where() (similar to Array.filter()) to return only completed tasks.
Views — The Display Layer
A View is responsible for rendering a Model’s data and handling user interactions.
const TaskView = Backbone.View.extend({
// Create a <li> element for this view (instead of a <div>)
tagName: "li",
// Underscore template — <%= %> evaluates JavaScript expressions
template: _.template("<%= title %>"),
// Event map: "event selector": "handlerMethod"
events: {
"click .toggle": "toggleTask"
},
// Called when the view is created
initialize() {
// listenTo: when the model changes, re-render automatically
this.listenTo(this.model, "change", this.render);
},
// Render the template into the view's element
render() {
// toJSON() converts the model's attributes to a plain object
this.$el.html(this.template(this.model.toJSON()));
return this; // Return this for chaining
},
toggleTask() {
this.model.toggle();
}
});Line by line: tagName: "li" creates an <li> element as the view’s root. The Underscore template (<%= title %>) inserts the model’s title property. The events object maps DOM events to handler methods — clicking .toggle calls toggleTask. initialize() sets up a listener: when the model changes, re-render. listenTo is important because it automatically cleans up when the view is removed (preventing memory leaks).
Routers — URL Navigation
Routers enable bookmarkable URLs in single-page apps using hash fragments.
const AppRouter = Backbone.Router.extend({
// Route patterns → method names
routes: {
"": "home", // # → home
"tasks": "showTasks", // #tasks → showTasks
"tasks/:id": "showTask" // #tasks/42 → showTask with id=42
},
showTasks() {
// Show the task list view
new TaskListView({ collection: new Tasks() });
},
showTask(id) {
// Show a single task detail view
new TaskDetailView({ model: new Task({ id }) });
}
});
// Start the router — listen for URL changes
const router = new AppRouter();
Backbone.history.start();Line by line: Routes map URL patterns to handler methods. :id captures a dynamic segment. Backbone.history.start() begins monitoring the URL for changes — when the hash changes, the router calls the matching handler.
Common Mistakes
Modifying model attributes directly instead of using
set(): Writingmodel.title = "New Title"won’t trigger events or sync to the server. Always usemodel.set("title", "New Title")ormodel.save().Forgetting to return
thisfromrender(): Withoutreturn this, you can’t chain methods likeview.render().el. This is a Backbone convention that jQuery plugins also follow.Using
on()instead oflistenTo():this.model.on("change", this.render)works but creates a memory leak when the view is destroyed.listenTo()ties the listener to the view’s lifecycle — when the view is removed, the listener is cleaned up automatically.Not calling
remove()on views: When removing a view from the DOM, callview.remove()instead of just jQuery’s.remove(). Backbone’sremove()also cleans up event listeners.Over-nesting views: Deep view hierarchies (views inside views inside views) become hard to manage. Use sub-views sparingly — one view per data entity is usually enough.
Practice Questions
What is the difference between
model.get()and direct property access?model.get("title")triggers change events and is the correct way to read model data. Direct access (model.attributes.title) bypasses the event system and is not recommended.How does
listenTo()prevent memory leaks?listenTo()binds the listener to the view’s lifecycle. When the view is removed viaremove(), alllistenTobindings are cleaned up automatically.What does
collection.fetch()do? It sends a GET request to the collection’s URL endpoint, parses the JSON response, creates Model instances for each item, and populates the collection.Why does Backbone use Underscore.js for templates? Underscore provides a lightweight, no-frills template engine (
_.template()) that was ideal when Backbone was created. Today you can use any template engine or render JSX-style views.What is the purpose of
Backbone.history.start()? It begins monitoring URL hash changes and triggers the router when a matching route is navigated to. Without it, routes are defined but never activated.
Challenge
Build a task manager app: Create a Backbone app with a Task model, a Tasks collection that syncs to a REST API, a TaskView that renders each task with a toggle button, and a TaskListView that renders the collection. Add a router with routes for #all, #active, and #completed that filter the display.
FAQ
Try It Yourself
Create a simple Backbone app using CDN scripts:
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.13.6/underscore-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.4.1/backbone-min.js"></script>
</head>
<body>
<h1>My Tasks</h1>
<ul id="task-list"></ul>
<script>
// Define a Task model
const Task = Backbone.Model.extend({
defaults: { title: "", completed: false },
toggle() { this.save({ completed: !this.get("completed") }); }
});
// Define a TaskView
const TaskView = Backbone.View.extend({
tagName: "li",
template: _.template(
"<input type='checkbox' <%= completed ? 'checked' : '' %> /> " +
"<%= title %>"
),
events: { "change input": "toggleTask" },
initialize() {
this.listenTo(this.model, "change", this.render);
},
render() {
this.$el.html(this.template(this.model.toJSON()));
return this;
},
toggleTask() { this.model.toggle(); }
});
// Collection and App View
const Tasks = Backbone.Collection.extend({ model: Task });
const tasks = new Tasks([
{ title: "Learn Backbone", completed: false },
{ title: "Build an app", completed: true }
]);
const AppView = Backbone.View.extend({
el: "#task-list",
initialize() {
this.listenTo(this.collection, "add", this.addOne);
this.collection.each(this.addOne, this);
},
addOne(task) {
const view = new TaskView({ model: task });
this.$el.append(view.render().el);
}
});
new AppView({ collection: tasks });
</script>
</body>
</html>Expected output: A page titled “My Tasks” with a list showing two items. Each item has a checkbox and title. Checking or unchecking a box toggles the task’s completed status.
What’s Next
| Topic | Description |
|---|---|
| See how a full framework builds on similar concepts | |
| Master the DOM library Backbone depends on | |
| Understand the architecture behind Backbone |
Related terms: JavaScript, jQuery, REST API, HTML, JSON
What’s Next
Congratulations on completing this Backbonejs tutorial! Here’s where to go from here:
- Practice daily — Consistency is more important than long study sessions
- Build a project — Apply what you learned by building something real
- Explore related topics — Check out other tutorials in the same category
- Join the community — Discuss with other learners and share your progress
Remember: every expert was once a beginner. Keep coding!
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro