js 如何使用fill填充数组的某部分内容

js 如何使用fill填充数组的某部分内容
最新回答
萌音草莓

2021-04-18 18:46:22

在 JavaScript 中,使用 fill 方法可以高效地填充数组的某部分内容,但需注意其直接修改原数组的特性及对象引用的潜在问题。 以下是具体用法和注意事项:

1. 基本语法

array.fill(value, start, end)

  • value:填充的值(可以是原始值或对象)。
  • start(可选):起始索引(包含),默认为 0。
  • end(可选):结束索引(不包含),默认为 array.length。

示例

let arr = [1, 2, 3, 4, 5];arr.fill(0, 2, 4); // 从索引2到4(不包含4)填充0console.log(arr); // 输出: [1, 2, 0, 0, 5]2. 填充整个数组

若省略 start 和 end,整个数组会被填充为指定值。

let arr2 = [1, 2, 3, 4, 5];arr2.fill(9); // 全部填充为9console.log(arr2); // 输出: [9, 9, 9, 9, 9]3. 填充对象时的引用问题

fill 填充对象时,所有元素指向同一对象引用,修改其中一个会影响全部。

let obj = { a: 1 };let arr3 = new Array(3).fill(obj);console.log(arr3); // 输出: [{a: 1}, {a: 1}, {a: 1}]arr3[0].a = 2; // 修改第一个元素console.log(arr3); // 输出: [{a: 2}, {a: 2}, {a: 2}](全部被修改)

解决方案:使用 map 或循环创建独立对象。

let arr4 = new Array(3).fill().map(() => ({ a: 1 }));arr4[0].a = 2;console.log(arr4); // 输出: [{a: 2}, {a: 1}, {a: 1}](仅第一个被修改)4. 避免修改原数组

fill 会直接修改原数组,若需保留原数组,可先通过 slice() 创建副本。

let arr5 = [1, 2, 3, 4, 5];let newArr = arr5.slice().fill(0, 2, 4);console.log(arr5); // 输出: [1, 2, 3, 4, 5](原数组未变)console.log(newArr); // 输出: [1, 2, 0, 0, 5](新数组被修改)5. 初始化动态长度数组

fill 可快速初始化长度为 n 的数组,填充默认值(如 null)。

let len = 10;let arr6 = new Array(len).fill(null);console.log(arr6); // 输出: [null, null, ..., null](长度为10)6. 配合 Array.from 生成特殊数组

fill 可与 Array.from 结合,生成特定规则的数组。

// 生成 [0, 0, 0, 0, 0]let arr7 = Array.from({ length: 5 }).fill(0);console.log(arr7);// 生成 [1, 2, 3, 4, 5](通过映射函数)let arr8 = Array.from({ length: 5 }, (_, i) => i + 1);console.log(arr8);7. 处理稀疏数组

fill 会填充稀疏数组中的所有空槽(empty items)。

let arr9 = new Array(5); // 稀疏数组: [ <5 empty items> ]arr9.fill(0);console.log(arr9); // 输出: [0, 0, 0, 0, 0]8. 兼容性与 Polyfill

fill 是 ES6 特性,老版本浏览器需引入 Polyfill。Polyfill 示例

if (!Array.prototype.fill) { Array.prototype.fill = function(value, start, end) { let O = Object(this); let len = O.length >>> 0; start = Math.max(start < 0 ? len + start : start, 0); end = Math.min(end === undefined ? len : (end < 0 ? len + end : end), len); for (let k = start; k < end; k++) { O[k] = value; } return O; };}9. 与 map 的区别
  • fill 直接修改原数组,map 返回新数组。
  • 链式调用时需注意顺序:let arr10 = [1, 2, 3];arr10.fill(0).map(x => x + 1); // 无效!arr10 已被修改为 [0, 0, 0]console.log(arr10); // 输出: [0, 0, 0]// 正确做法:先 map 再赋值或使用 Array.fromlet arr11 = [1, 2, 3].map(x => x + 1);console.log(arr11); // 输出: [2, 3, 4]
10. 何时使用 fill vs 循环
  • 使用 fill:批量填充固定值或简单范围。
  • 使用循环:需根据索引或条件动态计算值时。

总结:fill 是高效填充数组的工具,但需注意对象引用、原数组修改及兼容性问题。合理结合 slice、map 或 Array.from 可避免潜在陷阱。