以下内容是学习JavaScript数组的时候总结的经验以及需要注意的点。
<强>不要用for_in遍历数组强>
这是JavaScript初学者常见的误区.for_in用于遍历对象中包括原型链上的所有可枚举的(可列举的)的关键,本来不是为遍历数组而存在。
使用for_in遍历数组有三点问题:
<强> 1,遍历顺序不固定强>
JavaScript引擎不保证对象的遍历顺序。当把数组作为普通对象遍历时同样不保证遍历出的索引顺序。
<强> 2,会遍历出对象原型链上的值。强>
如果你改变了数组的原型对象(比如polyfill)而没有将其设为<代码>可列举的:虚假> 代码,for_in会把这些东西遍历出来。
<强> 3,运行效率低下。强>
尽管理论上的JavaScript使用对象的形式储存数组,JavaScript引擎还是会对数组这一非常常用的内置对象特别优化。https://jsperf.com/for-in-vs-..。
可以看到使用for_in遍历数组要比使用下标遍历数组慢50倍以上
PS:你可能是想找for_of
有人使用JSON中深拷贝对象或数组。这虽然在多数情况是个简单方便的手段,但也可能引发未知错误,因为:会使某些特定值转换为零代码> <代码>
南,定义,无穷对于JSON中不支持的这些值,会在序列化JSON时被转换为null,反序列化回来后自然也就是空
会丢失值为未定义的键值对
JSON序列化时会忽略值为未定义的关键,反序列化回来后自然也就丢失了
会将日期对象转换为字符串
JSON不支持对象类型,对于JS中日期对象的处理方式为转换为ISO8601格式的字符串。然而反序列化并不会把时间格式的字符串转化为日期对象
运行效率低下。
作为原生函数,<代码> JSON。stringify 代码>和<代码> JSON。代码解析>自身操作JSON字符串的速度是很快的。然而为了深拷贝数组把对象序列化成JSON再反序列化回来完全没有必要。
我花了一些时间写了一个简单的深拷贝数组或对象的函数,测试发现运行速度差不多是使用JSON中转的6倍左右,顺便还支持了TypedArray, RegExp的对象的复制
https://jsperf.com/deep-clone..。
不要用加勒比海盗。找到代替arr.some
<代码> Array.prototype。找到代码>是ES2015中新增的数组查找函数,与<代码> Array.prototype。一些代码>有相似之处,但不能替代后者。
<代码> Array.prototype。找到代码>返回第一个符合条件的值,直接拿这个值做<代码> 代码>如果判断是否存在,如果这个符合条件的值恰好是0怎么办?
<代码>加勒比海盗。找到代码>是找到数组中的值后对其进一步处理,一般用于对象数组的情况,<代码>加勒比海盗。一些代码>才是检查存在性;两者不可混用。
不要用加勒比海盗。地图代替arr.forEach
也是一个JavaScript初学者常常犯的错误,他们往往并没有分清<代码> Array.prototype。地图代码>和<代码> Array.prototype。forEach> 代码的实际含义。
<代码> 代码>地图中文叫做<代码>映射> 代码,它通过将某个序列依次执行某个函数导出另一个新的序列。这个函数通常是不含副作用的,更不会修改原始的数组(所谓纯函数)。
<代码> forEach> 代码就没有那么多说法,它就是简单的把数组中所有项都用某个函数处理一遍。由于<代码> forEach> 代码没有返回值(返回未定义),所以它的回调函数通常是包含副作用的,否则这个<代码> forEach> 代码写了毫无意义。
确实<代码> 代码>地图比<代码> forEach> 代码更加强大,但是<代码> 代码>地图会创建一个新的数组,占用内存。如果你不用<代码> 代码>地图的返回值,那你就应当使用forEach <代码> 代码>
ES6以前,遍历数组主要就是两种方法:手写循环用下标迭代,使用<代码> Array.prototype.forEach> 代码。前者万能,效率最高,可就是写起来比较繁琐——它不能直接获取到数组中的值。
笔者个人是喜欢后者的:可以直接获取到迭代的下标和值,而且函数式风格(注意FP注重的是不可变数据结构,forEach天生为副作用存在,所以只有FP的形而没有神)写起来爽快无比。但是!不知各位同学注意过没有:forEach一旦开始就停不下来了…
forEach接受一个回调函数,你可以提前<代码> 代码,返回相当于手写循环中的<代码> 代码>继续。但是你不能休息