Skip to content

Sponsor

Sponsor

collection.last - Get Last Item

Quick Start (30 seconds)

javascript
const messages = createCollection([
  { id: 1, text: 'Hello', time: '10:00' },
  { id: 2, text: 'How are you?', time: '10:05' },
  { id: 3, text: 'Good!', time: '10:10' }
]);

// Get last item
const last = messages.last;
console.log(last);
// { id: 3, text: 'Good!', time: '10:10' }

console.log(last.text);  // "Good!"

// Check if exists
if (messages.last) {
  console.log('Latest message:', messages.last.text);
}

// Empty collection
const empty = createCollection([]);
console.log(empty.last);  // undefined

// Reactive updates
effect(() => {
  const latest = messages.last;
  if (latest) {
    document.getElementById('latest-msg').textContent = latest.text;
  }
});
// Updates when new message added ✨

What just happened? You accessed the last item with a clean getter property!

What is collection.last?

last is a getter property that returns the last item in the collection, or undefined if empty.

Simply put: it gives you the item at the final position.

Think of it as looking at the bottom card in a deck - you see what's last without removing it.

Syntax

javascript
collection.last

Type: Getter property (read-only)

Returns:

  • Last item in collection
  • undefined if collection is empty

Why Does This Exist?

The Problem: Verbose Last Access

Without last, accessing the last item is verbose:

javascript
const messages = createCollection([...]);

// Verbose array access
const last = messages.items[messages.items.length - 1];

// Breaking collection abstraction

Problems:Verbose - items.length - 1 every time
Break abstraction - Must use .items
Error-prone - Easy to forget -1

The Solution with last

javascript
const messages = createCollection([...]);

// Semantic property
const last = messages.last;

// Clean and simple ✅

Benefits:Concise - One word
Semantic - Name expresses intent
Clean API - No .items needed
Safe - Returns undefined if empty

Mental Model

Think of last as the end of a line:

Collection Items         Last
┌──────────────┐        ┌──────────────┐
│ [Item 1]     │        │              │
│ [Item 2]     │        │              │
│ [Item 3]     │        │              │
│ [Item 4] ←───┼───────→│ Item 4       │
└──────────────┘        │ (last)       │
                        └──────────────┘

Key Insight: Always the item at last index, or undefined.

How It Works

javascript
// From 03_dh-reactive-collections.js
get last() {
  return this.items[this.items.length - 1];
}

Simple getter:

  • Returns items[length - 1]
  • Undefined if empty
  • Read-only property

Basic Usage

Example 1: Access Last Item

javascript
const numbers = createCollection([10, 20, 30, 40]);

console.log(numbers.last);  // 40

Example 2: Check Before Using

javascript
const items = createCollection([]);

if (items.last) {
  console.log('Last:', items.last);
} else {
  console.log('Collection is empty');
}

Example 3: Get Last Property

javascript
const logs = createCollection([
  { action: 'login', time: '10:00' },
  { action: 'click', time: '10:05' },
  { action: 'logout', time: '10:10' }
]);

console.log(logs.last?.action);  // "logout"

// Safe even if empty
const empty = createCollection([]);
console.log(empty.last?.action);  // undefined

Real-World Examples

Example 1: Latest Activity

javascript
const activities = createCollection([]);

function logActivity(action) {
  activities.add({
    action,
    timestamp: new Date(),
    user: currentUser.name
  });
}

effect(() => {
  const latest = activities.last;
  if (latest) {
    document.getElementById('last-activity').textContent = 
      `Last: ${latest.action} at ${latest.timestamp.toLocaleTimeString()}`;
  }
});

Example 2: Most Recent Message

javascript
const chatMessages = createCollection([]);

function addMessage(text) {
  chatMessages.add({
    text,
    sender: currentUser.name,
    time: Date.now()
  });
  
  // Scroll to show latest
  scrollToBottom();
}

effect(() => {
  const latest = chatMessages.last;
  if (latest) {
    playNotificationSound();
  }
});

Example 3: Last Transaction

javascript
const transactions = createCollection([
  { type: 'deposit', amount: 100 },
  { type: 'withdrawal', amount: 50 },
  { type: 'deposit', amount: 200 }
]);

function getLastTransaction() {
  return transactions.last;
}

const last = getLastTransaction();
if (last) {
  console.log(`Last: ${last.type} $${last.amount}`);
}

Example 4: Undo Last Action

javascript
const actionHistory = createCollection([]);

function performAction(action) {
  action.execute();
  actionHistory.add(action);
}

function undo() {
  const lastAction = actionHistory.last;
  
  if (lastAction) {
    lastAction.undo();
    actionHistory.items.pop();
    console.log('Action undone');
  } else {
    console.log('Nothing to undo');
  }
}

Example 5: Show Recent Addition

javascript
const cart = createCollection([]);

function addToCart(product) {
  cart.add({
    product,
    addedAt: Date.now()
  });
  
  const latest = cart.last;
  showToast(`Added: ${latest.product.name}`);
}

Example 6: Latest Score

javascript
const scoreHistory = createCollection([]);

function recordScore(score) {
  scoreHistory.add({
    score,
    timestamp: Date.now()
  });
}

effect(() => {
  const latest = scoreHistory.last;
  if (latest) {
    document.getElementById('current-score').textContent = latest.score;
    
    // Check if new high score
    const allScores = scoreHistory.items.map(s => s.score);
    const highScore = Math.max(...allScores);
    
    if (latest.score === highScore) {
      showCelebration('New high score!');
    }
  }
});

Example 7: Most Recent Upload

javascript
const uploads = createCollection([]);

function uploadFile(file) {
  uploads.add({
    filename: file.name,
    size: file.size,
    uploadedAt: Date.now(),
    status: 'uploading'
  });
  
  const upload = uploads.last;
  
  // Start upload
  performUpload(file).then(() => {
    upload.status = 'complete';
  });
}

effect(() => {
  const latest = uploads.last;
  if (latest && latest.status === 'complete') {
    showNotification(`Upload complete: ${latest.filename}`);
  }
});

Example 8: Queue End Position

javascript
const waitingList = createCollection([]);

function joinWaitlist(person) {
  waitingList.add(person);
  
  const position = waitingList.length;
  const lastPerson = waitingList.last;
  
  console.log(`${lastPerson.name} joined at position ${position}`);
}

Example 9: Recent Error

javascript
const errorLog = createCollection([]);

function logError(error) {
  errorLog.add({
    message: error.message,
    timestamp: Date.now(),
    stack: error.stack
  });
  
  // Keep only last 100 errors
  if (errorLog.length > 100) {
    errorLog.items.shift();
  }
}

function getLastError() {
  return errorLog.last;
}

// Show in UI
effect(() => {
  const lastError = errorLog.last;
  if (lastError) {
    document.getElementById('last-error').textContent = 
      `Error: ${lastError.message}`;
  }
});

Example 10: Completion Status

javascript
const steps = createCollection([
  { name: 'Start', completed: true },
  { name: 'Middle', completed: true },
  { name: 'End', completed: false }
]);

function isComplete() {
  const lastStep = steps.last;
  return lastStep?.completed || false;
}

if (isComplete()) {
  showCompletionScreen();
}

Important Notes

1. Returns undefined if Empty

javascript
const items = createCollection([]);
console.log(items.last);  // undefined

// Always check
if (items.last) {
  console.log(items.last.name);
}

2. Read-Only Property

javascript
const items = createCollection([1, 2, 3]);

// ❌ Cannot set last directly
items.last = 99;  // Won't work

// ✓ Modify collection
items.items[items.items.length - 1] = 99;  // Works

3. Updates Automatically

javascript
const items = createCollection([1, 2, 3]);

console.log(items.last);  // 3

items.add(4);
console.log(items.last);  // 4 (now last)

items.items.pop();
console.log(items.last);  // 3 (back to 3)

4. Works with Negative Index Alternative

javascript
const items = createCollection([10, 20, 30, 40]);

// These are equivalent
items.last;    // 40
items.at(-1);  // 40

// But last is more semantic for "get last item"

When to Use

Use last For: ✅ Get last item
✅ Most recent addition
✅ Latest status/message
✅ End of sequence
✅ Undo functionality

Don't Use For: ❌ Second to last - Use at(-2)
❌ Removing last - Use pop() or items.pop()

Comparison with Alternatives

javascript
const items = createCollection([10, 20, 30, 40]);

// collection.last
items.last;  // 40

// collection.at(-1)
items.at(-1);  // 40

// collection.items[items.items.length - 1]
items.items[items.items.length - 1];  // 40

Best: Use last for semantic clarity when you want the final item.

Common Patterns

Pattern 1: Get Latest with Fallback

javascript
const latest = collection.last || defaultValue;

Pattern 2: Append and Return

javascript
function addAndGetLast(item) {
  collection.add(item);
  return collection.last;
}

Pattern 3: Check Last Matches Condition

javascript
function isLastComplete() {
  return collection.last?.completed === true;
}

Summary

What is collection.last?
A getter property that returns the last item or undefined.

Why use it?

  • ✅ Semantic clarity
  • ✅ Concise syntax
  • ✅ Safe (undefined if empty)
  • ✅ Clean API

Remember: last is the cleanest way to access the final item! 🎉