针对JavaScript开发人员的Rust简介是怎样的

发布时间:2021-09-30 10:49:44 作者:柒染
来源:亿速云 阅读:143

这期内容当中小编将会给大家带来有关针对JavaScript开发人员的Rust简介是怎样的,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。

Rust是2010年起源于Mozilla Research的一种编程语言。如今,所有大公司都在使用它。

亚马逊和微软都认可它是其系统中C / C  ++的最佳替代品,但是Rust并不止于此。像Figma和Discord这样的公司现在也通过在客户端应用中使用Rust来引领潮流。

针对JavaScript开发人员的Rust简介是怎样的

我将从比较Rust和JavaScript开始,然后引导你完成Rust在浏览器中运行的步骤。最后,我将介绍一个使用Rust和JavaScript的COVID  simulator web应用程序的快速性能评估。

简而言之

Rust在概念上与JavaScript非常不同。但也有相似之处需要指出,让我们来看看问题的两面。

相似之处

这两种语言都有一个现代化的包管理系统。JavaScript有npm,Rust有Cargo。Rust有 Cargo.toml 来代替  package.json 进行依赖管理。要创建一个新的项目,使用 cargo init,要运行它,使用 cargo run。不太陌生吧?

Rust中有许多很酷的功能,你已经从JavaScript中知道了,只是语法略有不同。利用这个常见的JavaScript模式,对数组中的每个元素都应用一个闭包:

let staff = [    {name: "George", money: 0},    {name: "Lea", money: 500000}, ]; let salary = 1000; staff.forEach( (employee) => { employee.money += salary; } );

在Rust中,我们可以这样写:

let salary = 1000; staff.iter_mut().for_each(      |employee| { employee.money += salary; } );

诚然,习惯这种语法需要时间,用管子( | )代替括号。但在克服了最初的尴尬之后,我发现它比另一组括号读起来更清晰。

再举一个例子,这是JavaScript中的对象解构:

let point = { x: 5, y: 10 }; let {x,y} = point;

同样在Rust中:

let point = Point { x: 5, y: 10 }; let Point { x, y } = point;

主要的区别是,在Rust中我们必须指定类型(Point),更普遍的是,Rust需要在编译时知道所有类型。但与大多数其他编译语言不同的是,编译器尽可能自己推断类型。

为了进一步解释这个问题,下面是在C++和许多其他语言中有效的代码。每个变量都需要明确的类型声明。

int a = 5; float b = 0.5; float c = 1.5 * a;

在JavaScript以及Rust中,这段代码是有效的:

let a = 5; let b = 0.5; let c = 1.5 * a;

共享功能不胜枚举:

我可以继续列举下去,但我想我的观点现在已经很清楚了。Rust有一系列丰富的功能,这些功能在现代JavaScript中也有使用。

不同点

Rust是一种编译语言,这意味着没有运行时可以执行Rust代码。一个应用程序只能在编译器(rustc)完成它的魔法之后运行。这种方法的好处通常是更好的性能。

幸运的是,Cargo为我们解决了调用编译器的问题。而有了webpack,我们还可以将 Cargo 隐藏在 npm run build  后面。有了这个指南,只要为项目设置好Rust,就可以保留Web开发者的正常工作流程。

Rust  是一种强类型语言,这意味着在编译时所有类型必须匹配。例如,你不能调用一个参数类型错误或参数数量错误的函数。编译器会在你运行时遇到这个错误之前为你捕捉到它。显而易见的比较是TypeScript,如果你喜欢TypeScript,那么你很可能会喜欢Rust。

但别担心:如果你不喜欢TypeScript,Rust可能还是适合你。Rust  是近几年从头开始构建的,它考虑到了过去几十年来人类在编程语言设计方面所学到的一切。其结果是一种令人耳目一新的简洁语言。

Rust中的模式匹配是我最喜欢的一个特征,其他语言有 switch 和 case 来避免像这样的长链:

if ( x == 1) {    // ...  } else if ( x == 2 ) {   // ... } else if ( x == 3 || x == 4 ) {   // ... } // ...

Rust使用了如下更优雅的匹配项:

match x {   1 => { /* Do something if x == 1 */},   2 => { /* Do something if x == 2 */},   3 | 4 => { /* Do something if x == 3 || x == 4 */},   5...10 => { /* Do something if x >= 5 && x <= 10 */},   _ => { /* Catch all other cases */ } }

我认为这是非常整洁的,我希望JavaScript开发人员也能欣赏这种语法扩展。

不幸的是,我们还得谈谈Rust的黑暗面。直言不讳地说,使用严格的类型系统有时会让人感觉非常繁琐。如果你认为C++或Java的类型系统很严格,那么请准备好迎接Rust的艰难之旅吧。

就我个人而言,我很喜欢Rust这部分。我依赖于严格的类型系统,因此可以关闭大脑的一部分&mdash;&mdash;每当我发现自己在编写JavaScript时,大脑的一部分就会剧烈地兴奋起来。但是我知道对于初学者来说,总是和编译器作对是很烦人的。我们将在稍后的Rust教程中看到一些。

Hello Rust

现在,让我们用Rust在浏览器中运行一个 hello world ,我们首先要确保所有必要的工具都已安装。

工具

使用rustup安装Cargo + rustc。  Rustup是推荐的安装Rust的方法,它将安装最新的稳定版Rust的编译器(rustc)和包管理器(Cargo)。它将安装Rust最新稳定版本的编译器(rustc)和包管理器(Cargo)。它还可以管理beta版和每夜构建版,但对于本例来说,这不是必需的。

安装wasm-pack。 这是为了将编译器与npm集成。

我们还需要Node和npm。我们有一篇完整的文章[1]解释了安装这两个的最佳方法。

编写Rust代码

现在一切都安装好了,让我们来创建项目。最终的代码也可以在这个GitHub仓库[2]中找到。我们从一个可以编译成npm包的Rust项目开始,之后会有导入该包的JavaScript代码。

要创建一个名为 hello-world 的Rust项目,请使用 cargo init --lib  hello-world。这将创建一个新目录并生成Rust库所需的所有文件:

├──hello-world     ├── Cargo.toml     ├── src         ├── lib.rs

Rust代码将放在 lib.rs 中,在此之前我们必须调整 Cargo.toml。它使用 TOML[3]  定义了依赖关系和其他包的信息。如果想在浏览器中看到hello world,请在 Cargo.toml 中的某个地方添加以下行数(例如,在文件的最后)。

[lib] crate-type = ["cdylib"]

这告诉编译器在C兼容模式下创建一个库。显然我们在我们的例子中没有使用C。C-compatible只是意味着不是Rust专用的,这是我们使用JavaScript中的库所需要的。

我们还需要两个外部库,将它们作为单独的一行添加到依赖关系部分。

[dependencies] wasm-bindgen = "0.2.68" web-sys = {version = "0.3.45", features = ["console"]}

这些都是来自 crates.io[4] 的依赖项,它是 Cargo 使用的默认包仓库。

wasm-bindgen[5]是必要的,以创建一个我们以后可以从JavaScript中调用的入口点。(你可以在这里找到完整的文档。)值 ”0.2.68"  指定了版本。

web-sys[6]包含了所有Web  API的Rust绑定,它将使我们能够访问浏览器控制台。请注意,我们必须明确地选择控制台功能,我们最终的二进制文件将只包含这样选择的Web API绑定。

接下来是 lib.rs 内部的实际代码。自动生成的单元测试可以删除。只需使用以下代码替换文件的内容:

use wasm_bindgen::prelude::*; use web_sys::console;  #[wasm_bindgen] pub fn hello_world() {     console::log_1("Hello world"); }

顶部的 use 语句是用于从其他模块导入项目。这与JavaScript中的 import 类似)。

pub fn hello_world(){...} 声明一个函数。pub 修饰符是“public”的缩写,作用类似于JavaScript中的  export。注释 #[wasm_bindgen] 特定于Rust编译为[WebAssembly  (Wasm)](https://webassembly.org/ "wasm_bindgen] 特定于Rust编译为[WebAssembly (Wasm  "wasm_bindgen] 特定于Rust编译为[WebAssembly  (Wasm)")")。我们在这里需要它来确保编译器将包装函数公开给JavaScript。

在功能主体中,“Hello world”被打印到控制台上。Rust中的 console :: log_1() 是对 console.log()  的调用的包装。

你是否注意到函数调用中的 _1 后缀?这是因为JavaScript允许使用可变数量的参数,而Rust不允许。为了解决这个问题, wasm_bindgen  为每种参数数量生成一个函数。是的,这很快就会变得丑陋!但这有效。在web-sys文档[7]中提供了一个可以在Rust控制台中调用的完整函数列表。

现在我们应该已经一切就绪,试着用下面的命令编译它。这将下载所有的依赖项并编译项目,第一次可能会花一些时间。

cd hello-world wasm-pack build

哈!Rust编译器对我们不满意。

error[E0308]: mismatched types  --> src\lib.rs:6:20   | 6 |     console::log_1("Hello world");   |                    ^^^^^^^^^^^^^ expected struct `JsValue`, found `str`   |   = note: expected reference `&JsValue`              found reference `&'static str

注意:如果您看到其他错误(error: linking with cc failed: exit code:  1)并且你使用的是Linux,则说明缺少交叉编译依赖性。sudo apt install gcc-multilib 应该可以解决此问题。

正如我前面提到的,编译器很严格。当它期望一个 JsValue  的引用作为一个函数的参数时,它不会接受一个静态字符串。为了满足编译器的要求,必须进行显式转换。

console::log_1(&"Hello world".into());

方法 [into()](https://doc.rust-lang.org/std/convert/trait.Into.html "into(  "into()")") 将一个值转换为另一个值。Rust 编译器很聪明,它可以推迟哪些类型参与转换,因为函数签名只留下了一种可能性。在这种情况下,它将转换为  JsValue,这是一个由JavaScript管理的值的包装类型。然后,我们还得加上 &,通过引用而不是通过值来传递,否则编译器又会抱怨。

尝试再次运行 wasm-pack build,如果一切顺利,则最后一行应如下所示:

[INFO]: :-) Your wasm pkg is ready to publish at /home/username/intro-to-rust/hello-world/pkg.

如果你能走到这一步,你现在就可以手动编译Rust了。下一步,我们将把它与npm和webpack集成,后者将自动为我们完成这项工作。

JavaScript整合

在这个例子中,我决定将 package.json 放在 hello-world  目录内。我们也可以为Rust项目和JavaScript项目使用不同的目录,这是个口味问题。

以下是我的 package.json 文件。遵循的最简单方法是将其复制并运行 npm install,或者运行 npm init 并仅复制 dev  依赖项:

{     "name": "hello-world",     "version": "1.0.0",     "description": "Hello world app for Rust in the browser.",     "main": "index.js",     "scripts": {         "build": "webpack",         "serve": "webpack serve"     },     "author": "Jakob Meier <inbox@jakobmeier.ch>",     "license": "(MIT OR Apache-2.0)",     "devDependencies": {         "@wasm-tool/wasm-pack-plugin": "~1.3.1",         "@webpack-cli/serve": "^1.1.0",         "css-loader": "^5.0.1",         "style-loader": "^2.0.0",         "webpack": "~5.8.0",         "webpack-cli": "~4.2.0",         "webpack-dev-server": "~3.11.0"     } }

如你所见,我们使用的是webpack  5。Wasm-pack也可以和旧版本的webpack一起使用,甚至可以不使用捆绑程序。但每个设置的工作方式都有些不同,我建议你在跟随这个Rust教程时使用完全相同的版本。

另一个重要的依赖项是 wasm-pack-plugin。这是一个Webpack插件,专门用于加载使用wasm-pack构建的Rust软件包。

继续,我们还需要创建 webpack.config.js 文件来配置webpack。它应该是这样的:

const path = require('path'); const webpack = require('webpack'); const WasmPackPlugin = require("@wasm-tool/wasm-pack-plugin");  module.exports = {     entry: './src/index.js',     output: {         path: path.resolve(__dirname, 'dist'),         filename: 'index.js',     },     plugins: [         new WasmPackPlugin({             crateDirectory: path.resolve(__dirname, ".")         }),     ],     devServer: {         contentBase: "./src",         hot: true,     },     module: {         rules: [{             test: /\.css$/i,             use: ["style-loader", "css-loader"],         }, ]     },     experiments: {         syncWebAssembly: true,     }, };

所有的路径都配置为Rust代码和JavaScript代码并排。index.js 将在 src 文件夹中,紧挨着  lib.rs。如果你喜欢不同的设置,可以随时调整这些。

你还会注意到,我们使用webpack experiments[8],这是webpack 5引入的新选项。请确保将 syncWebAssembly  设置为true。

最后,我们必须创建JavaScript入口点 src/index.js:

import("../pkg").catch(e => console.error("Failed loading Wasm module:", e)).then(     rust =>         rust.hello_world() );

我们必须异步加载Rust模块。调用 rust.hello_world() 会调用一个生成的封装函数,而这个函数又会调用 lib.rs 中定义的Rust函数  hello_world。

现在,运行 npm run serve 应该可以编译所有内容并启动开发服务器。我们没有定义HTML文件,因此页面上没有任何显示。你可能还必须手动转到  http://localhost:8080/index,因为http://localhost:8080只是列出文件而不执行任何代码。

打开空白页后,打开开发人员控制台。Hello World应该有一个日志条目。

好吧,对于一个简单的hello world来说,这是相当多的工作。但现在一切都到位了,我们可以轻松地扩展Rust代码,而不用担心这些。保存对 lib.rs  的修改后,你应该会自动看到重新编译和浏览器中的实时更新,就像JavaScript一样。

何时使用Rust

Rust不是JavaScript的一般替代品。它只能通过Wasm在浏览器中运行,这在很大程度上限制了它的作用。即使你可以用Rust替换几乎所有的JavaScript代码,如果你真的想的话,那是一个坏主意,而且不是Wasm的目的。例如,Rust并不适合与你网站的UI进行交互。

我认为Rust +  Wasm是一个额外的选项,可以用来更有效地运行CPU重的工作负载。以较大的下载量为代价,Wasm避免了JavaScript代码面临的解析和编译开销。这一点,再加上编译器的强力优化,可能会带来更好的性能。这通常是公司为特定项目选择Rust的原因。选择Rust的另一个原因可能是语言偏好,但这是一个完全不同的讨论,我不会在这里讨论。

上述就是小编为大家分享的针对JavaScript开发人员的Rust简介是怎样的了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注亿速云行业资讯频道。

推荐阅读:
  1. JavaScript的简介
  2. JavaScript Date的对象简介是怎样的

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

rust javascript

上一篇:如何为调用cmd设置密码

下一篇:JavaScript中如何深入理解this

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》