伪数组
JavaScript 语言中伪数组具备两个特征:
- 属性名必须是数字的字符串
- 具有
length属性
伪数组不具备数组独有的
push、pop等方法,但是我们可以通过下标args[index]这种方式获取指定索引位置的值,虽然很简单,这也是将伪数组转化为真正数组的机理。
如何将伪数组转成真数组
- 先来了解一下
slice方法得内部实现
Array.prototype.slice = (start, end) => {
let O = ToObject(this)
let A = new Array()
let lenVal = O.length
let len = ToUnit32(lenVal)
let relativeStart = ToInteger(start)
let k, final, relativeEnd
if (relativeStart < 0) {
k = max(len + relativeStart, 0)
} else {
k = min(relativeStart, len)
}
if (end === undefined) {
relativeEnd = len
} else {
relativeEnd = ToInteger(end)
}
if (relativeEnd < 0) {
final = max(len + relativeEnd, 0)
} else {
final = min(relativeEnd, len)
}
let n = 0
while (k < final) {
let Pk = ToString(k)
let kPresent = O.hasOwnProperty(Pk)
if (kPresent) {
let kValue = O[Pk]
Object.defineProperty(A, ToString(n), {
value: kValue,
writable: true,
enumerable: true,
configurable: true
})
}
k++
n++
}
return A
}
slice 方法不要求 this 必须是数组,因此类数组对象也可以调用该方法,在本例中入参 start 和 end 均为undefined,实际上是根据 类数组对象 的 length 属性,从 0 到 length-1 去把类数组对象对应的值取出来,放到前面声明的数组 A里,最终再 return A
也可以简化一下 slice 的内部实现,例如
Array.prototype.slice = function(start, end) {
var result = new Array()
start = start || 0
end = end || this.length
for (var i = start; i < end; i++) {
result.push(this[i])
}
return result
}
- 方法一: 使用
slice方法,配合call或者apply
const lis = document.getElementsByTagName('li')
[].slice.call(lis)
[].slice.apply(lis)
Array.prototype.slice.call(lis)
Array.prototype.slice.apply(lis)
- 方法二:使用
slice方法,配合bind
const lis = document.getElementsByTagName('li')
const switchArrayFunc = Function.prototype.call.bind(Array.prototype.slice)
switchArrayFunc(lis)
方法二和方法一的原理都一样,都是伪数组去调用
slice
- 方法三:...解构赋值
const lis = document.getElementsByTagName('li')
[...lis]
- 方法四:
Array.form()
const lis = document.getElementsByTagName('li')
Array.from(lis)
- 方法五:万变不离其中
for循环
const lis = document.getElementsByTagName('li')
const array = []
for(let i = 0; i < lis.length; i++) {
array[i] = lis[i]
}