DEV Community

Timevolt
Timevolt

Posted on

The Rust Awakens: Ownership Explained for JavaScript Devs

The Quest Begins (The "Why")

Hey friend, picture this: you’re happily writing JavaScript, tossing objects around like confetti at a parade, and then you decide to give Rust a spin. You open the compiler, write a simple function that returns a slice of a vector, and boom—error[E0505]: cannot move out of … because it is borrowed. Your brain does a double‑take. “Wait, I didn’t even touch anything!” you mutter, staring at the screen like you just missed a plot twist in Inception.

That moment was my dragon. I’d spent years trusting the garbage collector to clean up after me, and Rust’s ownership system felt like a strict sensei who wouldn’t let you leave the dojo until you bowed correctly. I was frustrated, curious, and honestly a little scared. But once I grasped the core ideas, the whole language started to click like a well‑oiled machine.

So why does ownership matter? Because it gives you memory safety without a runtime garbage collector. No surprise pauses, no hidden allocations—just compile‑time guarantees that your program won’t dereference null or use‑after‑free. For a JS dev used to “it just works”, that’s a superpower worth earning.

The Revelation (The Insight)

The big surprise? Ownership isn’t just about who “owns” a value; it’s about how that value can be accessed, moved, or borrowed at any point in the program. Three rules govern everything:

  1. Each value has a single owner.
  2. When the owner goes out of scope, the value is dropped.
  3. You can either have one mutable reference or any number of immutable references to a value, but never both at the same time.

Sounds simple, right? The gotcha is that Rust treats references as a separate kind of value with its own lifetime. If you try to store a reference beyond the lifetime of what it points to, the compiler says “nope”. This is where many JS devs stumble because in JavaScript a reference (or variable) just points to an object that lives as long as something else holds it—garbage collection decides when it’s gone.

Let’s illustrate with a mistake I made early on. I wanted to return a slice of a vector from a function:


rust
fn first_word(s: &String) -> &str {
    let bytes = s.as_bytes();
Enter fullscreen mode Exit fullscreen mode

Top comments (0)