collection.last - Get Last Item
Quick Start (30 seconds)
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
collection.lastType: Getter property (read-only)
Returns:
- Last item in collection
undefinedif collection is empty
Why Does This Exist?
The Problem: Verbose Last Access
Without last, accessing the last item is verbose:
const messages = createCollection([...]);
// Verbose array access
const last = messages.items[messages.items.length - 1];
// Breaking collection abstractionProblems: ❌ Verbose - items.length - 1 every time
❌ Break abstraction - Must use .items
❌ Error-prone - Easy to forget -1
The Solution with last
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
// 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
const numbers = createCollection([10, 20, 30, 40]);
console.log(numbers.last); // 40Example 2: Check Before Using
const items = createCollection([]);
if (items.last) {
console.log('Last:', items.last);
} else {
console.log('Collection is empty');
}Example 3: Get Last Property
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); // undefinedReal-World Examples
Example 1: Latest Activity
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
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
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
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
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
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
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
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
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
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
const items = createCollection([]);
console.log(items.last); // undefined
// Always check
if (items.last) {
console.log(items.last.name);
}2. Read-Only Property
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; // Works3. Updates Automatically
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
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
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]; // 40Best: Use last for semantic clarity when you want the final item.
Common Patterns
Pattern 1: Get Latest with Fallback
const latest = collection.last || defaultValue;Pattern 2: Append and Return
function addAndGetLast(item) {
collection.add(item);
return collection.last;
}Pattern 3: Check Last Matches Condition
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! 🎉