前端模块化编程

前端模块化

前端技术发展可谓是日新月异,web2.0的到来,Ajax技术的广泛引用,jQuery库的层出不穷,前端代码日益膨胀,javascript的发展领域越来越广泛,就会应用使用模块化编程去规范管理。本文内容主要有理解模块化,为什么要模块化,模块化的优缺点以及模块化规范,并且介绍下开发中最流行的CommonJS, AMD, ES6、CMD规范。刚进门的小白用通俗易懂的笔调介绍这些枯燥无味的概念,忘君阅读,流连忘返!

模块化的理解

将一个复杂的程序根据规范进行封装成模块,然后通过其他地方与它有联系,向外部暴露接口(方法)进行调用,方便编程,程序化思想。

CommonJS模块化规范

  1. 概述
    Node 应用由模块组成,采用 CommonJS 模块规范。每个文件就是一个模块,有自己的作用域。在一个文件里面定义的变量、函数、类,都是私有的,对其他文件不可见。在服务器端,模块的加载是运行时同步加载的;在浏览器端,模块需要提前编译打包处理。
  2. 特点
  • 所有代码都运行在模块作用域,不会污染全局作用域。
  • 模块可以多次加载,但是只会在第一次加载时运行一次,然后运行结果就被缓存了,以后再加载,就直接读取缓存结果。要想让模块再次运行,必须清除缓存。
  • 模块加载的顺序,按照其在代码中出现的顺序。
  1. 基本语法
  • 暴露模块:module.exports = value或exports.xxx = value
  • 引入模块:require(xxx),如果是第三方模块,xxx为模块名;如果是自定义模块,xxx为模块文件路径
    此处我们有个疑问:CommonJS暴露的模块到底是什么? CommonJS规范规定,每个模块内部,module变量代表当前模块。这个变量是一个对象,它的exports属性(即module.exports)是对外的接口。加载某个模块,其实是加载该模块的module.exports属性。
// 该文件是index.js,将下面两个函数进行封装
const  max=(x,y)=>{
	let m=x;
	if(m<y){
		m=y;
	}
	return m;
}
const isLeapyear=(year)=>{
	if(year%4 === 0 && year % 100===0){
		console.log(`${year}是闰年`)
	}else{
		console.log(`${year}不是是闰年`)
	}
}

//通过将两个函数暴露出去 
module.exports={
	max,
	isLeapyear
}
// 在该文件下面引用两个封装好的函数
 const main=require('/index.js');
 
 	let m1=main.max(56,89);
 	console.log(`max=${m1}`);
let isleap=main.isLeapyear(2012);


Es6模块化规范

ES6 模块的设计思想是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。CommonJS 和 AMD 模块,都只能在运行时确定这些东西。比如,CommonJS 模块就是对象,输入时必须查找对象属性。

  1. ES6模块化语法
    export命令用于规定模块的对外接口,import命令用于输入其他模块提供的功能。
    模块默认输出, 其他模块加载该模块时,import命令可以为该匿名函数指定任意名字。

  2. ES6 模块与 CommonJS 模块的差异
    它们有两个重大差异:
    ① CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。
    ② CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。
    第二个差异是因为 CommonJS 加载的是一个对象(即module.exports属性),该对象只有在脚本运行完才会生成。而 ES6 模块不是对象,它的对外接口只是一种静态定义,在代码静态解析阶段就会生成。
    下面重点解释第一个差异,我们还是举上面那个CommonJS模块的加载机制例子:

// 该文件是index.js,将下面两个函数进行封装
const  max=(x,y)=>{
	let m=x;
	if(m<y){
		m=y;
	}
	return m;
}
const isLeapyear=(year)=>{
	if(year%4 === 0 && year % 100===0){
		console.log(`${year}是闰年`)
	}else{
		console.log(`${year}不是是闰年`)
	}
}

//通过将两个函数暴露出去,注意看这里es6的暴露方法不一样

exports {max,sLeapyear}

// 在该文件下面引用两个封装好的函数,注意引用的方法也不一样
 import {max,isLeapyear} from '/index.js'
 
 	let m1=max(56,89);  //这里将不是通过main.max来取得这个函数
 	console.log(`max=${m1}`);
let isleap=isLeapyear(2012);


总结

  • CommonJS规范主要用于服务端编程,加载模块是同步的,这并不适合在浏览器环境,因为同步意味着阻塞加载,浏览器资源是异步加载的,因此有了AMD CMD解决方案。
  • AMD规范在浏览器环境中异步加载模块,而且可以并行加载多个模块。不过,AMD规范开发成本高,代码的阅读和书写比较困难,模块定义方式的语义不顺畅。
  • CMD规范与AMD规范很相似,都用于浏览器编程,依赖就近,延迟执行,可以很容易在Node.js中运行。不过,依赖SPM 打包,模块的加载逻辑偏重
  • ES6 在语言标准的层面上,实现了模块功能,而且实现得相当简单,完全可以取代 CommonJS 和 AMD 规范,成为浏览器和服务器通用的模块解决方案。

你可能感兴趣的:(vue)