Rust 笔记:WebAssembly 的 JavaScript API

简介: Rust 笔记:WebAssembly 的 JavaScript API

WebAssemblyWebAssembly 的 JavaScript API


1. 概述

1.1 引言

在之前的文章中我们讲解过将某些语言(如 RustC++ 等)编译成 WebAssembly ,也简单讲解过 如何加载和运行 WebAssembly 代码

当加载了一个 .wasm 模块 之后,你就想要去使用它。WebAssemblyJavaScript API, 就为我们提供了这样的交互能力。 本文在前面已经对 WebAssembly 有一定的使用基础上,争取对 WebAssemblyJavaScript API 有全面把握,以为应用自如打好基础。

1.2 为什么需要用于 WebAssembly 的 JavaScript API

WebAssembly 是一种可移植、高性能的二进制格式,可以在现代 Web 浏览器中运行。虽然 WebAssembly 可以直接由编译器生成并在浏览器中运行,但为了能够与 JavaScript 交互和利用 Web 平台的功能WebAssembly 需要使用 JavaScript API,比如用于操作 DOM,等等。

归纳起来,WebAssembly 目前仍然需要使用 JavaScript API 的主要原因有以下几点:

  1. 当前,WebAssembly 还没有直接访问浏览器 API 的能力。WebAssembly 本身只是一种二进制格式,没有直接访问浏览器 DOM网络请求图形渲染 等能力。通过 JavaScript APIWebAssembly 可以与 JavaScript 代码进行交互,并利用 JavaScript 来访问浏览器提供的功能。
  2. JavaScript API 提供了底层数据传输和交互的机制。WebAssemblyJavaScript 之间需要进行数据的传递和交互。JavaScript API 提供了一系列的函数和对象,用于在 WebAssembly 模块和 JavaScript 之间传递数据、调用函数、导入导出功能等。

1.3 ★ 浏览器 和 NodeJS 环境加载 wasm 模块 差异

本文后续介绍各个 API 中涉及大量的代码示例,这些示例都是假定在浏览器中使用的。实际上在实际开发中,也经常应用于 NodeJS 环境,这里会有一些不同。在这一小节我们提前把这里的问题讲清楚,后面则不再对该问题进行赘述。

1.3.1 浏览器环境下

浏览器环境下我们使用 Fetch API 起 HTTP 请求来获取 WebAssembly 模块,因为:

  1. WebAssembly 模块 通常是作为 独立的二进制文件存在,而不是内联在 HTML 文件中。因此,需要通过网络从服务器获取模块文件
  2. WebAssembly 模块可能具有较大的文件大小,使用 HTTP 请求可以利用浏览器的缓存机制,减少模块的重复下载。
  3. Fetch API 提供了一种方便的方式来异步获取资源。它支持 Promise 和 async/await 语法,使得处理异步操作更加简洁和可读。使用 Fetch API 发起请求可以通过设置请求头、处理错误和响应等进行更灵活的控制。

总之,使用 Fetch API 发起 HTTP 请求来获取 WebAssembly 模块是为了从服务器异步获取模块文件,并能够灵活地处理请求和响应过程。这样可以实现模块的动态加载和更好的控制。

1.3.2 NodeJS 环境下

在 Node.js 环境中,由于没有浏览器的环境和 Fetch API,不能直接使用 fetch 函数来获取 WebAssembly 模块(除非你硬要搭建一个静态文件服务器,再来使用代码请求到模块代码来运行)。

通常情况下在 Node.js 环境中我们使用 fs 模块 来读取 模块文件 并 获取其 二进制数据。

具体的,在 NodeJS 中,你可以参考下面示例给出的方式 加载 WebAssembly 模块:

  1. 使用 fs.readFileSync 读取 WebAssembly 模块的二进制文件,并使用 WebAssembly.compile 编译模块。
const fs = require('fs');
const buffer = fs.readFileSync('module.wasm');
const module = new WebAssembly.Module(buffer);
  1. 使用 WebAssembly.instantiateWebAssembly.instantiateStreaming 方法直接实例化 WebAssembly 模块。
const fs = require('fs');
const buffer = fs.readFileSync('module.wasm');
const module = new WebAssembly.Module(buffer);
WebAssembly.instantiate(module).then(instance => {
  // ...
});

2. WebAssembly JavaScript API 详解

2.1 API 概述

2.1.1 JavaScript 的 WebAssembly 对象是一个命名空间对象

在逐个讲解前,我们一定要先注意,类似于 Math 对象 或者 Intl 对象

JavaScript 中,WebAssembly 不是一个构造函数(它不是一个函数对象),而是所有 WebAssembly 相关功能的 命名空间。——和大多数全局对象不一样。

一般我们主要通过 WebAssembly 对象上提供的:

2.1.2 API 一览表

普通函数
API 描述
instantiate() 编译和实例化 WebAssembly 代码的主要的 API,它返回一个 Module 及其第一个 Instance 实例。
instantiateStreaming() 直接从流式底层源编译和实例化 WebAssembly 模块,同时返回 Module 及其第一个Instance实例。
compile() WebAssembly 二次代码编译为一个 WebAssembly.Module,不进行实例化。
compileStreaming() 直接从流式底层源代码编译 WebAssembly.Module,将实例化作为一个单独的步骤
用作构造器函数

这些函数用于通过 JavaScript 函数的 构造调用 以创建他们表示的同名对象实例,相当于基于类的面向对象编程语言中某个类的构造方法,因此用的都是大写字母开头。不了解的可以参考我的另外一篇博文 https://blog.csdn.net/qq_28550263/article/details/123418894

API 描述 说明
Global(descriptor, value) 创建一个新的 Global 对象实例。 Global 对象表示一个全局变量实例,可以被 JavaScript 和 importable/exportable 访问 ,跨越一个或多个WebAssembly.Module 实例。他允许被多个 modules 动态连接。
Module(bufferSource) 创建一个新的 Module 对象实例。 Module 对象包含已经由浏览器编译的无状态 WebAssembly 代码,可以高效地与 Worker 共享和多次实例化。
Memory(memoryDescriptor) 创建一个新的 Memory 对象实例。 Memory 对象是一个可调整大小的ArrayBuffer或SharedArrayBuffer,用于保存 WebAssembly.Instance 访问的原始内存字节。
Table(tableDescriptor) 创建一个新的 Table 对象实例。
CompileError(message, fileName, lineNumber) 创建一个新的 CompileError 对象实例。 CompileError 对象表示 WebAssembly 解码或验证期间的错误。
LinkError(message, options) 创建一个新的 LinkError 对象实例。 LinkError 对象指示模块实例化期间的错误(除了来自start函数的 traps 之外)。
RuntimeError(message, options) 创建一个新的 RuntimeError 对象实例。
Instance(module, importObject) 创建一个新的 Instance 对象实例。 Instance 对象包含所有 导出的 WebAssembly 函数,这些函数允许从 JavaScript 调用 WebAssembly 代码。
Tag(type) 创建一个新的 Tag 对象实例。 .Tag对象定义了一种可以向 WebAssembly 代码抛出或从中抛出的 WebAssembly 异常类型。(这是一个新API)
Exception(tag, payload, options) 创建一个新的 Exception 对象实例。 Exception对象表示从 WebAssembly 抛出到 JavaScript 或 从 JavaScript 抛出到 WebAssembly 异常处理程序的 运行时异常。(这是一个新API)

2.2 WebAssembly API 中的普通函数

2.2.1 instantiate() 函数

该方法从已编译的 WebAssembly 模块创建一个实例。

其语法格式为:

WebAssembly.instantiate(bufferSource, importObject)

其中参数:

  • bufferSource:包含 WebAssembly 模块字节码的 ArrayBuffer、TypedArray 或 DataView。
  • importObject(可选):一个对象,用于传递给 WebAssembly 模块的导入对象。

例如:

// 发起对 WebAssembly 模块的 HTTP 请求
const response = await fetch('module.wasm');  
// 将响应转换为 ArrayBuffer
const buffer = await response.arrayBuffer();  
// 使用 ArrayBuffer 创建 WebAssembly 模块实例
const module = await WebAssembly.instantiate(buffer);  
// 获取 WebAssembly 实例对象
const instance = module.instance;

2.2.2 instantiateStreaming() 函数

该方法通过流式加载已编译的 WebAssembly 模块,并创建一个实例。

其语法格式为:

WebAssembly.instantiateStreaming(source, importObject)

其中参数:

  • source:一个表示可通过 HTTP 请求获取 WebAssembly 模块的 URL 字符串或 Response 对象。
  • importObject(可选):一个对象,用于传递给 WebAssembly 模块的导入对象。

例如:

// 流式加载并实例化 WebAssembly 模块
const module = await WebAssembly.instantiateStreaming(fetch('module.wasm'));  
// 获取 WebAssembly 实例对象
const instance = module.instance;

2.2.3 compile() 函数

该方法将 WebAssembly 模块的字节码编译成一个可执行的模块对象。

其语法格式为:

WebAssembly.compile(bufferSource)

其中参数:

  • bufferSource:包含 WebAssembly 模块字节码的 ArrayBuffer、TypedArray 或 DataView。

例如:

// 发起对 WebAssembly 模块的 HTTP 请求
const response = await fetch('module.wasm');  
// 将响应转换为 ArrayBuffer
const buffer = await response.arrayBuffer();  
// 将 ArrayBuffer 编译成可执行的 WebAssembly 模块对象
const module = await WebAssembly.compile(buffer);

2.2.4 compileStreaming() 函数

该方法通过流式加载 WebAssembly 模块的字节码,并将其编译成一个可执行的模块对象。其语法格式为:

WebAssembly.compileStreaming(source)

其中参数:

  • source:一个表示可通过 HTTP 请求获取 WebAssembly 模块的 URL 字符串或 Response 对象。

例如:

const module = await WebAssembly.compileStreaming(fetch('module.wasm'));

2.3 WebAssembly API 中的构造函数

2.3.1 Module() 构造函数 与 Module 对象

WebAssembly.Module 对象的构造函数

WebAssembly.Module() 构造函数 用于创建一个 WebAssembly.Module 实例对象。它接受一个 ArrayBuffer 作为参数,并返回一个模块对象,用于后续的实例化操作。

该构造函数的类型签名即下一节 Module 对象的类型签名 中的 new 方法的签名,这里不重复给出。

例如:

fetch('module.wasm')
  .then(response => response.arrayBuffer())
  .then(buffer => {
    const module = new WebAssembly.Module(buffer);
    // 使用模块进行实例化等操作
  });
Module 对象解析

WebAssembly.Module 对象类型签名为:

var WebAssembly.Module: {
    new (bytes: BufferSource): Module;
    prototype: Module;
    customSections(moduleObject: Module, sectionName: string): ArrayBuffer[];
    exports(moduleObject: Module): ModuleExportDescriptor[];
    imports(moduleObject: Module): ModuleImportDescriptor[];
}
customSections 方法

该方法用于获取模块中自定义的节(section)。

其中参数:

  • moduleObject 是一个 WebAssembly.Module 对象,
  • sectionName 是一个字符串,表示要获取的自定义节的名称。

该方法返回一个数组,这个数组包含了指定名称的自定义节的内容。

例如:

const response = await fetch('module.wasm');  
// 将响应转换为 ArrayBuffer
const buffer = await response.arrayBuffer();  
// 将 ArrayBuffer 编译成可执行的 WebAssembly 模块对象
const module = await WebAssembly.compile(buffer);  
const customSections = WebAssembly.Module.customSections(module, 'custom_section_name');
console.log(customSections);
exports 方法

该方法用于获取模块中的导出项(exports)信息。

其中参数:

  • module 是一个 WebAssembly.Module 对象。

该方法返回一个数组,包含了模块中所有导出项的信息。

例如:

const response = await fetch('module.wasm');
// 将响应转换为 ArrayBuffer
const buffer = await response.arrayBuffer();
// 将 ArrayBuffer 编译成可执行的 WebAssembly 模块对象
const module = await WebAssembly.compile(buffer);
const customSections = WebAssembly.Module.customSections(module, 'custom_section_name');
console.log(customSections);
imports 方法

该方法用于获取模块中的导入项(imports)信息。

其中参数:

  • module 是一个 WebAssembly.Module 对象。

该方法返回一个数组,包含了模块中所有导入项的信息。

例如:

const response = await fetch('module.wasm');
// 将响应转换为 ArrayBuffer
const buffer = await response.arrayBuffer();
// 将 ArrayBuffer 编译成可执行的 WebAssembly 模块对象
const module = await WebAssembly.compile(buffer);
const imports = WebAssembly.Module.imports(module);
console.log(imports);

2.3.2 Global() 构造函数 与 Global 对象

WebAssembly.Global 对象的构造函数

WebAssembly.Global() 构造函数 用于创建一个 WebAssembly.Global 实例对象

该构造函数的类型签名即下一节 Global 对象的类型签名 中的 new 方法的签名,这里不重复给出。

Global 对象解析

Global 对象的类型签名为:

var WebAssembly.Global: {
    new (descriptor: GlobalDescriptor, v?: any): Global;
    prototype: Global;
}

这个对象没有需要解释的其它方法。

2.3.3 Instance() 构造函数 与 Instance 对象

WebAssembly.Instance 对象的构造函数

WebAssembly.Instance() 构造函数 用于创建一个 WebAssembly.Instance 实例对象。它接受一个 WebAssembly.Module 对象和一个可选的导入对象作为参数,并返回一个实例对象,用于调用 WebAssembly 模块中的函数和访问导出的功能。

该构造函数的类型签名即下一节 Instance 对象的类型签名 中的 new 方法的签名,这里不重复给出。

例如:

fetch('module.wasm')
  .then(response => response.arrayBuffer())
  .then(buffer => {
    // 创建 wasm 的 Module 对象实例
    const module = new WebAssembly.Module(buffer);
    // 创建 wasm 的 Instance 对象实例
    const instance = new WebAssembly.Instance(module, { /* imports */ });
    // 使用实例调用导出的函数等操作
  });
WebAssembly.Instance 对象

Instance 对象的类型签名为:

var WebAssembly.Instance: {
    new (module: Module, importObject?: Imports): Instance;
    prototype: Instance;
}

这个对象没有需要解释的其它方法。

2.3.4 Memory() 构造函数 与 Memory 对象

WebAssembly.Memory 对象的构造函数

WebAssembly.Memory() 构造函数用于创建一个 WebAssembly.Memory 实例对象。它接受一个描述内存大小的页数作为参数,并返回一个内存对象,用于 WebAssembly 模块中的内存访问操作。

该构造函数的类型签名即下一节 Memory 对象的类型签名 中的 new 方法的签名,这里不重复给出。

例如:

const memory = new WebAssembly.Memory({ initial: 10, maximum

Memory 实例对象的 buffer 属性是一个可调整大小的 ArrayBuffer ,其内存储的是 WebAssembly 实例 所访问内存的原始字节码。

WebAssembly.Memory 对象

Memory 对象的类型签名为:

var WebAssembly.Memory: {
    new (descriptor: MemoryDescriptor): Memory;
    prototype: Memory;
}

这个对象没有需要解释的其它方法。

2.3.5 Table() 构造函数 与 Table 对象

WebAssembly.Table 对象的构造函数

WebAssembly.Table() 构造函数用于创建一个 WebAssembly.Table 实例对象。Table() 构造函数主要传入的是以下两个参数:

  • initial:指定表的初始大小(以元素数量表示),默认为 0。
  • element:指定表中每个元素的类型(函数引用类型),默认为 {element: “anyfunc”}。

可以参考该对象类型签名及进行理解。该构造函数的类型签名即下一节 Table 对象的类型签名 中的 new 方法的签名,这里不重复给出。

例如:

// 创建一个初始大小为 10 的 WebAssembly 表,存储任意函数引用类型
const table = new WebAssembly.Table({ initial: 10 });
// 向表中添加函数引用
table.grow(2); // 扩展表的大小为 12
table.set(0, myFunction); // 将 myFunction 设置为索引为 0 的元素
table.set(1, anotherFunction); // 将 anotherFunction 设置为索引为 1 的元素
// 调用表中的函数
table.get(0)(); // 调用索引为 0 的函数
WebAssembly.Table 对象

Table 对象的类型签名为:

type TableKind = "anyfunc" | "externref";
interface TableDescriptor {
    element: TableKind;
    initial: number;
    maximum?: number;
}
var WebAssembly.Table: {
    new (descriptor: TableDescriptor, value?: any): Table;
    prototype: Table;
}

TableKind 类型表示一个对象,表示表中每个元素的类型,可以是以下值之一:

  • “anyfunc”: 任意函数引用类型
  • “funcref”: 函数引用类型

这个对象没有需要解释的其它方法。

2.3.6 RuntimeError() 构造函数 与 RuntimeError 对象

WebAssembly.RuntimeError 对象的构造函数

WebAssembly.RuntimeError() 构造函数用于创建一个 WebAssembly.RuntimeError 实例对象。通过构造调用该对象,可以创建 WebAssembly 运行时错误(Runtime Error)。

其中参数:

  • message:一个可选的字符串,表示错误消息。

例如:

// 创建一个自定义的 WebAssembly 运行时错误
const error = new WebAssembly.RuntimeError("Custom runtime error occurred.");
throw error; // 抛出错误
WebAssembly.RuntimeError 对象

RuntimeError 对象用于在 WebAssembly 模块执行期间抛出自定义的运行时错误。通过 抛出自定义的 WebAssembly.RuntimeError,你可以在 WebAssembly 模块 的 执行期间捕获并处理特定的运行时错误情况

该对象的类型签名为:

var WebAssembly.RuntimeError: {
    (message?: string): RuntimeError;
    new (message?: string): RuntimeError;
    prototype: RuntimeError;
}

通过抛出自定义的 WebAssembly.RuntimeError,你可以在 WebAssembly模块的执行期间 捕获并处理特定的运行时错误情况。

【注】:WebAssembly.RuntimeError 是一个构造函数,用于创建错误对象。它不是 JavaScript 中内置的异常类型,而是用于在 WebAssembly 环境中表示运行时错误的特定对象。

这个对象没有需要解释的其它方法。

2.3.7 CompileError() 构造函数 与 CompileError 对象

WebAssembly.CompileError 对象的构造函数

WebAssembly.CompileError() 构造函数 用来创建一个 WebAssembly.CompileError 实例对象,以实现在编译 WebAssembly 模块时抛出自定义的编译错误。

其中参数:

  • message:一个可选的字符串,表示错误消息。

例如:

// 创建一个自定义的 WebAssembly 编译错误
const error = new WebAssembly.CompileError("Custom compile error occurred.");
throw error; // 抛出错误
WebAssembly.CompileError 对象

CompileError 对象的类型签名为:

var WebAssembly.CompileError: {
    (message?: string): CompileError;
    new (message?: string): CompileError;
    prototype: CompileError;
}

通过抛出 自定义的 WebAssembly.CompileError,你可以在编译 WebAssembly 模块时捕获并处理特定的编译错误情况。

【注】:WebAssembly.CompileError不是 JavaScript 中内置的异常类型,而是用于在 WebAssembly 环境中表示编译错误的特定对象。

2.3.8 LinkError() 构造函数 与 LinkError 对象

WebAssembly.LinkError 对象的构造函数

WebAssembly.LinkError() 构造函数 用于创建一个 WebAssembly.LinkError 实例对象,从而在链接 WebAssembly 模块时抛出自定义的链接错误。

其中参数:

  • message:一个可选的字符串,表示错误消息。

例如:

// 创建一个自定义的 WebAssembly 链接错误
const error = new WebAssembly.LinkError("Custom link error occurred.");
throw error; // 抛出错误
WebAssembly.LinkError 对象

LinkError 对象的类型签名为:

var WebAssembly.LinkError: {
    (message?: string): LinkError;
    new (message?: string): LinkError;
    prototype: LinkError;
}

通过抛出自定义的 WebAssembly.LinkError,你可以在 链接 WebAssembly 模块时 捕获并处理特定的链接错误情况。

【注】:WebAssembly.LinkError 是一个构造函数,用于创建错误对象。它不是 JavaScript 中内置的异常类型,而是用于在 WebAssembly 环境中表示链接错误的特定对象。

这个对象没有需要解释的其它方法。

2.3.9 Exception() 构造函数 与 Exception 对象

WebAssembly 技术仍在不断发展和演进中,新的功能和规范也可能随着时间推移而推出。目前谷歌 Chrome 浏览器等浏览器已经支持该对象,不过不能确保所有就有的浏览器都被部分支持。笔者尚未实际使用过,因此先介绍过来,待日后获取更多信息再对本小节内容进行调整。

该对象的 W3C 文档位置为:https://webassembly.github.io/exception-handling/js-api/#runtime-exceptions

WebAssembly.Exception 对象的构造函数

WebAssembly.Exception() 构造函数 用于创建一个 WebAssembly.Exception 实例对象 其语法格式为:

new Exception(tag, payload)
new Exception(tag, payload, options)

其中:

  • tag:用于定义 WebAssembly.Tag 中每个值的预期数据类型payload。
  • payload:包含异常负载的一个或多个数据字段的数组。元素必须匹配 中相应元素的数据类型 tag。如果有效负载中的数据字段数量与其类型不匹配,TypeError 则会抛出异常。
  • options(可选):具有以下可选字段的对象:
  • traceStack:如果 Exception 可能有一个堆栈跟踪附加到它的 stack 属性,则为 true,否则为 false。默认情况下,这是 false (如果未提供 optionsoptions.traceStack)。
WebAssembly.Exception 对象

它表示表示从 WebAssembly 抛出到 JavaScript 或从 JavaScript 抛出到 WebAssembly 异常处理程序的运行时异常。

Exception 访问抛出的异常的参数需要用于创建 的同一 Tag。提供了方法来测试异常是否与特定标记匹配,以及通过索引获取特定值(如果异常与指定标记匹配)。

当共享关联标签时,JavaScript 和其他客户端代码只能访问 WebAssembly 异常值,反之亦然(您不能只使用恰好定义相同数据类型的另一个标签)。如果没有匹配的标记,异常可以被捕获并重新抛出,但它们无法被检查。

用法例如:

// 创建标记并使用它来创建异常
const tag = new WebAssembly.Tag({ parameters: ["i32", "f32"] });
const exception = new WebAssembly.Exception(tag, [42, 42.3]);
实例属性 stack

返回异常的堆栈跟踪,或 undefined。

WebAssembly.Exception.prototype.stack

非标准:此功能是非标准的,不在标准轨道上。不要在面向 Web 的生产站点上使用它:它不适用于每个用户。实现之间也可能存在很大的不兼容性,并且行为可能会在未来发生变化。

2.3.10 Tag() 构造函数 与 Tag 对象

WebAssembly 技术仍在不断发展和演进中,新的功能和规范也可能随着时间推移而推出。目前谷歌 Chrome 浏览器等浏览器已经支持该对象,不过不能确保所有就有的浏览器都被部分支持。笔者尚未实际使用过,因此先介绍过来,待日后获取更多信息再对本小节内容进行调整。

该对象的 W3C 文档位置为:https://webassembly.github.io/exception-handling/js-api/#dom-tag-tag

WebAssembly.Tag 对象的构造函数

WebAssembly.Tag() 构造函数 用于创建一个 WebAssembly.Tag 实例对象 其语法格式为:

new WebAssembly.Tag(type)
WebAssembly.Tag 对象
type() 方法

该方法返回为标签定义数据类型数组的对象(在其构造函数中设置)。例如:

// 该例子为 MDN 给出,但是目前笔者测试的浏览器似乎并不支持。
const tagToImport = new WebAssembly.Tag({ parameters: ["i32", "f32"] });
console.log(tag.type());
// Console output:
// Object { parameters: (2) […] }
//   parameters: Array [ "i32", "i64" ]
//   <prototype>: Object { … }
目录
相关文章
|
1月前
|
JavaScript 前端开发
JavaScript随手笔记 --- 对数据进行判断最大位数是否超过八位
JavaScript随手笔记 --- 对数据进行判断最大位数是否超过八位
|
1月前
|
JavaScript 前端开发
JavaScript随手笔记 --- 用正则表达式匹配字符串是否为运算公式
JavaScript随手笔记 --- 用正则表达式匹配字符串是否为运算公式
|
30天前
|
JavaScript 前端开发 Java
JavaScript高级笔记-coderwhy版本(六)
JavaScript高级笔记-coderwhy版本
74 0
|
30天前
|
JavaScript 前端开发 Java
JavaScript高级笔记-coderwhy版本(一)
JavaScript高级笔记-coderwhy版本
34 0
JavaScript高级笔记-coderwhy版本(一)
|
1月前
|
JSON JavaScript 前端开发
Node.JS第二讲笔记
Node.JS第二讲笔记
32 0
|
1月前
|
JavaScript 前端开发 索引
JavaScript随手笔记---对比数组差异
JavaScript随手笔记---对比数组差异
JavaScript随手笔记---对比数组差异
|
1月前
|
JavaScript 前端开发
JavaScript随手笔记---轮播图(点击切换)
JavaScript随手笔记---轮播图(点击切换)
JavaScript随手笔记---轮播图(点击切换)
|
1月前
|
JSON JavaScript 前端开发
JavaScript随手笔记---数组中相同的元素进行分组(数据聚合) groupBy函数
JavaScript随手笔记---数组中相同的元素进行分组(数据聚合) groupBy函数
|
1月前
|
JavaScript 前端开发
JavaScript随手笔记---保留小数位
JavaScript随手笔记---保留小数位
|
1月前
|
数据采集 API 开发者
调用API接口获取小红书笔记详情数据(小红书怎么推广)
小红书平台对于其API的使用有严格的规定和限制,并且并非所有的功能和数据都通过公开API提供。关于获取小红书笔记详情的API,以下是一些建议和指导: