Array.prototype.fill
使用fill
配合Array
构造函数进行指定个数和初始值的数组创建,并可以通过相关函数的连续调用,完成对数组的修改,从而抛离了for
或while
的循环使用。
/**
* 生成指定长度有统一初始值的数组
*
* @param {Number} len - 长度
* @param {*} val - 初始值
* @returns {Array[]}
*/
function createSpArray(len, val) {
return Array(len).fill(val);
}
//使用举例
createSpArray(3,{}); // 输出:(3) [{…}, {…}, {…}]
createSpArray(3,1); // 输出:(3) [1, 1, 1]
createSpArray(3,1).map((i, idx)=>idx+1); // 输出:(3) [1, 2, 3]
但是需要注意的是,在MDN中提到了,fill
方法传递的值若是引用类型的话,则所有数组元素中的元素指向同一引用,若是不够小心的话,很容易出问题。
// Objects by reference.
var arr = Array(3).fill({}) // [{}, {}, {}];
arr[0].hi = "hi"; // [{ hi: "hi" }, { hi: "hi" }, { hi: "hi" }]
Array.prototype.map
在MDN中对map
函数有这样的一段描述:
map 方法会给原数组中的每个元素都按顺序调用一次 callback 函数。callback 每次执行后的返回值(包括 undefined)组合起来形成一个新数组。 callback 函数只会在有值的索引上被调用;那些从来没被赋过值或者使用 delete 删除的索引则不会被调用。
这里需要注意的是其中提到的有值索引,如下示例:
const res = Array(3); // res = (3) [empty × 3]
const arrB = res.map(i=>3); // arrB = (3) [empty × 3]
上述示例中,使用Array(3)
创建的便是无值索引,此时map的回调函数是未被调用的。再看如下示例:
const res = Array(3).fill(undefined); // b = (3) [undefined, undefined, undefined]
const arrB = res.map(i=>3); // arrB = (3) [3, 3, 3]
通过fill
方法,为创建的数组进行元素初始化,便可以正常的使用map
函数了。那么如何将原本为有值索引的元素变为无值索引呢?那么就是通过delete
进行删除了。示例如下:
const arr = [1,2,3];
delete arr[0]; // arr = (3) [empty, 2, 3];
arr.map(i=>{
console.info(i);
});
// 输出为:
// 2
// 3
类似的forEach
,filter
等对数组遍历操作的函数也有相应的限制,因此使用时需要注意。
Tip:虽然可能用的地方不多,但是知道了,了解了,在解决问题的时候有可能会多一种思路。基础是很重要的。
附一道经典的前端面试题:
在不使用循环的条件下,如何创建一个长度为100的数组,并且数组的每一个元素是该元素的下标?
祝好~