JS 中的类数组对象如何转换为数组?

大家好,我是前端西瓜哥,今天说一下 JS 的类数组对象是什么,以及如何将类数组对象转为数组。

类数组对象是什么?

类数组对象,就是含有 length 属性的对象,但这个对象不是数组。

通常来说还会有 0 ~ length-1 的属性,结构表现上非常像一个数组。

const arrlike = {1:'a', 4: 'd', length: 9};
Array.isArray(arrlike) // false

从底层上来看,这个对象的原型链上没有 Array.prototype,所以我们不能用 Array.prototype 上的 forEach、map 等数组特有的方法。

关于原型链,可以看我的这篇文章:《如何用原型链的方式实现一个 JS 继承?》

如果强行给一个类数组对象使用 forEach 方法,会得到一个类型错误。

function f(a, b) {arguments.forEach(item => console.log(item));
}
// Uncaught TypeError: arguments.forEach is not a function

除了手动创造的类数组对象,还有以下常见的类数组对象:

  • 普通数组中的 argument 对象。需要注意的是,箭头函数中不存在这个对象。

  • 一些获取 Dom 集合的方法,如 document.querySelectorAll()、 document.getElementsByClassName、document.getElementsByTagName() 也会返回类数组对象

下面看看我们有哪些将类数组转换为数组的方法。

Array.prototyle.slice.call()

我们可以用 Array.prototyle.slice 内置方法。

Array.prototype.slice.call(obj);
[].slice.call(obj);

[] 空数组效果同 Array.prototype,因为空数组本身没有 slice 方法,会走原型链拿到 Array.prototype 的方法。空数组写法除了短一点没有任何优点。

然后 call 来自 Function.prototype,可以使用一个指定的 this 值来调用一个函数,这里是 Array.prototype.slice。我们不给 slice 方法传开始和结束位置参数,这样就会默认取整个范围。

slice 的迭代时会跳过不存在的索引属性,所以你会看到 empty 的特殊值,和 undefined 还有点不同,你可以认为表示未被初始化。forEach、map 这些内置方法是会跳过它们不执行传入的回调函数的。

一个例子:

const arrlike = {1:'a', 4: 'd', length: 9};
const arr = Array.prototype.slice.call(arrlike);
console.log(arr);

图片

什么原理?

因为 slice 用于拷贝返回一个新的子数组,且只需要被操作的目标有 length 属性就行了。

下面是 Array.prototype.slice 的核心实现,默认 start 和 end 都在 length 范围内。

Array.prototype.mySlice = function(start, end) {if (start == undefined) start = 0;if (end == undefined) end = this.length;const cloned = new Array(end - start);for (let i = 0; i < cloned.length; i++) {// 为了确保不存在的索引保持为 empty 值if (i in this) {cloned[i] = this[start + i];}}return cloned;
}

你会发现,类数组对象替换掉这里的 this 后,能拷贝出一个真正数组。

Array.from()

ES6 新出的方法,可以将类数组对象或者是可迭代对象转换为数组。

const arrlike = {1:'a', 4: 'd', length: 9};
arr = Array.from(arrlike);
console.log(arr);

图片

和 Array.prototyle.slice.call() 有点不同,不存在的索引的值被设置了 undefined。

如果一个对象,既是类数组对象,又是可迭代对象,Array.from() 方法会使用该对象的迭代器方法。

一般来说,调用 JS 的内置方法返回类数组对象同时是可迭代对象,我们通常喜欢用扩展运算符(...),更优雅。

const elCollection = document.getElementsByTagName('div');
const elArray = [...elCollection];

结尾

一般来说,我们在开发中遇到的类数组对象都是 JS 内置方法返回的,同时也是可迭代对象,我们一般都是用 [...arrlik] 扩展运算符,咻咻咻搞定。

如果类数组对象不是可迭代对象,可以使用 Array.prototyle.slice.call()Array.from()

前者会对不存在的索引维持为 empty,后者则是 undefined。我们可以认为基本差别不大,建议用 Array.from(),语义化更好些。

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

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

相关文章

js中对象转数组

今天睡前看到小组群里贴了这么一张图&#xff0c;印象中曾经面试的时候好像也是遇到过&#xff0c;对于大佬们来说这肯定是很基础的一道题&#xff0c;在此分享给正在学习前端和正在面试的小伙伴们。 这里我用fo……in……实现了两种取值方式的改变 let obj {json:0,production…

(十六)创建Lua脚本模板

Unity里能创建 c#脚本模板&#xff0c;但是如果我想创建Lua脚本模板怎么办呢&#xff1f;拓展一下编辑器吧。 设置一下Lua脚本的模板地址 &#xff1a; Assets/Editor/Lua/Template/lua.lua using UnityEngine; using UnityEditor; using System; using System.IO; using Sys…

Unity(二十):创建自定义脚本模板

编辑器内部自定义脚本存储位置展示 创建自己的自定义脚本 using System.Collections.Generic; using System.IO; using System.Linq; using System.Text.RegularExpressions; using UnityEditor; using UnityEditor.ProjectWindowCallback; using UnityEngine;internal class C…

修改Visual Studio中C#中的默认脚本模板方法

目录 一、修改后的效果 二、修改Visual Studio中C#的默认脚本步骤 三、验证修改模板是否成功 一、修改后的效果 二、修改Visual Studio中C#的默认脚本步骤 ①如果按照Visual Studio的默认安装路径安装该IDE,则路径为&#xff1a; C:\Program Files (x86)\Microsoft Visual …

Unity 添加,修改默认创建脚本模板

Unity 默认创建的脚本可以添加也可以修改&#xff0c;不需要修改Editor。 一、找到模板目录 \Editor\Data\Resources\ScriptTemplates 二、如果要修改模板&#xff0c;直接打开修改就可以了&#xff0c;每个模板都是可以修改的。 修改默认unity创建的脚本&#xff1a; 三、如…

Unity编辑器VS的脚本模板(Script Templates)设置

最近在用Unity做小游戏玩儿时&#xff0c;经常需要用到添加一些整体的说明或者相关系列脚本开发的功能&#xff0c;每一次都需要去手动的敲一下题头说明&#xff0c;虽然也只是从一个脚本copy题头过来修改&#xff0c;但是也是挺麻烦的&#xff0c;做的只是无用功重复&#xff…

unity修改脚本模板

文章目录 前言 前言 在unity有时候创建脚本的时候&#xff0c;会频繁加一些命名空间或者要继承基类并且重写方法&#xff0c;在这里记录一下&#xff0c;修改一下创建脚本时默认模板。 打开安装的unity&#xff0c; 将 81-C# Script-NewBehaviourScript.cs 移动到桌面 使用VS打…

Unity 自定义脚本模板

找到模板 C:\Program Files\Unity\Editor\Data\Resources\ScriptTemplates修改模板 将自己想要自定义模板的原版复制一个副本&#xff0c;并自定义名称 80&#xff1a;序号&#xff1b;Tmz Script&#xff1a;一级列表中的名称&#xff1b;NewTmzScript&#xff1a;新建出来…

pygame安装成功了但却无法导入求大神解

setting里面也设置成功使用了 就是无法导入 有懂得大神指导一下吗 2.8 后面发现是版本不兼容导致的

Pygame下载和安装

Pygame 的下载非常简单&#xff0c;可分为两种方式&#xff1a;一是通过 Python 的包管理器 pip 来安装&#xff1b;二是下载二进制安装包进行安装。其中使用 pip 包管理器安装是最简单、最轻量级的方法&#xff0c;下面以 Windows 系统为例对上述两种方式进行讲解。 图1&#…

pip install pygame安装报错解决方案

针对pip install pygame安装报错的两种不同的解决方法&#xff1a; 一&#xff1a;若python中已经安装好了pip&#xff0c;但pip install pygame却报错的话&#xff0c;可以尝试以下步骤&#xff1a; &#xff08;1&#xff09;开始&#xff0c;输入cmd &#xff08;2&#…

Pygame安装心得

Pygame安装 想必很多人都是从《Python编程&#xff1a;从入门到实践》来的&#xff0c;第一次安装Pygame&#xff0c;我也一样。现在我来谈谈我的安装心得。我的系统是win10。 打开CMD 键盘winR打开运行界面&#xff0c;输入cmd&#xff0c;回车。 &#xff08;这个黑东西…

pygame的安装

默认python和pip已经安装好了 1、去官网下载pygame 我使用的是py3.8&#xff0c;所以选择cp38。里面包括ios、linux和windows&#xff0c;注意选择64/32位。 2、将pygame复制到项目所在的文件夹中&#xff0c;如图&#xff1a; 3、单击选中include文件夹&#xff0c;按住shi…

python安装pygame教程_python-pygame安装教程

安装好python后&#xff0c;配置环境变量。 安装pygame需要先配置两个环境变量。 第一个是python的。先打开计算机&#xff0c;然后点击‘系统属性’然后点击‘高级系统设置’然后点击‘环境变量’在系统变量中找到path选择并编辑在末尾添加“;”号来作为与前面的间隔。我将p…

pygame 安装方法

本人python初学者&#xff0c;在各种找教程和尝试之后整理pygame 安装方法 说明&#xff1a; 使用系统&#xff1a;Windows 10 64位 python 版本&#xff1a;python 3.8 python安装位置&#xff1a;G:\Python38 以上信息请根据你所使用的电脑有所区别 查询升级pip 版本 pip l…

Pygame 安装教程

实验周用 Python 写个小游戏&#xff0c;需要用到 Pygame &#xff0c;记录一下安装过程。 一、下载文件 先去官网下载文件。我选的是 Pygame1.9 版本&#xff0c;因为去图书馆借了本书&#xff0c;是按照 Pygame1.9 版本进行讲解的&#xff0c;如果用 Pygame2.X &#xff0c;…

Pygame安装方法(Windows10, Python-3.7.2)

第一部分: 安装Pygame Pygame是一个开源游戏框架, 一组有趣强大的库, 但是, 很多人看到代码后复制下来却看到了报错 ModuleNotFoundError: No module named "pygame". 这是一个常见的问题, 表明你没有安装Pygame. 安装教程: 首先按住Win r键, 调出运行. 输入 c…

python之pygame安装教程_Pygame安装教程

1、python --version 查看安装的Python版本&#xff0c; pip --version 查看安装的pip版本&#xff0c; 升级pip命令&#xff1a; python -m pip install --upgrade pip 如果已经下载了安装文件就使用&#xff1a;pip install 文件名 如果没有下载就使用&#xff1a;python -…

python安装pygame教程_pygame 安装教程

步骤&#xff1a; 1.去官网下载PyGame 注意&#xff1a;要下载对应版本的包 其中&#xff0c;如果python为以下版本&#xff1a; &#xff08;cp36就是python3.6的意思&#xff09; 2. .exe文件直接安装 .whl文件启动doc命令安装&#xff1a; 在文件所在位置打开doc界面…