作为前端工程师,习惯了 JavaScript 的高效表达能力:箭头函数、async await
、模块化…开发者不用操心内存分配,垃圾回收,编译优化等脏活累活。不愧是高级语言,挥舞宝剑吧,兵来将挡,水来土掩。但如果你的「剑术」够好了,想要修炼一下内功,不妨学习一门底层语言 – Rust。
学习一门底层语言,犹如修炼内功,帮助我们以更底层的视角看待编程,写出健壮安全的代码。修炼 Rust 绝非一朝一夕,本文旨在从 JavaScript 开发者的角度,对比和厘清 Rust 中那些有趣的,难啃的,或独有的概念,帮助同胞们迈出学习 Rust 的第一步。
一切,都要从内存说起。
栈内存!堆内存!
之所以标题加了两个感叹号,是因为想要充满气势地告诉大家:得内存者得天下!学习一门底层语言,其内存管理机制是绕不开的课题,如何安全有效地分配、使用、释放内存,是每一门语言的必修课。Rust 正是以其优秀的内存安全闻名天下。学习 Rust,内存知识是基础之基础,核心之核心。
计算机程序运行的时候,所有的值,都是需要储存在内存中的。但由于值的类型不同,有的值是静态的,有的值是动态的,有的值较小,有的值很大… 因此内存也分成两种 – 栈内存和堆内存,用于存储不同类型的数据。
说起栈内存(Stack Memory)和堆内存(Heap Memory),JS 开发者们其实并不陌生。我们知道 JS 的数据类型分成基础类型和引用类型,基础类型值就是字符串,数字,布尔值等等,引用类型值就是对象啊,数组啊,这些我们很熟悉。
在 JS 中,基础类型值储存在栈内存中;引用类型值储存在堆内存中,并将其值的引用放到栈内存中。
上面的 JS 代码中,先后声明了的 a,b,c 这 3 个变量。a 和 b 分别是数字和字符串,属于基础类型值,直接储存在栈内存上;c 是一个对象,属于引用类型,储存在堆上,并把值的引用指针(堆上的内存地址)放到栈上,这样,程序在读写 c 的时候,可以通过其栈上的指针,从堆上定位到它的值了。
如果你能理解以上内容,那太好了,因为 Rust 也遵循以上的基本规则。
栈内存(Stack Memory)
栈是一个后进先出的队列结构。我们不妨把栈内存想象成一个个小卡槽整齐排列的样子,每个小槽是大小相等的内存空间:
在 Rust 中声明基础类型值的时候:
let a = 1;
let b