最近看到 vue 源码的 nextTick ,发现里面清空数组的方式是把 length 置零,有点好奇具体发生了什么。于是搜索一番,也顺便记录一番。
const callbacks = []
let pending = false
function flushCallbacks () {
pending = false
const copies = callbacks.slice(0)
callbacks.length = 0 // <================
for (let i = 0; i < copies.length; i++) {
copies[i]()
}
}
首先我们看看 callbasks = []
,实际上做了哪些事情呢?
- 创建了一个新的空数组
[]
- 将其引用赋值给
callbacks
如果在赋值前,有其他变量也引用了 callbacks 引用的数组,是不会被影响的。
let callbacks = [1, 2, 3] // 这里只能用 let 或 var
let cbs = callbacks
callbacks = []
console.log(callbacks, cbs) // [] [1, 2, 3]
可是如果你是把数组的 length 置零,修改的是数组本身。
const callbacks = [1, 2, 3] // 这里可以用 const
const cbs = callbacks
callbacks.length = 0
console.log(callbacks, cbs) // [] []
MDN 对 Array.length 的描述如下:
length 是Array的实例属性。返回或设置一个数组中的元素个数。该值是一个无符号 32-bit 整数,并且总是大于数组最高项的下标
length
属性的值是一个 0 到 Math.pow(2, 32) - 1
的整数。不在这个范围里会报错 RangeError
。
可以给 length
设置一个比当前数组长度更小的值来截断数组。
const callbacks = [1, 2, 3]
callbacks.length = 2
console.log(callbacks) // [1, 2]
也可以设置一个更大的值来扩展数组,实际元素的数目将会增加,新的元素都是 undefined
。
const callbacks = [1, 2, 3]
callbacks.length = 5
console.log(callbacks) // [1, 2, 3, <2 empty items>]
当然,这么写可能会让你的同事看的一脸懵逼。为了避免修改数组变量(const
),可以用其他显式的方式来清空数组
const callbacks = [1, 2, 3]
callbacks.splice(0, callbacks.length)
console.log(callbacks) // []