Leo 部门最近来了位前端实习生 Robin,做为师傅,Leo 认真的为 Robin 介绍了公司业务、部门工做等状况,还有前端的新人学习地图。javascript
接下来 Robin 开始一周愉快的学习啦~html
一周后,Leo 为 Robin 同窗布置了学习做业,开发一个【人员搜索选择】的页面,效果大体以下:前端
Robin 看完这个效果图后,一脸得意的样子,这确实不难呀~java
过几天后,Robin 带着本身写的代码,给 Leo 展现了她的代码,并疑惑的问到:git
她将这个“数组”输出到控制台:github
Leo 看了看代码:数组
getUserList(){ const memberList = $('#MemberList li'); memberList.map(item => { console.log(item) }); console.log(memberList); }
Leo 又问到:app
Robin 一脸疑惑,而后 Leo 再原来代码上,加了个 Array.from
方法以下:dom
getUserList(){ const memberList = Array.from($('#MemberList li')); memberList.map(item => { console.log(item) }) console.log(memberList) }
而后从新执行代码,输出下面结果:函数
Leo 输出的结果,跟 Robin 说到:
Robin 满脸期待望着师傅,对类数组对象更加充满期待。
所谓 类数组对象,即格式与数组结构相似,拥有 length
属性,能够经过索引来访问或设置里面的元素,可是不能使用数组的方法,就能够归类为类数组对象。
举个例子🌰:
const arrLike = { 0: 'name', 1: 'age', 2: 'job', length: 3 }
arguments
对象;function f() { return arguments; } f(1,2,3) // Arguments(3) [1, 2, 3, callee: ƒ, Symbol(Symbol.iterator): ƒ]
NodeList
(好比 document.getElementsByClassName('a')
获得的结果;document.getElementsByTagName('img') // HTMLCollection(3) [img, img, img]
typedArray
(好比 Int32Array
);typedArray 即 类型化数组对象 是一种相似数组的对象,它提供了一种用于访问原始二进制数据的机制。JavaScript引擎会作一些内部优化,以便对数组的操做能够很快。然而,随着Web应用程序变得愈来愈强大,尤为一些新增长的功能例如:音频视频编辑,访问WebSockets的原始数据等,很明显有些时候若是使用JavaScript代码能够快速方便地经过类型化数组来操做原始的二进制数据将会很是有帮助。 —— 《MDN 类型化数组》
const typedArray = new Uint8Array([1, 2, 3, 4]) // Uint8Array(4) [1, 2, 3, 4]
另外使用 jQuery 获取元素,会被 jQuery 作特殊处理成为 init 类型:
$('img') // init(3) [img, img, img, prevObject: init(1), context: document, selector: "img"]
固然还有一些不常见的类数组对象,好比“Storage API 返回的结果”,这里就不一一列出。
下面经过 Robin 代码做为示例,介绍类数组对象的属性:
const memberList = $('#MemberList li');
// 读取 memberList[0]; // Node: <li>...</li> // 写入 memberList[0] = document.createElement("div") memberList[0]; // Node: <div>...</div>
memberList.length; // 10
for (let i = 0;i < memberList.length; i++){ console.log(memberList[i]); } /* Node: <li>...</li> Node: <li>...</li> ... 共10个,省略其余 */ memberList.map(item => console.log(item)); /* 0 ... 共10个,省略其余 */
但若是是 HTMLCollection
就不能使用 map
咯:
const img = document.getElementsByTagName("img"); img.map(item => console.log(item)); // Uncaught TypeError: img.map is not a function
Leo 看了看 Robin 处理这个列表的代码:
getUserList(){ const memberList = $('#MemberList li'); const result = { text: [], dom : [], }; memberList.map(item => { item = memberList[item] // 判断当前节点是否有 checked 类名 }) console.log(result) this.showToast(`选中成员:${result.text}`); }
很明显,Robin 并无对 jQuery 获取到的 memberList
作处理,直接使用,经过索引来获取对应值。
Leo 继续和 Robin 介绍到:
使用 Array.from
来将类数组对象转为数组对象,操做起来很是简单:
getUserList(){ const memberList = Array.from($('#MemberList li')); // 省略其余代码 }
其语法以下:
Array.from(arrayLike[, mapFn[, thisArg]])
参数:
arrayLike
想要转换成数组的伪数组对象或可迭代对象。mapFn
可选若是指定了该参数,新数组中的每一个元素会执行该回调函数。thisArg
可选可选参数,执行回调函数 mapFn
时 this
对象。返回值:
一个新的数组实例。
更多 Array.from
介绍能够查看文档。
slice()
方法返回一个新的数组对象,这一对象是一个由 begin
和 end
决定的原数组的浅拷贝(包括 begin
,不包括end
)。原始数组不会被改变。
实现代码:
getUserList(){ const memberList = Array.prototype.slice.call($('#MemberList li')); // 省略其余代码 }
更多 Array.prototype.slice 介绍能够查看文档。
展开语法(Spread syntax), 能够在函数调用/数组构造时, 将数组表达式或者string在语法层面展开;还能够在构造字面量对象时, 将对象表达式按key-value
的方式展开。
实现代码:
getUserList(){ const memberList = [...document.getElementsByTagName("li")]; // 省略其余代码 }
更多 ES6展开运算符 介绍能够查看文档。
getUserList(){ const memberList = Array.prototype.concat.apply([], $('#MemberList li')); // 省略其余代码 }
Leo 介绍完这些知识后,Robin 又优化了下本身的代码,涉及到类数组对象操做的核心 js 代码以下:
class SelectMember { constructor(){ this.MockUsers = window.MockUsers; this.init(); } init(){ this.initMemberList('#MemberList', this.MockUsers); this.initBindEvent(); } // ... 省略部分代码,保留核心代码 submitSelect(){ const memberList = Array.from($('#MemberList li')); const result = { text: [], dom : [], }; memberList.map(item => { const hasClass = $(item).children('.round-checkbox').children('span').hasClass(this.selectClassName); if(hasClass){ result.text.push($(item).children('.user-data').children('h4').text()); result.dom.push(item); } }) this.showToast(`选中成员:${result.text}`); } } let newMember = new SelectMember();
很明显,使用正确方式来处理类数组对象,不只能使咱们代码更加少,减小转换处理,还能提升代码质量。
整个项目的完整代码,能够在个人 github 查看:
本文咱们经过一个实际场景,详细介绍了类数组对象在实际开发中的使用,对于常见的类数组对象,咱们还介绍了处理方式,能很大程度减小咱们处理类数组对象的操做,将类数组统一转成数组,更加方便对数据的操做。但愿看完本文的你,之后再遇到类数组对象,不会再一脸懵逼咯~~~