深入理解JS reduce方法及其在Webpack多入口配置中的应用

作者:望舒

时间:2026-10-21

浏览:484

本文详细解析JavaScript中reduce方法的累加与数组拼接原理,并通过具体代码示例展示其两种基础应用场景。在此基础上,深入探讨如何利用reduce方法灵活处理Webpack中多目录下的多文件入口配置,解决页面与组件分散在不同目录时的打包难题,提供简洁高效的配置方案。

文章目录

reduce 方法基础介绍

1. 解析 reduce 函数

1.1 基础示例

reduce 函数的核心目的在于简化累加操作:


var arr = [0, 1, 2, 3];

// reduce 实现累加
var total = arr.reduce(function (pre, cur){
 return pre + cur;
}, 0);

console.log(total);  // 6

在此代码中,reduce 接收两个参数:首个为执行计算的回调函数,次个为累加器的初始值:0

设定初始值为 0 后,reduce 从数组索引 0 开始执行累加,具体步骤如下:


total = 0;    // => 0
total = 0 + 0;  // => 0
total = 0 + 1;  // => 1
total = 1 + 2;  // => 3
total = 3 + 3;  // => 6

若未指定初始值 0,reduce 将数组首项作为初始值,并从索引 1 开始累加,过程如下:


total = 0;    // => 0
total = 0 + 1;  // => 1
total = 1 + 2;  // => 3
total = 3 + 3;  // => 6

由此可见,reduce 依据初始值 0 持续累加,实现了最基础的数组求和功能。

reduce 函数的两种简单运用场景

1.2 两种典型应用场景

首个示例,利用 reduce 函数合并二维数组:


var arr = [ [0], [1, 2], [3, 4, 5] ];

// reduce 实现数组拼接
var result = arr.reduce(function (pre, cur){
 return pre.concat(cur);
}, []);

console.log(result);  // [0, 1, 2, 3, 4, 5]

第二个示例,利用 reduce 函数生成 JSON 数组:


// 此例演示:将所有员工的姓名进行拆分
var staff = ['Bob Dell', 'Johon Jobs', 'Maria July'];

// reduce 构造 JSON 数组
var result = staff.reduce(function (arr, full_name){
 arr.push({
  first_name: full_name.split(' ')[0],
  last_name: full_name.split(' ')[1]
 });

 return arr;
}, []);

console.log(JSON.stringify(result));
// [{"first_name":"Bob","last_name":"Dell"},{"first_name":"Johon","last_name":"Jobs"},{"first_name":"Maria","last_name":"July"}]

巧妙运用 reduce 函数,可有效减少中间变量及代码量。

利用 reduce 实现 webpack 多文件入口配置

2. 应用于 webpack 多入口配置

webpack 配置中的 entry 参数用于定义入口文件路径,通常针对单一目录文件打包,只需遍历该目录并构造如下对象传入 entry 即可:


// 注:index.js 为每个页面的入口文件,所有页面均在 ./fe/pages/ 目录下
var entry = {
 index: './fe/pages/home/index.js',
 list: './fe/pages/list/index.js'
};

一般情况下,我们利用 reduce 方法遍历同一目录下的多个入口:


var fs = require('fs');
var path = require('path');
...

// 定义入口路径
var entryPath = './fe/pages';

// 遍历路径下多文件入口
var entris = fs.readdirSync(entryPath).reduce(function (o, filename) {
 !/\./.test(filename) &&
 (o[filename] = './' + path.join(entryPath, filename, 'index.js'));
 return o;
}, {});

// entry = {
//  index: './fe/pages/home/index.js',
//  list: './fe/pages/list/index.js'
// }

针对多页面应用开发场景,可能需要构造如下对象:


// 多个入口,页面、公共组件并不一定在同一个目录下
var entry = {
 index: './fe/pages/home/index.js',
 list: './fe/pages/list/index.js',
 header: './fe/components/header/index.js',
 footer: './fe/components/footer/index.js'
};

观察可知,需打包的页面及公共组件未必位于同一目录,此时需对原方法扩展,参考代码:


var fs = require('fs');
var path = require('path');
...

// 定义入口路径
var entryPath = ['./fe/pages', './fe/components'];

// 遍历路径下多文件入口
var mkEntriesMap = function (entryPath){
 if (typeof(entryPath) == 'string') {  // 若 entryPath 为字符串,则直接遍历此目录
  var path_map = fs.readdirSync(entryPath).map(function (filename){
   return filename + '::./' + path.join(entryPath, filename, 'index.js');
  });
 } else if (typeof(entryPath) == 'object') {  // 若 entryPath 为数组,则进行两级遍历
  var path_map = entryPath.map(function (entry){
   return fs.readdirSync(entry).map(function (filename){
    return filename + '::./' + path.join(entry, filename, 'index.js');
   });
  }).reduce(function (preArr, curArr){
   return preArr.concat(curArr);
  }, []);
 } else {
  throw 'Type of config.entryPath is not valid.';
  return;
 }

 return path_map.reduce(function (o, file_map){
  var file_name = file_map.split('::')[0];
  var file_path = file_map.split('::')[1];

  if (!/\./.test(file_name)) {
   o[file_name] = file_path;
  }

  return o;
 }, {});
};

// 构造对象
var entris = mkEntriesMap(entryPath);

// entry = {
//  index: './fe/pages/home/index.js',
//  list: './fe/pages/list/index.js',
//  header: './fe/components/header/index.js',
//  footer: './fe/components/footer/index.js'
// }

此举优势在于仅需配置初始 entryPath,同时兼容单路径或多路径文件打包:


// entryPath 可以为一个字符串
var entryPath = './fe/pages';

// entryPath 也可以设为一个数组
var entryPath = ['./fe/pages', './fe/components'];

本文内容至此结束,期望对各位学习有所助益,也恳请多多支持本站。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章