从Array.from理解类数组

By 大Van家 on 2021-12-27
阅读时间 3 分钟
文章共 723
阅读量

同系列文章请查看:Github:pre-interview

从Array.from理解类数组

Array.from:允许在 JavaScript 集合(如: 数组、类数组对象、或者是字符串、map 、set 等可迭代对象) 上进行有用的转换。

执行下面的程序:

1
2
3
4
5
6
7
8
9
var obj = {
0: 1,
1: 2,
2: 3,
length: 3
};

var newArr = Array.from(obj);
console.log(newArr); // > (3) [1, 2, 3]

length:2

把 obj.length 属性修改为 2

1
2
3
4
5
6
7
8
9
var obj = {
0: 1,
1: 2,
2: 3,
length: 2
};

var newArr = Array.from(obj);
console.log(newArr); // > (2) [1, 2]

结论:length 决定了 Array.from 最终返回的新数组长度,需要剪裁掉。

length:4

如果 length 为 4 呢?

1
2
3
4
5
6
7
8
9
var obj = {
0: 1,
1: 2,
2: 3,
length: 4
};

var newArr = Array.from(obj);
console.log(newArr); // > (2) [1, 2, 3, undefind]

所以,补全上面的结论:

length 决定了 Array.from 最终返回的新数组长度,需要剪裁掉或补齐(undefined)。

length:0

如果去掉 length 属性呢?

1
2
3
4
5
6
7
8
9
var obj = {
0: 1,
1: 2,
2: 3,
// length: 4
};

var newArr = Array.from(obj);
console.log(newArr); // > []

可以看出,在obj转为Array时,等价于 length: 0

为什么不报错呢

类数组的理解:是由 obj 伪装成类似于数组的一种位类型,所以不是JS的固有数据类型,并没有语法要求类数组必须含有某属性或方法,在类数组中定义 length 属性只是一种规范

加深理解:push

将程序修改为如下:

1
2
3
4
5
6
7
8
9
var obj = {
0: 1,
1: 2,
2: 3,
push: [].push
};

obj.push(4);
console.log(obj);

push: [].push 继承了数组的 push 方法;

打印结果:

记住上面的结论:length 决定了 Array.from 最终返回的新数组长度

第一步,obj 中的 length 属性等价于 0

1
2
3
4
5
6
7
var obj = {
0: 1,
1: 2,
2: 3,
length: 0,
push: [].push
};

第二步:执行 push 后, length++

1
2
obj.push(4)
// length: 1

打印结果中的 0: 4 是如何出现的?

0: 1 -> 0: 4 替换后的结果。

Array.from

定义一个 obj

1
2
3
4
5
6
var obj = {
0: 1,
1: 2,
2: 3,
length: 3
};

假如想要生成以下数组:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[
{
student: No.1,
order: 0
},
{
student: No.2,
order: 1
},
{
student: No.3,
order: 2
},
]

实现

常规思路:

1
2
3
4
5
6
7
8
9
10
// 先转数组
const newArr = Array.from(obj)
const data = newArr.map((item, index) => {
return {
student: 'No.' + item,
order: index,
}
})

console.log(data)

emmm怎么做没啥大问题,但是又有点问题,问题就是暴露了你根本不熟悉 Array.from 方法,因为它还有第二个参数:

Array.from(obj, function() {})

知道这个以后,直接一步到位:

1
2
3
4
5
6
7
const newArr = Array.from(obj, function (item, index) {
return {
student: 'No.' + item,
order: index,
}
})
console.log(newArr)

进一步学习,第三个参数,在配置中设置前缀

1
2
3
4
5
6
7
8
const newArr = Array.from(obj, function (item, index) {
return {
student: this.prefix + item,
order: index,
}
}, {
prefix: 'No.', // 前缀
})

同理,数组遍历方法中,如 forEach, filter, map, reduce, reduceRight, every, some,都有回调函数和第三个参数。(reduce, reduceRight略微不同)


Tips: Please indicate the source and original author when reprinting or quoting this article.