今天决定每天写一道面试题(偶尔懒了也可以不写, 不强迫自己), 对前端常见的面试题进行一些话术的总结和知识点整合吧
正好今天听同事校招面试问到一个类数组, 那么就由此开始吧
本文将从以下几个方面进行讲述
文章目录
什么是类数组
类数组, 顾名思义, 不是数组, 长的像数组;
其实类数组本质是一个对象, 只不过是具有如下两个特性的对象
- 拥有length属性 和数字索引
- 不具有普通数组的操作方法
具有length属性, 主要是为了保证类数组可以进行遍历
与数组的区别就是没有数组的方法, 比如pop,push,slice等等, 不能进行这些数组操作
为什么需要类数组 以及 常见的类数组有哪些
为什么需要类数组
因为在有些地方, 我们需要数据具有数组的形式但是又不能有数组的方法从而防止对这些数据进行改动, 因此就有了类数组
常见的类数组有哪些
arguments
函数参数
function args() {
console.log(arguments)
console.log(Object.prototype.toString.call(arguments))
console.log(arguments.length)
}
args(1, 2, 3)
[Arguments] { '0': 1, '1': 2, '2': 3 }
[object Arguments]
3
由代码可见, arguments的本质上也是一个对象, 这个对象的构造函数是Arguments
HTMLCollection
通过getElementsByTagName和getElementsByClassName选择器筛选出的DOM元素
由图可见, HTMLCollection有length属性, 也是类数组; 它的构造函数是HTMLCollection
NodeList
通过querySelectorAll筛选出的NodeList
和HTMLCollection类似
鸭式辩形
其实上面的形式都是鸭式辩形
总结起来就是
const obj = {
0:'a',
1:'b',
length:2
}
同时还可以给对象添加一些其他的函数比如
const obj = {
0:'a',
1:'b',
2:'c',
3:'d',
length:4,
push(value){
this[this.length] = value
this.length++
}
}
这样类数组就有了数组的push方法
类数组的遍历
上面提到过, 类数组其实是对象的变形, 所以类数组可以使用for in的遍历方法对对象进行遍历
但是这个方法会把类数组中的其他属性遍历出来, 比如length, push
const obj = {
0: 'a',
1: 'b',
2: 'c',
3: 'd',
length: 4,
push(value) {
this[this.length] = value
this.length++
},
}
for (let i in obj) {
console.log(i)
}
0
1
2
3
length
push
所以对于类数组, 我们通常使用for循环的方式进行遍历, 因为类数组有length属性, 遍历到此就结束了
for (let i = 0; i < obj.length; i++) {
console.log(obj[i])
}
a
b
c
d
而且由于类数组的key值一定是从0开始到某值, 这样也是使我们能取到obj[i]值的原因
for (let i = 0; i < 10; i++) {
console.log(obj[i])
}
a
b
c
d
undefined
undefined
undefined
undefined
undefined
undefined
因为其他属性的key值不是i了, 而是length, push等
类数组转为数组
如果想要类数组使用数组上的某些方法, 可以使用Array原型上的方法
Array.prototype.slice.call(obj,1)
Array.prototype.map.call(a, function(x) {
return x.toUpperCase();
})
Array.prototype.push.call(obj, 3) //返回length的值5
使用数组上的slice和map方法可以返回一个数组
let arr = Array.prototype.map.call(obj, function (x) {
return x.toUpperCase()
})
console.log(arr, Object.prototype.toString.call(arr))
let arr2 = Array.prototype.slice.call(obj)
console.log(arr2, Object.prototype.toString.call(arr2))
[ 'A', 'B', 'C', 'D' ] '[object Array]'
[ 'a', 'b', 'c', 'd' ] '[object Array]'
另外还有
Array.from(obj)
判断类数组
//判断是否是一个类数组
function isArrayLike(o) {
if (
o && //o非null, undefined
typeof o === 'object' && // o是对象
isFinite(o.length) && //o.length是有限数值
o.length >= 0 && //o.length是非负值
o.length === Math.floor(o.length) && //o.length是整数
o.length < 4294967296 //o.length< 2^32
) {
return true
} else {
return false
}
}