
Introduction to Rust for JavaScript Developers

Introduction to Rust for JavaScript Developers
So this one is a no brainer. Everyone who asks me about Rust from a JavaScript background wants to know how Rust is different and how it is the same. Well, the answer to the second part first: Rust and JavaScript are very different and are used for very different things. Rust is a systems programming language, and as such is going to be much closer to C, C++ and Assembly than it is to a scripting language like JavaScript. But even though Rust is very different, there are a few features of the language that will feel familiar. I will cover a few of the basics of Rust here and will point out how the corresponding JavaScript concepts you are used to will be apparent. Check out the Rust Getting Started Guide here.
Why Learn Rust?
I already know a bit about the JavaScript language because a lot of websites are implemented in this language on the client and the server side. JavaScript is typically used for quick development of websites and web applications on the client and server side. Although it's also possible to do cross platform applications with it, I wouldn't really call it a language for applications where performance is at issue, low level systems programming, or resource constrained environments. Rust will help fill those gaps.
- Memory Safety: Rust prevents entire classes of bugs at compile-time
- Performance: Comparable to C and C++, with zero-cost abstractions
- Concurrency: Built-in support for safe concurrent programming
- Ecosystem Integration: Can be used alongside JavaScript in projects (via WebAssembly)
Key Differences from JavaScript
1. Compilation vs Interpretation
javascript is a dynamic, typed interpreted language and Rust is a dynamic, but statically typed compiled language. There are other differences as well, and a few simple examples should highlight these.
JavaScript Example:
// JavaScript - Runtime type checking
const add = (a, b) => a + b;
console.log(add(5, 3)); // 8
console.log(add("5", "3")); // "53" - works but unexpected
Rust Example:
// Rust - Compile-time type checking
fn add(a: i32, b: i32) -> i32 {
a + b
}
fn main() {
println!("{}", add(5, 3)); // 8
// add("5", "3"); // Won't compile - type error
}
2. Memory Management
One of the biggest changes you'll see in Rust, especially when coming from a garbage collected language like JavaScript, is that Rust uses an ownership model as opposed to garbage collection. We've already talked a bit about ownership, but it is extremely important to understand how ownership works in Rust, because it is how Rust actually manages memory. Learning and truly understanding ownership is going to be important for creating safe and effective code.
JavaScript Example:
// JavaScript - Garbage collected
let name = "Alice";
let person = { name: name };
name = "Bob"; // Original variable changed, but person still has reference
console.log(person.name); // "Alice"
Rust Example:
// Rust - Ownership model
let s1 = String::from("hello");
let s2 = s1; // s1's ownership moved to s2
// println!("{}", s1); // ERROR: s1 no longer owns the data
println!("{}", s2); // OK: s2 owns the string
Essential Rust Concepts
Variables and Mutability
Rust variables are immutable by default, unlike JavaScript:
// Immutable by default
let x = 5;
// x = 6; // ERROR: cannot assign twice to immutable variable
// Make it mutable explicitly
let mut y = 5;
y = 6; // OK
println!("{}", y); // 6
// Constants are always immutable
const MAX_SIZE: u32 = 100;
Functions
Functions in Rust have a return type that is declared in the function definition. The return type and the return value of a function can be specified without the use of the return statement.
// Function with explicit types
fn greet(name: &str) -> String {
format!("Hello, {}!", name)
}
fn multiply(a: i32, b: i32) -> i32 {
a * b // No semicolon = implicit return
}
fn main() {
println!("{}", greet("Alice"));
println!("{}", multiply(4, 5));
}
Ownership and Borrowing
This is the phrase that every Rust programmer learns to love, to hate, to complain about and to question. Rust's unique selling point, or perhaps more so its most distinctive feature. In most languages, the runtime is responsible for managing the memory for the memory allocated by the program (via garbage collection). Rust does this by controlling access and validity of the memory using a set of rules known as ownership.
fn main() {
let s1 = String::from("hello");
// Move (transfer ownership)
let s2 = s1;
// println!("{}", s1); // ERROR: s1 no longer owns the value
// Borrowing (lending with references)
let s3 = String::from("world");
let len = calculate_length(&s3); // Borrow with &
println!("'{}' has length {}", s3, len); // s3 still valid
}
fn calculate_length(s: &String) -> usize {
s.len()
} // s goes out of scope, but doesn't own the String, so nothing changes.
Pattern Matching
Rust's match is more powerful than JavaScript's switch:
enum Color {
Red,
Green,
Blue,
}
fn describe_color(color: Color) -> &'static str {
match color {
Color::Red => "A warm color",
Color::Green => "A natural color",
Color::Blue => "A cool color",
}
}
Common Patterns for JavaScript Developers
Error Handling
Instead of try-catch, Rust uses Result types:
use std::fs::File;
use std::io::Read;
fn read_file_contents(path: &str) -> Result<String, std::io::Error> {
let mut file = File::open(path)?; // ? operator for error propagation
let mut contents = String::new();
file.read_to_string(&mut contents)?;
Ok(contents)
}
fn main() {
match read_file_contents("example.txt") {
Ok(contents) => println!("File: {}", contents),
Err(e) => println!("Error: {}", e),
}
}
Iterators
Rust iterators are similar to JavaScript's array methods but more efficient:
fn main() {
let numbers = vec![1, 2, 3, 4, 5];
// Iterator with functional style
let doubled: Vec<i32> = numbers
.iter()
.map(|x| x * 2)
.filter(|x| x > &4)
.collect();
println!("{:?}", doubled); // [6, 8, 10]
}
Structs and Methods
Rust's structs are similar to JavaScript objects:
struct User {
name: String,
email: String,
age: u32,
}
impl User {
fn new(name: String, email: String, age: u32) -> User {
User { name, email, age }
}
fn display_info(&self) {
println!("Name: {}, Email: {}, Age: {}", self.name, self.email, self.age);
}
}
fn main() {
let user = User::new(
String::from("Alice"),
String::from("alice@example.com"),
30,
);
user.display_info();
}
Rust and WebAssembly
You are probably thinking about this in a wrong order. I just built an adder plugin for JavaScript using Rust, and I want to see what this development workflow looks like. The end goal is to have a high performance plugin from Rust to JavaScript, but we need to figure out how the JavaScript gets called into the Rust plugin first. Surprisingly, the whole JavaScript to Rust plugin to Rust to WebAssembly flow that we'll be using is called WebAssembly, or "WASM" for short. So here is where I am in "Rust-land" – building a blazing fast adder plugin for JavaScript.
Rust Implementation:
// lib.rs
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn fibonacci(n: u32) -> u32 {
if n <= 1 {
n
} else {
fibonacci(n - 1) + fibonacci(n - 2)
}
}
JavaScript Usage:
// JavaScript
import init, { fibonacci } from './pkg/fibonacci.js';
await init();
console.log(fibonacci(10)); // 55
Getting Started
Installation
Install Rust using rustup:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
rustup update
Creating Your First Project
cargo new hello_rust
cd hello_rust
cargo run
Essential Commands
cargo build- Compile your projectcargo run- Compile and runcargo test- Run testscargo check- Fast syntax check without compilingcargo fmt- Format your codecargo clippy- Linting and suggestions
Learning Resources
- The Rust Book - Official comprehensive guide
- Rust by Example - Practical code examples
- Rustlings - Interactive exercises
- Exercism - Guided learning tracks
- RustConf talks - Community talks on YouTube
Conclusion
Rust is just another way to write systems programming code. Although this time in a way that is also much safer. While it is certainly possible to have fast systems code and low memory usage, it is equally common to write code that can crash at a later date, long after you have left the system on unattended for days. Although not a safety critical area of code, this type of crash can easily lead to 'damage to pocketbook or equivalent' through lost work, time wasted and similar, making it a common concern for end users. However with Rust, this type of common 'shoot yourself in the foot' type of issue, is directly addressed by forcing you to write safer code. A systems programmer will certainly find that Rust programming is somewhat different than writing code in a language such as JavaScript, but with enough practice you can adjust to new Rust style. Although there are a few changes, particularly when you try to change your mindset to properly understand how memory ownership works in Rust, you'll be amazed at just how easy the model is to use and therefore how little you'll have to worry about it. Simply, your code will be safe and also very fast.
So you think you can take on the world with JavaScript? Well you're probably right, as it turns out. As it goes with learning to program you've probably already got all the fundamentals locked down, like variables, functions and data structures. Yep you know what I mean, Variables, Functions, Data Structures. Rust is basically just implementing all the common class concepts (I know, I know, go back to CS class) and making them part of the language, and then enforcing the safe usage of those classes at compile time, instead of at run time. So all the knowledge you've already got locked away is suddenly front and centre in Rust. We'll start small with small projects but as you start to feel less fear of the word concurrency, and less fear of the word memory, you'll be well on your way to learning Rust.
Well this Rust language is a pretty interesting project, and if you are looking for a little performance bump in the code that you write, or if you are looking to start doing systems programming this may be a project you are interested in following.
James Okafor
Writer at DevPulse covering Programming.
