js模块化使用与进阶

模块化概念

模块化是指解决一个复杂问题时,自顶向下逐层把系统划分成若干模块的过程,模块有多种属性,分别反映其内部特性。即:模块化是一种处理复杂系统分解为更好的可管理模块的方式,模块化用来分隔,组织,打包软件。

  • 每个模块都完成一个特定的子功能,所有模块按照某种方式组装起来,成为一个总体,完成整个系统所要要求的功能。
  • 模块是可组合,分解和更换的单元。
  • 模块具有以下几种基本属性: 接口,功能,状态,逻辑
    • 功能,状态和接口反映模块的外部特性。
    • 逻辑反映模块的内部特性。

js模块化的优点

模块化,低耦合,高内聚,方便维护,防止代码冲突(命名重读)。

js模块化实现方案,以及IIFE

  • 第一种方式:基于单例形式,将单例放在全局作用域中,实现模块化。但是这种方法没有处理代码冲突,命名冲突问题,变量局部化问题
  • 第二种方式:基于闭包形式实现模块化。
  • 闭包模块化的基石 --> IIFE形式的模块化:
	const hello = ( function( name ){		
			console.log("hello world!");
			function hello(){
				console.log( "hello "+name + "!" );	
		  }
		  return hello;
	} )("meng");
	hello();

nodejs中的模块化

nodejs是基于commonjs规范的文件的读写。node天生自带模块化。
原因:

   "nodejs中的js文件,会被编译器添加一个闭包环境。所写的js文件代码,会被一个闭包包裹。"
  • nodejs中如何定义一个模块? --> nodejs中一个js文件就是一个模块。
  • nodejs中如何导出一个模块? --> 使用module.exports或者exports。
  • nodejs中如何导入一个模块? -->使用require(xxx)。其中require(xxx)是同步方式引入模块。

原理:

     ( function( exports, module, require, __filename, __dirname ){
			module.exports = exports = this = {};
			
			"用户在nodejs中的js文件编写的相关代码..."
	
			exports.xxxx = xxxx;
			return moduke.exports;
    } )

注意:

  • 导入导出都是操作的exports对象,通过require(xxxx)实际是获得的exports对象。在添加要暴露的变量或者对象或者方法时,可以使用exports.xxx = xxx形式,也可以直接使用module.exports = xxx形式。
  • 如果在多处有导入同一个模块的语句,那么只会对该模块导入一次。第一次使用require(xxx)之后,对象会被缓存到require对象中。下次导入该模块式,直接返回该对象。

CommonJS的导入导出举例:

##文件1  test1.js  用于导出多个变量,对象以及函数.  exports.xxx = xxx
	let a= 10;
	let b = 20;
	let add = (...rest )=>{
    	let total = 0;
    	rest.forEach( ( item, index, origin )=>{
       		 total += item;
   		 } );
   		 return total;
	}

	exports.a = a;
	exports.b = b;
	exports.add = add;
	
	
##文件2 ArrayUtils.js 用于导出对象,且直接就是exports. module.exports = xxx
	function ArrayUtils( ){

  		  if ( !Object.is( new.target.name, "ArrayUtils" ) ){
    		    throw  new Error("必须使用new关键字调用该函数");
  		  }

   		 //遍历
  		  ArrayUtils.prototype.forEach = function( list ){
      		  for( let i=0; i<list.length; i++ ){
        		    console.log( list[i] );
       		 }
  		  }

  		  //映射
	    ArrayUtils.prototype.map =  ( list, callback ) =>{
    		    const resultList = [];
    		    for( let i=0; i<list.length; i++ ){
        		    const item = callback( list[i], i, list );
         		   resultList.push(item);
       		 }
     		   return resultList;
  	    }
    }
	module.exports = ArrayUtils;
	
	
## 文件3 用于导入模块,并且使用
const ArrayUtils = require( './ArrayUtils.js' );
const test1 = require('./test1.js');

const list = [10, 9, 8, 7];
const arrayUtils = new ArrayUtils();

arrayUtils.forEach( list );
const reuslt = arrayUtils.map(list, (item, index, origin)=>{
    return item *10;
});
arrayUtils.forEach(reuslt)

console.log(test1.a);
console.log(test1.b);
console.log(test1.add(test1.a, test1.b,3,4))

关于nodejs的模块导包的自定义模拟实现

## mian文件,模拟入口
/**
 *  实现nodejs的自定义导入方式
 *  比如:
 *    1. require123函数进行导入
 *    2. 比如module.exports123对象进行导入
 *
 */

const fs = require("fs");
const pathUtils = require("path");
class Main {
    constructor(){
        //定义模块对象 module123
        global.module123 = {'123':'123'};
        //定义导入函数
        global.require123 = function( path ){
            if( path.search("\.|\..\/") != -1 ){
                /**
                 * 追加闭包环境
                 * 且传输相应的变量
                 *
                 * 1.module
                 * 2.exports
                 * 3.require
                 * 4.__filename
                 * 5.__dirname
                 */
                //文件所在目录, 计算出传递给其他模块使用.
                const fileName =  path
                const filePath = pathUtils.dirname(fileName);
                console.log('filepath:'+filePath)
                //先导入指定目标的文件
                const buff = fs.readFileSync(fileName);
                //在进行闭包包裹
                let content = buff.toString();
                //文件对应的路径
                content =  "((function( exports123, module123, require123, __filename123, __dirname123 ){ module123.exports123 = exports123 = {}; "+ content + ";return module123.exports123 })( module123.exports123, module123,require123, \'"+filePath+"\',\'"+fileName+"\' ))";
                return  eval(content)
            }else {
                //第三方包中的文件
            }
        }
    }
};

new Main();
//先获取要导入文件的内容
const result =   require123( pathUtils.join(__dirname, "./test/ArrayUtils.js"));
(new result()).forEach([2,3,4,5]);


 ## test/ArrayUtils文件,被Main文件通过自定义require123(xxx)导入
const pathUtils = require('path');
const test1 = require123( pathUtils.join(__dirname123,'..', '../test1.js'));
function ArrayUtils( ){
    //遍历
    ArrayUtils.prototype.forEach = function( list ){

        for( let i=0; i<list.length; i++ ){
            console.log( list[i] );
        }
    }

    //映射
    ArrayUtils.prototype.map =  ( list, callback ) =>{

        const resultList = [];
        for( let i=0; i<list.length; i++ ){
            const item = callback( list[i], i, list );
            resultList.push(item);
        }
        return resultList;
    }
}
module123.exports123 = ArrayUtils;


##  Test1文件,被ArrayUtils文件通过自定义require123(xxx)导入
  console.log(11111111);  #就简单一句。

ES6中的模块化

  • ES6模块化语法
	todo 待完成
  • ES6导入导出示例
	todo 待完成

CommonJS与ES6module的区别

	todo 待完成

Webpack模块化打包原理

	todo 待完成

Webpack模块化打包关于ES6模块语法的优化

	todo 待完成
发布了58 篇原创文章 · 获赞 34 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_36723759/article/details/103935769