原文: https://zswfx.com/articles/5da713302ddd022595ff506a
咱们在使用 Array.prototype.splice
方法的时候,都会说起说它速度慢,效率低。尤为在例如 Vue
或者React
框架中也不推荐使用,缘由是为何呢?javascript
方法介绍以下:vue
方法也比较明了,就是在数组内删除或者添加元素。
以下示例:java
// 添加一个元素 const arr = [1, 2, 3] arr.splice(1, 0, 2, 3) // [1, 2, 3, 2, 3] // 删除元素 arr.splice(2, 2) // arr: [1, 2, 3]
返回值则是删除元素的数组,如果添加就是空数组.react
在 w3c 中关于 splice 是如何描述过程的呢?数组
Array.prototype.splice 位于ecmascript 规范中 15.4 数组章节下面的 15.4.4.12 点击这了便可
下面看关于 splice描述:框架
下面就用删除和添加两个例子来讲明规范的操做过程:ecmascript
在规范里面共有 17步的数据操做:性能
actualDeleteCount > 0
即为删除,而后获得A的删除数组,这里就获取到了要删除的元素,若删除元素个数为0,则跳过A为空数组,k 为0, 不然 k为删除个数,A 为删除元素集合. actualStart 为传入的数组中某个下标值, actualDeleteCount 为传入某个个数范围是 0-len 在 splice
方法中,咱们会使用状况以下:es5
删除元素在第9步处理删除元素数组,第12步处理元素前移并删除结尾的元素。添加元素在13步内处理元素后移,并在15步在对应下标下放入元素。删除元素同时删除上面每一步都会走到。spa
关于规范一些内部方法说明:
[[HasProperty]](P) 对象上的内部方法,若经过P获得对象结果为undefined则为false,不然为true。
[[GET]](P) 对象内部方法,经过属性名P获取结果。
[[Put]](P, V, Throw) 设置对象属性P的值为V,Throw若为true,遇到错误则会抛出TypeError。
[[Delete]](P, Throw) 删除对象上属性P,若Throw为true,遇到错误则抛出TypeError.
操做数组:
[0, 1, 2, 3]
这里进行 splice(1, 2, 4)
操做,从下标1位置移除2个元素,并添加一个元素
[0, 1, 2, 3]
进行 splice(1, 1, 5, 6)
操做,从下标1的位置删除一个元素,并插入 5和6
的示例。
经过上面规范分析和图示分析,其实splice之因此”慢“
, 是由于每次splice操做除了须要分配新的内存区域去存储数据外,还须要不断操做元素的下标,大量移动元素位置,若start=0,岂不是每一个元素都须要移动一次呢?这就是说效率不高缘由。
tips: splice 会修改数组自己,因此在vue和react中数组数据变化不会致使UI变化的缘由之一。
其余参考:
https://www.jianshu.com/p/483...
上面说splice 用于三种状况:
在最新的ecma中有新的方法能够替代splice用途
使用 filter
代替:
const arr = [1, 2, 3, 4] // 删除下标为2的元素 const newArray = arr.filter((_, index) => index !== 2) // [1, 2, 4]
使用 concat
或者 spread
代替配合 slice
实现任何位置插入:
const array = [1, 2, 3,] // 下标1 插入10 const newArray = array.slice(0, 1).concat(10, array.slice(1)) // [1, 10, 2, 3] // const newArray = [...array.slice(0, 1), 10, array.slice(1)]
同上
const array = [0, 1, 2, 3, 4, 5] // 下标位置2位置删除2个,并插入7,8,9 const newArray = array.slice(0, 2).concat([7, 8, 9], array.slice(4)) // [0, 1, 7, 8, 9, 4, 5]
相信本身,总会有一个办法解决问题,代码性能也会一点点提升,欢迎交流。