基于类、对象和闭包的模块

文章介绍了如何利用闭包在JavaScript中实现模块化,通过类和私有函数实现模块功能,以及使用立即执行函数(IIFE)和Node.js的文件系统API来组织和加载模块。示例展示了如何创建统计模块和自动化模块打包的过程。
摘要由CSDN通过智能技术生成
  1. 类充当自己方法的模块
  2. 类方法相互独立是因为每个方法都被定义成独立的原型对象的属性
  3. 类成为模块是因为对象是模块
函数中声明的局部变量和嵌套函数都是函数私有的,可以使用立即调用的函数表达式实现某种模块化,实现细节和辅助函数隐藏在包装函数中,只把模块中的公共 API 作为函数的值返回
const BitSet = (function() { // 将BitSet设置为这个立即执行函数的返回值  
  // 私有实现细节在这里  
  // function isValid(set, n) { ... }  
  // function has(set, byte, bit) { ... }  
  const BITS = new Uint8Array([1, 2, 4, 8, 16, 32, 64, 128]); // 定义一个包含位权重的数组  
  const MASKS = new Uint8Array([~1, ~2, ~4, ~8, ~16, ~32, ~64, ~128]); // 定义一个包含按位取反后的位权重的数组  

  // 这个模块的公共API只包括BitSet类,我们在这里定义并返回它。这个类可以使用上面定义的私有函数和常量,  
  // 但这些私有函数和常量对类的使用者来说是隐藏的  
  return class BitSet extends AbstractWritableSet {  
      // ... 省略了实现部分 ...  
  };  
}());


// 这是一个定义统计模块的示例  
const stats = (function() {  
  // 模块私有的工具函数:求和  
  const sum = (x, y) => x + y;  

  // 模块私有的工具函数:求平方  
  const square = x => x * x;  

  // 公共函数:计算平均值  
  function mean(data) {  
      return data.reduce(sum) / data.length;  
  }  

  // 公共函数:计算标准差  
  function stddev(data) {  
      let m = mean(data); // 首先计算平均值  
      return Math.sqrt(  
          data.map(x => x - m) // 减去平均值得到偏差  
              .map(square) // 对偏差求平方  
              .reduce(sum) // 求和  
              / (data.length - 1) // 除以数据点数量减一(无偏估计)  
      );  
  }  

  // 导出公共函数作为对象的属性  
  return {  
      mean, // 导出平均值函数  
      stddev // 导出标准差函数  
  };  
})();  

// 下面是使用这个统计模块的示例  
console.log(stats.mean([1, 3, 5, 7, 9]));   // 输出: 5 // 计算数组的平均值,并输出结果  
console.log(stats.stddev([1, 3, 5, 7, 9])); // 输出: Math.sqrt(10) // 计算数组的标准差,并输出结果
10.1.1 基于闭包的模块自动化
  1. 读取指定目录中的所有文件。
  2. 将每个文件的内容包装在一个IIFE中,并创建一个变量来保存模块的导出对象。
  3. 创建一个函数来加载模块并返回它的导出对象。
  4. 假设文件中定义了函数,并创建了一个函数来调用这些函数并返回它们的返回值。这里假设函数名已经提前知道(在真实场景中,你需要解析文件内容来提取函数名)。
  5. 拼接所有文件的代码,包括加载模块和调用函数的函数。
  6. 将拼接后的内容写入一个输出文件。
//  本质是 node 脚本
const fs = require('fs');  
const path = require('path');  
  
// 读取目录中的所有文件  
function readDir(dirPath) {  
    return fs.readdirSync(dirPath).map(file => path.join(dirPath, file));  
}  
  
// 将文件内容包装在IIFE中  
function wrapInIIFE(content) {  
    return `(function() {  
        ${content}  
        return { exports: exports };  
    })();`;  
}  
  
// 解析文件并返回内容  
function parseFile(filePath) {  
    const content = fs.readFileSync(filePath, 'utf8');  
    const moduleName = path.basename(filePath, path.extname(filePath));  
    const wrappedContent = wrapInIIFE(content);  
      
    // 创建一个新的变量来保存模块的导出对象  
    const exportsVar = `exports_${moduleName}`;  
      
    // 创建一个新的函数来调用模块并返回它的导出对象  
    const loadModule = `function load_${moduleName}() {  
        return ${wrappedContent}.exports;  
    }`;  
      
    // 创建一个函数来调用模块并获取它的返回值  
    const callModuleFunction = (functionName) => `function call_${moduleName}_${functionName}() {  
        const module = load_${moduleName}();  
        if (typeof module.${functionName} === 'function') {  
            return module.${functionName}.apply(module, arguments);  
        }  
        throw new Error('Function ${functionName} does not exist in module ${moduleName}');  
    }`;  
      
    // 拼接所有代码  
    let result = loadModule + '\n';  
      
    // 假设文件中有定义函数,并且我们想要跟踪它们的返回值  
    // 这里只是一个简单的例子,你可能需要解析文件内容来提取函数名  
    const functionNames = ['function1', 'function2']; // 这里应该是解析出来的函数名列表  
    for (const functionName of functionNames) {  
        result += callModuleFunction(functionName) + '\n';  
    }  
      
    return result;  
}  
  
// 拼接所有文件内容  
function concatenateFiles(dirPath) {  
    const filePaths = readDir(dirPath);  
    let concatenatedContent = '';  
      
    for (const filePath of filePaths) {  
        concatenatedContent += parseFile(filePath) + '\n';  
    }  
      
    return concatenatedContent;  
}  
  
// 入口函数  
function buildModuleBundle(dirPath, outputFilePath) {  
    const bundleContent = concatenateFiles(dirPath);  
    fs.writeFileSync(outputFilePath, bundleContent);  
    console.log(`Bundle created at ${outputFilePath}`);  
}  
  
// 使用示例  
const dirPath = './modules'; // 你的模块文件目录  
const outputFilePath = './bundle.js'; // 输出的捆绑文件路径  
buildModuleBundle(dirPath, outputFilePath);
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值