两年前写的一个文章目录生成插件vue-outline,一直用着没出啥问题(本站的文章目录也是用该插件生成的)。但是最近一个网友在使用的时候却出现了异常报错,异常代码使用了一个for...in遍历数组:
for (let idx in selectors) {
let elementList = dom.querySelectorAll(selectors[idx])
elementList.forEach(element => {
if (element.__nav_except || element.offsetParent === null) return
element.__nav_level = idx
})
}
代码本意是,通过用户给定的选择器列表selectors确定哪些元素可以提取出来作为标题,比如传一个['h1', 'h3', 'div.title']。网友的使用方法完全正确,selectors传递的都是合法的选择器,但是会出现以下报错:
一个函数不是一个合法的选择器?selectors里传递的都是选择器。最后这位网友找到了原因,可能和for...in有关系,因为他在数组的原型上添加了一些便捷的方法:
而for...in会遍历出原型上的这些方法,这就导致在执行前面的代码时,把一个函数作为参数传递给了querySelectorAll,导致报错!
for...in本身是Object的遍历方法,JS中的数组也继承自Object,所以自然而然也能使用for...in遍历出属性。然而for...in有一些难以注意到的细节,稍不注意就可能被坑。
const list = [1, 2, 3]
for (let i in list) {
console.log(i, i + 1, typeof i)
}
打印:
0 01 string
1 11 string
2 21 string
可以看到typeof i的返回值是“string”,这个最坑的地方在于我们通过下标加减想取别的元素时,就会出现异常,像上述输出的i + 1一样,并不是数字相加,而是字符串拼接!
const obj = {
a: 'value_a',
b: 'value_b'
}
Object.prototype.c = 'proto_value_c'
Object.defineProperty(obj, 'd', {
get () { return 'value_d' },
enumerable: false,
})
for (let key in obj) {
console.log(key, obj[key])
}
输出:
a value_a
b value_b
c proto_value_c
可以看到,原型上的属性c也打印出来了,但是通过Object.defineProperty定义的不可枚举属性d(enumerable: false)没有被遍历到。
for...in的遍历顺序是枚举顺序,对于数组而言,规范并没有约束各浏览器的实现。因此即便在一定范围内是按顺序遍历的,也应该尽量不依赖for...in遍历的顺序。MDN文档也明确指出,不建议使用for...in遍历数组,特别是想按照索引顺序遍历的时候:
此外,因为有稀疏数组的存在,其实JS里的数组不一定是顺序结构存储的。当数组的键分布较为稀疏,为了充分节约空间,数组可能会退化为像对象一样的哈希表存储结构。
因为for...in本身是对象的遍历方法,并不适用于数组,对于数组,还是for...of、for循环、forEach等遍历比较好。
来自:https://wintc.top/article/49
循环是所有语言最基础的语法。这篇文章将介绍avascript多种循环遍历的实现介绍,包括for ..in遍历方式 ,do..while,forEach,for…of,map等等,
JavaScript数组遍历的区别,推荐在循环对象属性的时候使用for in,在遍历数组的时候的时候使用for of;for in循环出的是key,for of循环出的是value;for of是ES6新引入的特性。修复了ES5的for in的不足;
遍历二叉树,这个相对比较复杂。二叉树的便利,主要有两种,一种是广度优先遍历,一种是深度优先遍历。什么是广度优先遍历?就是根节点进入,水平一行一行的便利。
数组遍历:for --使用变量将数组长度缓存起来,在数组较长时性能优化效果明显,forEach --ES5语法;对象遍历:for...in --以任意顺序遍历一个对象自有的、继承的、可枚举的
二叉树的顺序存储结构就是用一维数组存储二叉树中的各个结点,并且结点的存储位置能体现结点之间的逻辑关系。二叉树的遍历有三种方式,如下:
相同点:都是循环遍历数组中的每一项;每次执行匿名函数都支持三个参数,参数分别为item(当前每一项),index(索引值),arr(原数组)
for in语句用于遍历数组或者对象的属性(对数组或者对象的属性进行循环操作);For循环可以将代码块执行指定的次数。forEach按照原始数组元素顺序依次处理元素.
深度优先遍历(Depth-First-Search),是搜索算法的一种,它沿着树的深度遍历树的节点,尽可能深地搜索树的分支。当节点v的所有边都已被探寻过,将回溯到发现节点v的那条边的起始节点。
项目开发中,不管是建立在哪个框架基础上,对数据的处理都是必须的,而处理数据离不开各种遍历循环。javascript中循环遍历有很多种方式,记录下几种常见的js循环遍历。
循环遍历是写程序很频繁的操作,JavaScript 提供了很多方法来实现。这篇文章将分别总结数组和对象的遍历方法,新手可以通过本文串联起学过的知识。
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!