Skip to content

Knockout.js Pure Computed Observables — Efficient Dependency Management

DodaTech Updated 2026-06-28 6 min read

In this tutorial, you will learn about Knockout.js Pure Computed Observables. We cover key concepts, practical examples, and best practices to help you master this topic.

Knockout.js pureComputed is an optimized computed observable that automatically tracks whether it has active observers, releasing or acquiring dependencies as needed for efficient memory management.

What You'll Learn

  • Creating pureComputed observables
  • How pureComputed differs from regular computed
  • When to use pureComputed vs computed
  • Pure computed lifecycle and disposal
  • Performance characteristics and best practices

Why It Matters

In large applications with many ViewModels, regular computed observables hold subscriptions to their dependencies even when nothing is reading their value. Pure computeds release these subscriptions when unobserved, reducing memory overhead and dependency tracking cost.

Real-World Use

A chat application with hundreds of message ViewModels, each having a pureComputed for formatted timestamp, mentioned users, and link detection. Most messages are off-screen at any time, so pure computeds release their dependencies until the message is visible again.

Pure vs Regular Computed

flowchart TD
    A[Computed Type] --> B{Has Observers?}
    B -->|Yes| C[Track Dependencies]
    B -->|No - Regular| D[Keep Subscriptions Active]
    B -->|No - Pure| E[Release All Subscriptions]
    C --> F[On Dependency Change: Re-evaluate]
    D --> F
    E --> G[On New Observer: Re-acquire Dependencies]
    G --> C
    style C fill:#e6f3ff,stroke:#4a90d9,stroke-width:2px
    style E fill:#ff6b6b,stroke:#c0392b,stroke-width:2px

Creating a Pure Computed

var firstName = ko.observable('John');
var lastName = ko.observable('Doe');

// Pure computed
var fullName = ko.pureComputed(function() {
  console.log('Re-evaluating fullName');
  return firstName() + ' ' + lastName();
});

// Nothing logged yet - pure computed is not evaluated until observed
console.log(fullName());
// Console: Re-evaluating fullName
// Output: John Doe

// No console log - value is cached
console.log(fullName());
// Output: John Doe

firstName('Jane');
// No console log - pure computed is lazy and has observers, so it marks
// itself dirty but does not re-evaluate until next read
console.log(fullName());
// Console: Re-evaluating fullName
// Output: Jane Doe

Expected output: The pure computed does not evaluate until its value is requested. It caches the result and only re-evaluates when a dependency changes and the value is read again.

Observing a Pure Computed

var firstName = ko.observable('John');
var lastName = ko.observable('Doe');

var fullName = ko.pureComputed(function() {
  console.log('Evaluating fullName');
  return firstName() + ' ' + lastName();
});

// Now we subscribe (become an observer)
var subscription = fullName.subscribe(function(name) {
  console.log('fullName changed to: ' + name);
});

// Subscription triggers evaluation
firstName('Bob');
// Console: Evaluating fullName
// Console: fullName changed to: Bob Doe

// Dispose the subscription - no more observers
subscription.dispose();

// Now pure computed releases its dependencies
// This means it no longer tracks firstName/lastName changes
firstName('Charlie');
// No console output (no evaluation, no notification)

Expected output: While the subscription exists, the pure computed tracks dependencies and notifies on change. After disposal, it releases all dependencies and stops tracking.

When to Use Pure Computed

Use pureComputed when:

  • The computed is used in a foreach binding (many instances, most off-screen)
  • The computed is expensive to evaluate
  • The computed is temporary (conditional UI sections)
  • Memory usage is a concern in large applications

Use regular computed when:

  • The evaluator has side effects (should not, but sometimes needed)
  • The computed must always stay up-to-date regardless of observers
  • You need to access the computed's dependencies list

Pure Computed in Components

// Product item component - many instances
function ProductItem(product) {
  var self = this;

  self.name = ko.observable(product.name);
  self.price = ko.observable(product.price);
  self.quantity = ko.observable(product.quantity);

  // Pure computed - releases when product is scrolled off-screen
  self.total = ko.pureComputed(function() {
    return self.price() * self.quantity();
  });

  // Pure computed for formatted display
  self.formattedTotal = ko.pureComputed(function() {
    return '$' + self.total().toFixed(2);
  });
}

// In a list of 1000 products, only visible items' computeds stay active

Pure Computed with Read/Write

var firstName = ko.observable('John');
var lastName = ko.observable('Doe');

var fullName = ko.pureComputed({
  read: function() {
    return firstName() + ' ' + lastName();
  },
  write: function(value) {
    var parts = value.split(' ');
    firstName(parts[0]);
    lastName(parts.slice(1).join(' '));
  }
});

// Write works the same as regular computed
fullName('Jane Smith');
console.log(firstName()); // Output: Jane
console.log(lastName());  // Output: Smith

Evaluation Delay and Lazy Evaluation

var a = ko.observable(1);
var b = ko.observable(2);

var sum = ko.pureComputed(function() {
  console.log('Computing sum');
  return a() + b();
});

// Change a dependency while no one is observing
a(10);

// The pure computed did not re-evaluate
// because no one was watching

// Now someone reads it
console.log(sum()); // Output: Computing sum \n 12

// The pure computed evaluated lazily on demand

Pure Computed vs Computed: Key Differences

Feature Regular Computed Pure Computed
Dependency tracking Always active Active only when observed
Memory usage Higher (always subscribed) Lower (releases when unobserved)
Evaluation Eager (evaluates on creation) Lazy (evaluates on first read)
Side effects Allowed (not recommended) Should not have side effects
isActive() Always true False when unobserved

Converting Between Types

var a = ko.observable(1);

// Regular computed - always active
var regular = ko.computed(function() { return a() * 2; });

// Convert to pure by wrapping
var pure = ko.pureComputed(function() { return a() * 2; });

// You cannot convert a regular computed to pure after creation
// Choose the right type at creation time

Common Mistakes

  1. Using pureComputed with side effects - Pure computeds may be evaluated lazily or not at all. Side effects in the evaluator may execute unpredictably.

  2. Expecting pure computed to evaluate eagerly - Pure computeds do not evaluate until someone reads them or subscribes. Code that relies on immediate evaluation will break.

  3. Not using pureComputed in foreach - A regular computed inside a foreach creates subscriptions for every item, even hidden ones. Pure computeds release subscriptions for off-screen items.

  4. Assuming pure computed is always more efficient - The overhead of tracking observers and releasing/acquiring subscriptions may outweigh benefits for always-visible computeds.

  5. Calling dispose on a pure computed unnecessarily - Pure computeds manage their own lifecycle. Explicit dispose() is only needed when you want to permanently remove the computed.

Practice Questions

  1. What triggers a pure computed to start tracking its dependencies?
  2. What happens to a pure computed's subscriptions when all its observers are removed?
  3. When would you choose a regular computed over a pure computed?
  4. Does a pure computed evaluate immediately upon creation?
  5. Why should pure computed evaluators avoid side effects?

Challenge: Create a product list with 100 items, each having pure computeds for formatted price, discounted price, and stock status. Use the browser's performance tools to compare memory usage between pure computeds and regular computeds. Experiment with scrolling to see how pure computeds release and acquire dependencies.

FAQ

Does pureComputed work with the mapping plugin?

Yes. The mapping plugin respects pure computed definitions. You can configure the mapping to create pure computeds for derived properties.

Can a pure computed depend on another pure computed?

Yes, pure computeds can depend on other pure computeds. The dependency graph is managed correctly, and both release subscriptions when all observers are gone.

Why is my pure computed not updating the UI?

If the pure computed has no observers (e.g., a conditional binding removes the element that uses it), it stops tracking. The UI updates when the element is re-added and a new read occurs.

Is there a performance penalty for using pureComputed?

There is a small overhead for tracking observer count. For most use cases, the memory savings outweigh this cost. For always-visible values, a regular computed is slightly faster.

Can I test if a pure computed is currently being observed?

Yes, use the isActive() method. Returns true if the computed has at least one subscriber.

Mini Project

Build a search results page with 500 items, each with pure computeds for matching score, highlighted title, and formatted metadata. Implement pagination and observe how pure computeds release subscriptions for items not on the current page.

What's Next

Control when observables notify subscribers with deferred updates and rate limiting for optimal performance in data-intensive applications.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro