探索优雅的处理 JavaScript 类数组对象的技巧

news2024/10/5 15:31:42

一. 引言

在 JavaScript 编程中,我们经常遇到类数组对象,它们拥有类似数组的结构和行为,但却不具备真正的数组方法和属性。常见的类数组对象包括 DOM 集合、函数的 arguments 对象和字符串等。如果我们想对这些类数组对象进行操作和处理,我们需要掌握一些优雅的技巧。

处理类数组对象的见方法有循环迭代、转换为数组、使用数组方法、使用 Array.prototype 方法、使用解构赋值以及其他一些殊情况的处理。本篇文章中,我们将介绍这些方法,并给出一些实用的示例。

通过优雅地处理类数组对象,我们可以更加灵活地操作和处理数据,从而提高开发效率和代码质量。无论是处理 DOM 元素、函数参数还是字符串,了解这些优雅的技巧都能让我们更游刃有余。

接下来让我们一起来认识如何优雅地处理类数组对象,实现 JavaScript 神奇的转变!

二. 了解类数组对象

1. 什么是类数组对象

类数组对象是指在 JavaScript 中具有类似数组的特点,但并非真正的数组。它们与数组相似,可以通过索引访问元素,并且具有length属性来表示元素的个数。但与真正的数组不同,类数组对象不具备数组原型链上的方法和属性。

例如:

const obj = {
  0: "apple",
  1: "banana",
  2: "orange",
  length: 3,
};

console.log(obj.length); // 输出: 3

2. 常见的类数组对象

(1)arguments对象:在函数内部可用的特殊对象,存储了函数参数的类数组对象。

function sum() {
  console.log(arguments);
}

sum(1, 2, 3); // Arguments(3) [1,2, 3, callee: f, Symbol(Symbol.iterator): f]


(2)NodeList对象:DOM 元素的集合,通过像document.querySelectorAll()方法获取

<ul id="list" style="width: 100px; margin: 0; float: left">
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
</ul>

<script>
  const paragraphs = document.querySelectorAll("li");
  console.log(paragraphs.length); // 输出: 指定选择器的li元素个数
  console.log(paragraphs); // 输出: 指定选择器的li元素
  console.log(paragraphs[0]); // 输出: 第一个li元素
</script>


(3)HTMLCollection对象:表示一组 DOM 元素的集合,例如通过类似getElementsByClassName、getElementsByTagName等方法获取的元素集合。

<button class="btn">第一个按钮</button>
<button class="btn">第二个按钮</button>

<script>
  const buttons = document.getElementsByClassName("btn");
  console.log(buttons.length); // 输出: 指定类名的按钮元素个数
  console.log(buttons); // 输出: 指定类名的按钮元素
  console.log(buttons[0]); // 输出: 指定索引的按钮元素
</script>


(4)TypedArray对象:表示一定长度的二进制数据缓冲区的类数组对象,例如Int8Array、Uint8Array等。

const buffer = new ArrayBuffer(8); // 创建一个8字节的缓冲区
const intArray = new Int32Array(buffer); // 使用Int32Array视图包装缓冲区

console.log(intArray);
console.log(intArray[0]); // 输出: 0

intArray[0] = 42;
console.log(intArray);
console.log(intArray[0]); // 输出: 42


(5)FileList:表示一组文件的集合,通常来自于文件上传 input 元素

<input type="file" multiple="true" />

<script>
  window.onload = function (event) {
    init();
  };
  function init() {
    const fileInput = document.querySelector('input[type="file"]');
    fileInput.onchange = onFileChange;
  }
  function onFileChange(event) {
    const files = event.target.files;
    console.log(files.length); // 输出: 选择的文件数量
    console.log(files); // 输出: 所有文件对象
    console.log(files[0]); // 输出: 第一个文件对象
  }
</script>

这些类数组对象都可以通过索引访问元素,并且具有length属性,但不具备数组原型链上的方法和属性。如果需要使用数组的方法和属性,可以将类数组对象转换为真正的数组,例如通过Array.from、Array.prototype.slice.call、Array.prototype.concat等方法。

三. 类数组对象的特性

这些特性使得类数组对象在某些场景下非常有用,例如处理函数参数(arguments对象),DOM 操作中获取的元素集合(HTMLCollection对象和NodeList对象)等。

1. 索引访问和写入

类数组对象可以通过索引访问元素,读取或者写入数据。可以使用中括号([])操作符来读写类数组对象中的元素。

示例代码:

const obj = {
  0: "apple",
  1: "banana",
  2: "orange",
  length: 3,
};

console.log(obj[0]); // 输出: "apple"
console.log(obj[1]); // 输出: "banana"

obj[2] = "grape";
console.log(obj[2]); // 输出: "grape"

2. 长度属性

类数组对象具有length属性,用于表示对象中元素的个数。可以通过访问length属性来获取类数组对象中元素的数量。

示例代码:

const obj = {
  0: "apple",
  1: "banana",
  2: "orange",
  length: 3,
};

console.log(obj.length); // 输出: 3

3. 迭代类数组对象

类数组对象可以使用迭代方法进行遍历操作,可以使用for循环对其进行迭代操作。或者通过一些方法先将其转换成数组,在对其进行迭代也是可以的!

示例代码:

const obj = {
  0: "apple",
  1: "banana",
  2: "orange",
  length: 3,
};

for (let index = 0; index < obj.length; index++) {
  const element = obj[index];
  console.log(element);
}

使用 for 循环迭代类数组的输出入下图所示:

注意:通过迭代方法进行遍历操作时,最好先将类数组对象转换为真正的数组,以避免出现一些问题。

四. 类数组对象 VS 真正的数组

类数组对象与真正的数组在以下两个方面存在区别:

1. 原型链上的方法和属性

真正的数组具有数组对象的原型链,因此具有丰富的方法和属性,如push、pop、shift、unshift等用于操作数组的方法,以及length、concat、slice等用于处理数组的属性和方法。而类数组对象并没有这些原型方法和属性,使用类数组对象时不能直接调用数组的方法和属性。

示例代码:

const arr = [1, 2, 3];
const obj = {
  0: 1,
  1: 2,
  2: 3,
  length: 3,
};

console.log(arr.push(4)); // 输出: 4
console.log(obj.push(4)); // 报错: obj.push is not a function

console.log(arr.length); // 输出: 4
console.log(obj.length); // 输出: 3

2. 结构差异

类数组对象与真正的数组在内部结构上存在差异。真正的数组是一段连续的内存空间,可以直接通过索引访问到每个元素,而类数组对象并非连续的内存空间,且可能具有非数字索引。类数组对象通常是基于对象实现的,使用非数字索引作为键来存储元素。因此,类数组对象的内部结构与真正的数组不同。

示例代码:

const arr = [1, 2, 3];
const obj = {
  0: 1,
  1: 2,
  2: 3,
  length: 3,
};

console.log(arr[0]); // 输出: 1
console.log(obj[0]); // 输出: 1

console.log(arr[3]); // 输出: undefined
console.log(obj[3]); // 输出: undefined

console.log(arr); // 输出: [1, 2, 3]
console.log(obj); // 输出: {0: 1, 1: 2, 2: 3, length: 3}

总结:尽管类数组对象与真正的数组在某些方面类似,但在原型链上的方法和属性、内部结构方面存在差异。因此,在使用类数组对象时需要注意这些区别,需要根据实际需求进行相应的处理。如有需要,可以将类数组对象转换为真正的数组,以便能够使用数组的方法和属性来操作数据。

五. 处理类数组对象的常见方法

假如有一个类数组对象,如下所示:

const obj = {
  0: "apple",
  1: "banana",
  2: "orange",
  length: 3,
};

下面总结处理以上这个类数组对象的几种方式:

1. 使用数组展开运算符(...)

const arr = [...obj];
console.log(arr); // 输出: ["apple", "banana", "orange"]

2. 使用 Array.from()方法

const arr = Array.from(obj);
console.log(arr); // 输出: ["apple", "banana", "orange"]

3. 使用 Array.prototype.slice.call()方法

const arr = Array.prototype.slice.call(obj);
console.log(arr); // 输出: ["apple", "banana", "orange"]

4. 使用 Array.prototype.map.call()方法

const arr = Array.prototype.map.call(obj, (item) => item);
console.log(arr); // 输出: ["apple", "banana", "orange"]

5. 使用 ES6 的 Array.from()方法与箭头函数

const arr = Array.from(obj, (item) => item);
console.log(arr); // 输出: ["apple", "banana", "orange"]

以上的这些方法可以将类数组对象转换为真正的数组,并可以使用数组的方法和属性对其进行操作。根据实际需求选择适合的方式进行处理。

六. 总结

通过本篇文章,我们了解了在 JavaScript 中处理类数组对象的一些优雅的技巧。这些技巧可以帮助我们更加灵活地操作和处理数据,提高开发效率和代码质量。

首先,我们学习了几种在前端开发中常见的类数组对象。包括:arguments对象、NodeList对象、HTMLCollection对象、TypedArray对象,以及FileList等。

其次,我们了解了如何将类数组对象转换为真正的数组。可以使用 Array.from() 方法、Array.prototype 方法或者扩展运算符(...)来实现转换。这些方法可以让我们方便地使用数组的方法和属性进行处理。

总结来说,处理类数组对象对于 JavaScript 开发者来说是非常重要的,在实际开发中,我们经常遇到类数组对象,只有了解这些处理技巧,我们才能更加轻松地处理数据,编写高效、干净的代码。加油!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1250131.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用 STM32F7 和 TensorFlow Lite 开发低功耗人脸识别设备

本文旨在介绍如何使用 STM32F7 和 TensorFlow Lite框架开发低功耗的人脸识别设备。首先&#xff0c;我们将简要介绍 STM32F7 的特点和能力。接下来&#xff0c;我们将讨论如何使用 TensorFlow Lite 在 STM32F7 上实现人脸识别算法。然后&#xff0c;我们将重点关注如何优化系统…

基于SpringBoot+Redis的前后端分离外卖项目-苍穹外卖(八)

套餐模块功能开发 1. 新增套餐1.1 需求分析和设计1.1.1产品原型&#xff1a;1.1.2接口设计&#xff1a;1.1.3数据库设计&#xff1a; 1.2 代码开发1.2.1 DishController层1.2.2 DishService接口类1.2.3 DishServiceImpl接口实现类1.2.4 DishMapper层1.2.5 DishMapper.xml1.2.6 …

元宇宙现已开放!

在 2023 年 11 月 3 日 The Sandbox 首个全球创作者日上&#xff0c;The Sandbox 联合创始人 Arthur Madrid 和 Sebastien Borget 宣布元宇宙已开放&#xff0c;已创作完整体验的 LAND 持有者可以自行将体验发布至 The Sandbox 地图上。 精选速览 LAND 持有者&#xff1a;如果…

实验室信息管理系统源码,LIS系统源码,lis源码

医学检验(LIS)管理系统源码&#xff0c;云LIS系统全套商业源码 随着全自动生化分析仪、全自动免疫分析仪和全自动血球计数器等仪器的使用&#xff0c;检验科的大多数项目实现了全自动化分析。全自动化分析引入后&#xff0c;组合化验增多&#xff0c;更好的满足了临床需要&…

Android Frameworks 开发总结之七

1.修改android 系统/system/下面文件时权限不够问题 下面提到的方式目前在Bobcat的userdebug image上测试可行&#xff0c;还没有在user上测试过. 修改前: leifleif:~$ adb root restarting adbd as root leifleif:~$ adb disable-verity verity is already disabled using …

集「才华」与「美貌」于一身的原型设计利器—摹客RP

文章目录 画原型做设计&#xff0c;用摹客RP就够了 初遇摹客再遇摹客RP摹客RP简介与注册摹客RP的突出亮点1️⃣拥有海量矢量图标&#xff0c;满足各种设计场景2️⃣打造高扩展性组件&#xff0c;打破传统组件编辑模式3️⃣海量摹客RP模板例子随意挑选4️⃣实现多人实时协同&…

【数据结构】什么是栈?

&#x1f984;个人主页:修修修也 &#x1f38f;所属专栏:数据结构 ⚙️操作环境:Visual Studio 2022 目录 &#x1f4cc;栈的定义 &#x1f4cc;元素进栈出栈的顺序 &#x1f4cc;栈的抽象数据类型 &#x1f4cc;栈的顺序存储结构 &#x1f4cc;栈的链式存储结构 链栈的进…

micro_ros需要用到的hardware

我没有那么长的线啊&#xff0c;所以就用一个4块5的usb转串口看看 没有那么高档的开发板&#xff0c;就用主流的STM32F103C8T6试试看 这应该就是个仿真器了&#xff0c;一个字不认得都能够看的出来吧

《尚品甄选》:后台系统——权限管理之角色管理(debug一遍)

文章目录 一、权限管理介绍二、表结构的设计三、查询角色四、添加角色五、修改角色六、删除角色 一、权限管理介绍 在后台管理系统中&#xff0c;权限管理是指为了保证系统操作的安全性和可控性&#xff0c;对用户的操作权限进行限制和管理。简单的来说就是某一个用户可以使用…

【开源】基于JAVA的计算机机房作业管理系统

项目编号&#xff1a; S 017 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S017&#xff0c;文末获取源码。} 项目编号&#xff1a;S017&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 登录注册模块2.2 课程管理模块2.3 课…

【开源】基于Vue和SpringBoot的食品生产管理系统

项目编号&#xff1a; S 044 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S044&#xff0c;文末获取源码。} 项目编号&#xff1a;S044&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 加工厂管理模块2.2 客户管理模块2.3…

王道p150 14.假设二叉树采用二叉链表存储结构,设计一个算法,求非空二叉树 b的宽度(即具有结点数最多的那一层的结点个数) (c语言代码实现)

采用层次遍历的方法求出所有结点的层次&#xff0c;并将所有结点和对应的层次放在一个队列中。然后通过扫描队列求出各层的结点总数&#xff0c;最大的层结点总数即为二叉树的宽度。 /* A B C D E F …

使用Pytorch从零开始构建Conditional PixelCNN

条件 PixelCNN PixelCNN 是 PixelRNN 的卷积版本&#xff0c;它将图像中的像素视为一个序列&#xff0c;并在看到前面的像素后预测每个像素&#xff08;定义如上和左&#xff0c;尽管这是任意的&#xff09;。PixelRNN 是图像联合先验分布的自回归模型&#xff1a; p ( x ) …

Leetcode 剑指 Offer II 054. 把二叉搜索树转换为累加树

题目难度: 中等 原题链接 今天继续更新 Leetcode 的剑指 Offer&#xff08;专项突击版&#xff09;系列, 大家在公众号 算法精选 里回复 剑指offer2 就能看到该系列当前连载的所有文章了, 记得关注哦~ 题目描述 给定一个二叉搜索树&#xff0c;请将它的每个节点的值替换成树中…

visual studio 下的git

我这个是看视频笔记 YouTube : https://www.youtube.com/watch?vgkDASVE_Hdg 主要内容是&#xff1a;建立git 库&#xff0c; 保存commit&#xff0c; 建立分支 create branch, 合并分支merge branch,比较 diff&#xff0c;Revert ,history,delete branch, rename branch, t…

详解STUN与TR111

STUN协议定义了三类测试过程来检测NAT类型&#xff1a; Test1&#xff1a;STUN Client通过端口{IP-C1:Port-C1}向STUN Server{IP-S1:Port-S1}发送一个Binding Request&#xff08;没有设置任何属性&#xff09;。STUN Server收到该请求后&#xff0c;通过端口{IP-S1:Port-S1}把…

网站定制开发主要分类有哪些|企业 app 软件小程序定制

网站定制开发主要分类有哪些|企业 app 软件小程序定制 网站定制开发是指根据客户需求&#xff0c;为其量身定制设计和开发的网站服务。目前&#xff0c;网站定制开发主要分为以下几个分类&#xff1a; 1.静态网站定制开发&#xff1a;静态网站是由 HTML、CSS 和 JavaScript 等静…

golang defer关键词执行原理与代码分析

使用的go版本为 go1.21.2 首先我们写一个简单的defer调度代码 package mainimport "fmt"func main() {defer func() {fmt.Println("xiaochuan")}() }通过go build -gcflags -S main.go获取到对应的汇编代码 可以在图中看到有个CALL runtime.deferreturn(…

深度解读英伟达新一轮对华特供芯片H20、L20、L2的定位

大家好&#xff0c;我是极智视界&#xff0c;欢迎关注我的公众号&#xff0c;获取我的更多前沿科技分享 邀您加入我的知识星球「极智视界」&#xff0c;星球内有超多好玩的项目实战源码和资源下载&#xff0c;链接&#xff1a;https://t.zsxq.com/0aiNxERDq 因为一直从事 AI 工…

统计二叉树中的伪回文路径 : 用位运用来加速??

题目描述 这是 LeetCode 上的 「1457. 二叉树中的伪回文路径」 &#xff0c;难度为 「中等」。 Tag : 「DFS」、「位运算」 给你一棵二叉树&#xff0c;每个节点的值为 1 到 9 。 我们称二叉树中的一条路径是 「伪回文」的&#xff0c;当它满足&#xff1a;路径经过的所有节点值…