从非数组对象转数组方法小结

Array.prototype.slice.call(obj)

该方法可以将类数组对象转换为数组,所谓类数组对象,就是含 length 和索引属性的对象

返回的数组长度取决于对象 length 属性的值,且非索引属性的值,或索引大于 length 的值都不会被返回到数组中

实锤如下

let obj = {
    '0': 3,
    '1': 13,
    '2': 23,
    '3': 33,
    'length': 3,
    'name': 330
}

let arr = Array.prototype.slice.call(obj)
// [3, 13, 23]

简洁写法 [].slice.call(obj)

Array.from(obj)

该方法可以将类数组对象和可迭代对象转换为数组

类数组对象上文已提及,何为可迭代对象?

  • Array、Set、Map 和字符串都是可迭代对象(WeakMap/WeakSet 并不是可迭代对象)
  • 字符串变成了可迭代对象,解决了编码的问题
  • 这些对象都有默认的迭代器,即具有 Symbol.iterator 属性
  • 可以用 for of 循环
  • 所有通过生成器创建的迭代器都是可迭代对象
  • document.getElementsByTagName("div") 返回的是可迭代对象但不是一个数组

    • Array.isArray(document.getElementsByTagName('div')) 返回 false

通过生成器创建可迭代对象

let obj = {
    '0': 3,
    '1': 13,
    '2': 23,
    '3': 33
}

function *createIterator(obj){
    for(let value in obj){
        yield obj[value]
    }
}

let iterator = createIterator(obj)
let arr = Array.from(iterator)
// [3, 13, 23, 33]

改造对象本身,使其成为可迭代对象

默认情况下,开发者定义的对象都是不可迭代对象,但如果给 Symbol.iterator 属性添加一个生成器,则可以将其变为可迭代对象

let obj = {
    '0': 3,
    '1': 13,
    '2': 23,
    '3': 33
}

obj[Symbol.iterator] = function* () {
    for(let value in this){
        yield this[value]
    }
}

let arr = Array.from(obj)
// [3, 13, 23, 33]

判断对象是否为可迭代对象的方法

typeof obj[Symbol.iterator] === 'function'

一点延伸 for of 与 forEach 与 for in

for of 用于循环可迭代对象,包括有 Array, Set, Map, 字符串

而 Array, Set, Map 都有 forEach 方法

另外,NodeList 不是 Array, Set, Map,但是一个可迭代对象,可以用 for of 遍历

此外,用 for of 循环对象时可以通过 break 提前终止,而 forEach 无法提前跳出循环

for in 遍历对象的可枚举属性,包括其原型链上的属性,且不保证顺序

若要遍历对象自身的可枚举属性,使用 hasOwnProperty() 方法来确定属性是否时对象自身属性

Object.getOwnPropertyNames(obj), 返回对象自身可枚举或不可枚举属性

反正已经扯远了,那就再扯远一点, Object.assign() 方法将所有可枚举属性的值从一个或多个源对象复制到目标对象

[…obj]

展开运算符可以将可迭代对象转换为数组

例如,[...'obj'] 返回 ["o", "b", "j"]

字符串去重

[...new Set('objobj')]

Object.values(obj)

默认情况下,开发者定义的对象都是不可迭代对象,但提供了返回迭代器的方法

  • entries()
  • values()
  • keys()

通过使用这些方法,可以返回相关的数组

与类数组对象需要对象有 length 值不同,Object.values(obj) 返回对象自身可枚举属性值的集合

let obj = {
    '0': 3,
    '1': 13,
    '2': 23,
    '3': 33
}

let arr = Object.values(obj) // [3, 13, 23, 33]

字符串与数组的关系

在很大程度上,可以将字符串看成字符串数组,

都有 length 属性

都有 concat() / indexOf() / includes() / slice() 方法

不过值得注意的是, string 上没有方法可以原地修改它自身的内容,都是返回新的 string

string 还有个 repeat() 方法,创建指定数量的字符串副本


优雅地使用JavaScript解决问题

425 声望
31 粉丝
0 条评论
推荐阅读
前端背景知识查漏补缺
ECMAScript 与 JavaScript ECMAScript 是一套脚本语言的规范,内部编号 ECMA-262 该规范由 Ecma(European Computer Manufacturers Association) 制定 规范保证开发者按照规范编写的代码能在大部分浏览器中正常工...

nbb32103阅读 2.9k

安全地在前后端之间传输数据 - 「3」真的安全吗?
在「2」注册和登录示例中,我们通过非对称加密算法实现了浏览器和 Web 服务器之间的安全传输。看起来一切都很美好,但是危险就在哪里,有些人发现了,有些人嗅到了,更多人却浑然不知。就像是给门上了把好锁,还...

边城31阅读 7.2k评论 5

封面图
涨姿势了,有意思的气泡 Loading 效果
今日,群友提问,如何实现这么一个 Loading 效果:这个确实有点意思,但是这是 CSS 能够完成的?没错,这个效果中的核心气泡效果,其实借助 CSS 中的滤镜,能够比较轻松的实现,就是所需的元素可能多点。参考我们...

chokcoco20阅读 2.1k评论 2

在前端使用 JS 进行分类汇总
最近遇到一些同学在问 JS 中进行数据统计的问题。虽然数据统计一般会在数据库中进行,但是后端遇到需要使用程序来进行统计的情况也非常多。.NET 就为了对内存数据和数据库数据进行统一地数据处理,发明了 LINQ (L...

边城17阅读 1.9k

封面图
【已结束】SegmentFault 思否写作挑战赛!
SegmentFault 思否写作挑战赛 是思否社区新上线的系列社区活动在 2 月 8 日 正式面向社区所有用户开启;挑战赛中包含多个可供作者选择的热门技术方向,根据挑战难度分为多个等级,快来参与挑战,向更好的自己前进!

SegmentFault思否20阅读 5.6k评论 10

封面图
过滤/筛选树节点
又是树,是我跟树杠上了吗?—— 不,是树的问题太多了!🔗 相关文章推荐:使用递归遍历并转换树形数据(以 TypeScript 为例)从列表生成树 (JavaScript/TypeScript) 过滤和筛选是一个意思,都是 filter。对于列表来...

边城18阅读 7.7k评论 3

封面图
Vue2 导出excel
2020-07-15更新 excel导出安装 {代码...} src文件夹下新建一个libs文件夹,新建一个excel.js {代码...} vue页面中使用 {代码...} ===========================以下为早期的文章今天在开发的过程中需要做一个Vue的...

原谅我一生不羁放歌搞文艺14阅读 19.9k评论 9

优雅地使用JavaScript解决问题

425 声望
31 粉丝
宣传栏