现代 JavaScript 教程:手写 `concat` 函数拼接 `Uint8Array` 类型化数组
文档教程前端【免费下载链接】zh.javascript.info现代 JavaScript 教程The Modern JavaScript Tutorial以最新的 ECMAScript 规范为基准通过简单但足够详细的内容为你讲解从基础到高阶的 JavaScript 相关知识。项目地址https://gitcode.com/gh_mirrors/zh/zh.javascript.info点击查看免费下载导读在 Web 开发中二进制数据文件上传、下载、图像处理几乎无处不在而 JavaScript 处理二进制数据的核心载体就是ArrayBuffer及其上的类型化数组视图TypedArray。然而类型化数组并不像普通Array那样自带concat方法本文基于现代 JavaScript 教程仓库中 4-binary/01-arraybuffer-binary-arrays 章节的实战练习对应任务见 task.md完整讲解如何手写一个concat(arrays)函数把多个Uint8Array片段拼接成单一数组。读完本文你将掌握类型化数组的set批量拷贝机制、reduce统计长度的方法以及如何基于BYTES_PER_ELEMENT理解底层内存布局并能独立解决此类二进制数据拼接需求。为什么需要手写concatTypedArray 方法的缺失普通数组Array拥有丰富的方法但类型化数组TypedArray即Uint8Array、Uint16Array、Float64Array等视图的统称与普通数组存在两个显著差异。在 article.md 的 TypedArray 方法 一节中明确指出没有splice无法删除一个值因为类型化数组是缓冲区buffer上的视图而缓冲区是固定的、连续的内存区域我们所能做的只是分配一个零值没有concat方法这正是本练习需要手写concat的直接原因。类型化数组虽然支持map、slice、find、reduce等常规数组方法但针对拼接场景它提供了两个关键替代工具arr.set(fromArr, [offset])从offset默认为 0开始将fromArr中的所有元素复制到arrarr.subarray([begin, end])创建从begin到end不包括的同类型新视图与slice类似但不复制任何内容只是对同一段数据开一个新窗口。其中set方法就是实现拼接的核心它让我们能够把多个来源数组依次写入一个预先分配好的目标数组。任务要求把多个 Uint8Array 片段拼成一个练习的任务描述非常简洁见 task.md给定一个Uint8Array数组请写一个函数concat(arrays)将数组拼接成一个单一数组并返回。配套的任务模板source.js给出了调用示例function concat(arrays) { // ...your code... } let chunks [ new Uint8Array([0, 1, 2]), new Uint8Array([3, 4, 5]), new Uint8Array([6, 7, 8]) ]; console.log(Array.from(concat(chunks))); // 0, 1, 2, 3, 4, 5, 6, 7, 8 console.log(concat(chunks).constructor.name); // Uint8Array从模板可以提炼出两条隐含验收标准内容正确拼接结果应为[0, 1, 2, 3, 4, 5, 6, 7, 8]类型保持返回值的构造器必须是Uint8Array即结果仍是类型化数组而不是普通数组。解题思路先算总长再依次 set 拷贝实现concat的核心思路分三步统计总长度用reduce累加所有子数组的length得到结果数组所需的元素个数预分配结果数组用new Uint8Array(totalLength)一次性分配内存元素个数 × 每元素字节数BYTES_PER_ELEMENT 底层ArrayBuffer的字节数逐个拷贝维护一个游标length对每个子数组调用result.set(array, length)把内容写入目标数组的指定偏移位置然后让游标累加该子数组的长度保证下一段紧接上一段之后。这里不需要考虑字节对齐或元素大小换算——因为输入输出都是同一类型Uint8Array每个元素恰好占 1 个字节元素个数就是字节偏移量若换成Uint16Array底层set依然按元素为单位拷贝偏移量同样是元素索引而非字节索引。官方参考解法与逐行解读仓库中给出了官方解法完整代码见 _js.view/solution.jsfunction concat(arrays) { // sum of individual array lengths let totalLength arrays.reduce((acc, value) acc value.length, 0); let result new Uint8Array(totalLength); if (!arrays.length) return result; // for each array - copy it over result // next array is copied right after the previous one let length 0; for(let array of arrays) { result.set(array, length); length array.length; } return result; }逐段解读let totalLength arrays.reduce((acc, value) acc value.length, 0);第 3 行reduce从初始值 0 开始累加每个子数组的length。类型化数组与普通数组一样有length属性因此这一步对Uint8Array、Uint16Array等任何类型化数组都通用。let result new Uint8Array(totalLength);第 5 行创建长度元素个数为totalLength的新类型化数组。它会在内部自动创建对应字节数的ArrayBuffer并预填充 0。这是典型的先分配、后填充模式避免在循环中反复扩容。if (!arrays.length) return result;第 7 行空输入时直接返回空数组。这既是一种短路优化也让空输入行为变得明确——返回长度为 0 的Uint8Array而不会因为循环不执行而出现其他意外。result.set(array, length); length array.length;第 13-14 行这是拼接的核心。set方法把当前子数组整体拷贝到结果数组的length偏移处随后游标前进当前子数组的长度使下一段拷贝紧接其后等价于完成了串行拼接。注意result.set的语义是元素级批量拷贝它把源数组的每个元素值复制到目标数组而不是共享底层内存。因此即使后续修改chunks中的原始片段也不会影响已拼接好的result。测试用例验证类型、内容与空输入仓库为本题编写了完整的测试_js.view/test.js覆盖三个关键行为describe(concat, function() { let chunks [ new Uint8Array([0, 1, 2]), new Uint8Array([3, 4, 5]), new Uint8Array([6, 7, 8]) ]; it(result has the same array type, function() { let result concat(chunks); assert.equal(result.constructor, Uint8Array); }); it(concatenates arrays, function() { let result concat(chunks); assert.deepEqual(result, new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7, 8])); }); it(returns empty array on empty input, function() { let result concat([]); assert.equal(result.length, 0); }); });三个用例分别验证类型保持result.constructor Uint8Array。由于我们是用new Uint8Array(totalLength)构造结果返回的自然是Uint8Array如果误用Array.from或其他方式返回普通数组此用例就会失败。拼接正确性三个片段[0,1,2]、[3,4,5]、[6,7,8]依次拼成[0..8]assert.deepEqual确保元素值逐位相等。空输入健壮性concat([])返回长度为 0 的类型化数组对应解法中if (!arrays.length) return result;的分支。底层原理从视图理解拼接的本质要真正理解这段代码需要回到类型化数组的本质。ArrayBuffer是对固定长度连续内存区域的引用它本身不携带任何类型信息而Uint8Array等视图对象就是眼镜透过它把ArrayBuffer中的字节解释为特定格式的数字序列——Uint8Array把每个字节视为 0~255 的 8 位无符号整数见 article.md同一块 ArrayBuffer 可以通过不同视图Uint8Array、Uint16Array、Uint32Array、Float64Array解释为不同粒度的数字序列这也是视图不存储数据、只负责解释数据的含义。由此可以推出拼接实现的两个关键结论分配语义new Uint8Array(totalLength)与new ArrayBuffer(totalLength)的区别在于前者自动创建了配套的ArrayBuffer视图除传入ArrayBuffer的第一种构造变体外其他构造方式都会自动创建底层 buffer详见 article.md。result.byteLength恰好等于totalLength × Uint8Array.BYTES_PER_ELEMENT即 1因此元素个数与字节数在本题中数值相等。拷贝语义result.set(array, offset)是 TypedArray 原生方法按元素逐个复制值。这正是固定长度缓冲区上无法 splice/无法 concat这一限制的补偿手段——我们无法原地增删但可以预分配一块足够大的新缓冲区再把旧数据搬进去。扩展思考泛化与边界情况本题的官方解法已足够精炼但在实际工程中还可做如下泛化思考时不妨对照 article.md 中完整的类型化数组清单Int8Array、Uint16Array、Uint32Array、Float32Array、Float64Array等支持任意类型的输入数组若arrays中混有Uint8Array和Uint16Arrayset会在拷贝时自动做类型转换超出目标类型范围的高位会被截断参见 article.md 的越界行为一节。是否需要按最大类型统一结果取决于业务语义。把结果类型参数化可将解法封装为concat(arrays, TypedArrayClass Uint8Array)用new TypedArrayClass(totalLength)构造结果以支持拼接任意类型化数组。大数据量下的性能set是引擎级实现的批量拷贝比逐元素result[i] array[i]循环更快这是官方解法选择set的根本原因。总结类型化数组没有内建的concat方法但借助reduce统计总长度 new TypedArray(totalLength)预分配 set(array, offset)批量拷贝三步即可高效实现多段二进制数据的拼接。本文给出的官方解法solution.js及其配套测试test.js完整覆盖了类型保持、内容正确、空输入三个关键场景可作为后续处理Blob、File分片合并或网络流数据重组时的直接参考。更完整的ArrayBuffer、TypedArray 与DataView知识体系可继续阅读 4-binary/01-arraybuffer-binary-arrays/article.md。赞分享文档教程前端【免费下载链接】zh.javascript.info现代 JavaScript 教程The Modern JavaScript Tutorial以最新的 ECMAScript 规范为基准通过简单但足够详细的内容为你讲解从基础到高阶的 JavaScript 相关知识。项目地址https://gitcode.com/gh_mirrors/zh/zh.javascript.info点击查看免费下载相关推荐JavaScript TypedArray 拼接实战为二进制数组手写 concat 函数JavaScript TypedArray 拼接实战为二进制数组手写 concat 函数 导读 本篇文章基于《现代 JavaScript 教程》中文仓库 4文档教程前端手写 Uint8Array 拼接函数en.javascript.info 中的 TypedArray concat 实战任务解析手写 Uint8Array 拼接函数en.javascript.info 中的 TypedArray concat 实战任务解析 本篇技术指南以 The Mo文档/教程前端type-challenges 第 533 题 Concat在类型系统里实现数组拼接type challenges 第 533 题 Concat在类型系统里实现数组拼接 导读 本指南围绕 type challenges 仓库中的第 533 道示例工程上一篇Rust pcap未来展望即将到来的令人兴奋的新特性下一篇5个ffmpeg-python帧操作技巧视频编辑入门完全指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

前端性能优化实战:从图片压缩、懒加载到CDN缓存的完整方案

前端性能优化实战:从图片压缩、懒加载到CDN缓存的完整方案

1. 被老板盯上的那一刻,我们得先分清“慢”到底是从哪来的我先说个真实的场景。某次上线前的演示,老板随手点开我们刚做完的一个商品详情页,图片一张张在手机屏幕上“撑开”,视频首帧黑了两秒才出画面,页面滚动起来头像…

2026/10/9 5:14:23 阅读更多 →
AnyPS5:跨平台PS5手柄协议桥接技术解析

AnyPS5:跨平台PS5手柄协议桥接技术解析

项目标题:“AnyPS5”本身是一个高度凝练、带有明显技术产品命名风格的代号,但当前输入中未提供任何实质性描述——无项目正文、无关键词列表、无摘要描述,仅有一个孤立标题与空置的热搜词栏。这在真实从业场景中其实非常典型:我们…

2026/10/9 5:14:23 阅读更多 →
并联式混合动力Simulink控制策略模型搭建全解析

并联式混合动力Simulink控制策略模型搭建全解析

做混动整车仿真这几年,有一个体会特别深:并联式混合动力系统Simulink控制策略模型,表面上是个建模问题,实际上是个决策问题。它真正检验的不是你会不会搭Simulink模块,而是你能不能把“发动机和电机分别在什么时刻出力…

2026/10/9 5:14:23 阅读更多 →

最新新闻

工业无机盐科普:无水硫酸钠理化特性与工业应用介绍丨广东大小化工有限公司

工业无机盐科普:无水硫酸钠理化特性与工业应用介绍丨广东大小化工有限公司

无水硫酸钠,是工业生产中非常常见的无机盐原料,属于基础性化工辅料。因为稳定性好、适用性广、杂质可控,被大量应用在轻工、化工、建材、印染等行业。很多工厂日常使用频繁,但对其完整特性与正确储存方式了解不多。一、无水硫酸钠…

2026/10/9 5:38:42 阅读更多 →
FDE深度解析:月薪50-70K·15薪的能力结构及进阶路径,小白程序员必收藏!

FDE深度解析:月薪50-70K·15薪的能力结构及进阶路径,小白程序员必收藏!

本文从薪酬角度解析FDE(Field Data Engineer)岗位的能力要求,50-70K15薪对应行业洞见、技术整合、现场交付、资产沉淀四重能力叠加。FDE承担交付结果,薪资高于传统工程师。文章阐述FDE的进阶路径,从线性增长到资产沉淀…

2026/10/9 5:38:42 阅读更多 →
ThreadLocal系列(四):父子线程信息传递与TTL

ThreadLocal系列(四):父子线程信息传递与TTL

父子线程信息传递与TTL前面介绍了ThreadLocal使用与内存泄漏防范,还从引用队列角度思考如何防范内存泄漏。 这篇文章是自己在实际中用到了RAG检索与回答用自定义线程池而不是tomcat线程池,防止tomcat线程池线程被占用导致无法处理其他请求。 其中用到了跨…

2026/10/9 5:38:42 阅读更多 →
园区网关表免集中器怎么接?4G 母表带子表拓扑

园区网关表免集中器怎么接?4G 母表带子表拓扑

园区网关表,通常指的是一台带 4G 上行的母表,经 RS485 带多台子表、替现场省掉独立集中器的方案。该方案适用于楼栋集中、不想动原有布线的老旧园区。摘要:本文介绍园区网关表方案——以一台带 4G 上行的母表经 RS485 带多台子表,…

2026/10/9 5:38:42 阅读更多 →
软件测试与开发:思维模式、技术栈及职业发展的深度对比

软件测试与开发:思维模式、技术栈及职业发展的深度对比

1. “测试就是点点点”这句话,坑了多少人我在这个行业里待了十几年,见过不少刚入行的新人,也带过不少团队。一个特别有意思的现象是:很多开发同学对测试工作的认知,基本停留在“他们就是点点点,找找bug&…

2026/10/9 5:38:42 阅读更多 →
民心与文脉:穿透华夏千年兴衰的终极密码

民心与文脉:穿透华夏千年兴衰的终极密码

摘要 纵观华夏千年王朝更迭与近代势力兴衰,战争胜负、兵力强弱、疆域大小并非政权成败的核心决定因素。 真正决定历史走向的恒定规律,在于政权是否顺应底层民心、是否扎根华夏本土文脉。 本文以近代多方势力兴衰为样本,逐条拆解历史轮回底层…

2026/10/9 5:37:41 阅读更多 →

日新闻

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API这个话题,隔三差五就会在群里被翻出来讨论一次。上周还有个同事线上处理一个订单超时问题,排查到最后发现是ZonedDateTime序列化后时区丢了,用户在下单当天晚上看到的时间整整差了8个小时。这类问题几乎每个做Java开发的人都遇到过…

2026/10/9 0:00:49 阅读更多 →
EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

前几个月我手头有好几台机器需要互相访问:办公室台式机、家里 NAS、还有一台云主机。如果只是偶尔传个文件倒还好,问题是工作场景经常要在几处环境之间来回切换,每次都先登录跳板机再层层代理,实在折腾。我先后试过端口映射、自建…

2026/10/9 0:00:49 阅读更多 →
AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent 这个词在过去一年里被反复提及,但真正动手搭过一套能跑起来的 Agent 系统的人都知道,从"知道它是什么"到"让它稳定干活"之间隔着一整套工程决策。我前后参与过几个 Agent 项目的落地,从最初用现成框架拼装&…

2026/10/9 0:01:50 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:32 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:40 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 10:10:36 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 21:13:17 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 13:34:55 阅读更多 →