关于javascript中伪数组和真数组的一些小秘密
作者:陆荣涛 发布时间:2023-07-02 03:47:47
我有一个朋友,一直纠结一个问题:
arguments接受的实参是一个列表,得到的是一个像数组一样的东西,于是他想实现无限参数求和,在遍历数组求和时,使用了forEach遍历,却报错了,问这是为什么?
(真的不是我!)
代码如下:
执行代码结果:
首先我们要分析一下真数组和伪数组的本质区别;
arguments既然得到一个类似于数组的东西,使用forEach方法为什么会报错呢?
实际上,它并不是一个真正的数组,而是一个类数组或者叫伪数组,也就是一个类似于数组的东西,其实它也只是一个概念,咱们不能轻易被这些概念吓着。
下面我们一起看看什么是伪数组呢?
1.我们先来看看用于接受实参的方法 arguments , 执行代码如下:
function fn() {
console.log(arguments);
}
fn(1,2,3,4,5)
执行代码结果:
这里可以看到,Arguments显示的也有方括号 [1,2,3,4,5...] ,但是后面多了一些其他方法;也有length属性,但没有数组的push,pop等那些方法,像数组又不是数组。
并且从上图标注的 [[prototype]]可以看到 arguments伪数组 的原型指向的是Object对象。
2.大家也可以去打印看看其他比如getElementsByClassName 得到的
<div></dic>
<div></dic>
<div></dic>
<script>
var oDivs = document.getElementsByTagName("div");
console.log(oDiv);
</script>
执行查看结果:
这里可以看到:HTMLCollection显示的也有方括号 [1, 2, 3, 4, 5...] ,但是后面也多了一些其他方法;也有length属性,同样没有数组的push,pop等那些方法,也是像数组又不是数组。
也可以看出 [[prototype]]通过标签名获取页面元素拿到的伪数组的原型指向的是HTMLCollection对象
当然也还有一些其他的,这里就不一一列举了,简单说,伪数组具有以下特点:
拥有length属性,可以获取长度;
拥有角标索引,可以通过length属性遍历获取所有值。
但是不可以使用数组的内置方法。
3.我们再来看一下数据的打印结果:
可以看到,真数组的 proto 指向的是Array数组
那么我们一起看看为什么伪数组不能使用数组的内置方法和属性呢?
从以上所述,我们也可以看出伪数组的原型不一样,其实就是不同的对象,而数组的原型是Array,他们与真数组的本质不一样。这也是伪数组为什么不能使用数组的属性和方法的根本原因,也就是说伪数组没有办法使用数组的方法。比如forEach、pop等方法,必须把他们转化为真数组才能使用数组的各种方法。
接下来我们就说说伪数组转真数组的方法:
1 最简单的方法:
//1.先声明一个空数组
let newArr = [];
//然后遍历伪数组
for (let i = 0; i < arguments.length; i++ ) {
//将伪数组中的值通过索引逐个添加到新数组当中。
newArr[i] = arguments[i};
}
2 利用Array的原型对象的slice方法,配合call()方法修改slice中this指向
//slice原本是数组的截取子数组的方法,这里给数组的原型对象方法slice的指向强制改成arguments
let newArr = Array.prototype.slice.call(arguments);
3 利用扩展运算符(...)将伪数组转化为真数组
//ES6语法 let newArr=[];
let newArr = [...arguments];
4 利用ES6的Array.from方法
let newArr = Array.from(arguments);
改变之后,我们就可以得到一个真正的数组,后面再使用forEach获取其他方法也就不会报错啦。
总结:
伪数组的原型是Object ,真数组的原型是Array ;
伪数组其实是键值对的形式,真数组是基于索引下标实现的;
伪数组可以通过以上4种方式转化为真数组,进而使用数组的forEach等其他方法
当然了,如果只是普通遍历也可以用for循环来实现,不需要转真数组这么麻烦,在实际开发中大家也要酌情使用哦!
来源:https://juejin.cn/post/7127904903778795527


猜你喜欢
- 目录TCP简介TCP介绍TCP特点TCP与UDP的不同点udp通信模型tcp客户端tcp服务器tcp注意点TCP简介TCP介绍TCP协议,传
- python 包含子目录中的模块方法比较简单,关键是能够在sys.path里面找到通向模块文件的路径。下面将具体介绍几种常用情况: (1)主
- 对于python语言的True和False我们并不陌生了,在学习的过程中常会遇到这样的返回值,那么True真和False假的具体含义是什么?
- 1. 安装PyYAMLpip install PyYAML2. 加载yaml文件直接使用yaml.load()函数demo.yml :kin
- 复数数据结构在 cpython 当中对于复数的数据结构实现如下所示:typedef struct { double
- 方法一:<script language="JavaScript"> <!--
- 简介你手中的这本《JavaScript王者归来》不仅是一本传播知识的书,更是一本求道的书。本书分为五个部分循序渐进地与读者讨论了JavaSc
- 本文实例讲述了原生JS实现的简单轮播图功能。分享给大家供大家参考,具体如下:经过几天的努力,终于攻克了这一难题,于是迫不及待的想要分享给大家
- 1、类变量、实例变量概念类变量:类变量就是定义在类中,但是在函数体之外的变量。通常不使用self.变量名赋值的变量。类变量通常不作为类的实例
- 目录:分析和设计组件编码实现和算法用 Ant 构建组件测试 JavaScript 组件话说上期我们讨论了队列管理组件的设计,并且给它取了个响
- (ob1 is ob2) 等价于 (id(ob1) == id(ob2))首先id函数可以获得对象的内存地址,如果两个对象的内存地址是一样的
- 一、概念1、模块化代码可以使代码易于维护和调试,并且提高代码的重用性;2、函数可以用来减少冗余的代码并提高代码的可重用性。函数也可以用来模块
- 本周的豆知识分享就来深入研究一下window.event对象。请先看看下边的代码片断。 <button id=”btn”&g
- 老声长谈,着是困惑很多人的问题,如果处理不好,都是乱码,说这些话并不是我对编码很精通,只是在这方面是得留神,自己总结了一点小经验(容易出现乱
- 1、在file->settings->file and code templates->python script即可自定
- 这篇博客将介绍Canny边缘检测的概念,并利用cv2.Canny()实现边缘检测;Canny边缘检测是一种流行的边缘检测算法。它是由约翰F开
- scrollWidth 是对象的实际内容的宽,不包边线宽度,会随对象中内容的多少改变(内容多了可能会改变对象的实际宽度)。 cl
- 今天介绍Python当中十大可视化工具,每一个都独具特色,惊艳一方。MatplotlibMatplotlib 是 Python 的一个绘图库
- 在这系列视觉设计的文章间隙插一篇字体单位的文章。前文说了,字体单位应该用em而不用px,原因简单来说就是支持IE6下的字体缩放,在页面中按c
- Ubuntu16.04自带python2.7与python3.5,某个项目编译却要求python版本大于等于3.7,遂考虑在原系统基础上再安