JS中的几种模块化规范(CommonJS、AMD、CMD、ES6 Module)

//使用

module1.foo();

module2();

module3.foo();

module3.bar();

举例2:

// file greeting.js 定义一个模块

var helloInLang = {

en: ‘Hello world!’,

es: ‘¡Hola mundo!’,

ru: ‘Привет мир!’

};

var sayHello = function (lang) {

return helloInLang[lang];

}

// 对外输出

module.exports.sayHello = sayHello;

// file hello.js 引入一个模块

var sayHello = require(‘./lib/greeting’).sayHello;

var phrase = sayHello(‘en’);

console.log(phrase);

举例3:

// a.js

module.exports = {

moduleFunc: function() {

return true;

};

}

// 或

exports.moduleFunc = function() {

return true;

};

// 在 b.js 中引用

var moduleA = require(‘a.js’);

// 或

var moduleFunc = require(‘a.js’).moduleFunc;

console.log(moduleA.moduleFunc());

console.log(moduleFunc())

2.AMD规范

2.1说明
  • CommonJS规范出现后,在Node开发中产生了非常好的效果,开发者希望借鉴这个经验来解决浏览器JS的模块化

  • 但是大部分人认为浏览器和服务器的环境差别太大,毕竟浏览器JS时通过网络动态以此加载的,而服务器的JS是保存在本地磁盘中。因此浏览器需要实现异步加载,模块在定义的时候就必须先知名它所需要依赖的模块,然后把本模块的代码写在回调函数中执行,最终衍生出了AMD规范

  • AMD的主要思想时异步模块,主逻辑在函数回调中执行

2.2 标准内容

在这里插入图片描述

1.定义没有依赖的模块

module1.js

define(function(require,exports.module){

return 模块

}

2.定义具有依赖的模块

module2.js

define([‘module1’,‘module2’],function(m1,m2){

return 模块

}

3.引入模块

main.js

require([‘module1’,‘module2’],function(m1,m2){

})

在这里插入图片描述

2.3 举例使用:

//module.js

define(function (require, exports, module) {

console.log(‘module.js’)

exports.name = “jack” //暴露

})

//module2.js

define(function (require, exoprts, module) {

console.log(‘module2.js’);

exports.desc = “hello world”

})

//main.js

require([‘module1’, ‘module2’], function (m1, m2) {

console.log(‘main.js’);

console.log(m1.name + ‘,’ + m2.desc); //引入module1和module2之后,直接使用其暴露的属性

})

// 执行顺序:

// module1.js

// module2.js

// main.js

人无完人,AMD/RequireJS 也存在饱受诟病的缺点。按照 AMD 的规范,在定义模块的时候需要把所有依赖模块都罗列一遍(前置依赖),而且在使用时还需要在 factory 中作为形参传进去。

CMD/RequireJS模块化的顺序是这样的:模块化加载=》全部模块预执行=》主逻辑中调用模块

所以是依赖加载完成后会先预先将模块执行一遍,这种方式会使得程序效率低;

define([‘a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘f’, ‘g’], function(a, b, c, d, e, f, g){ … });

3.CMD规范

3.1 说明
  • AMD/RequireJS的JS模块实现有很多不优雅的地方,主要原因不能以一种更好的管理模块的依赖加载和执行;

那么就出现了SeaJS,SeaJs遵循的是CMD规范,CMD规范在AMD的基础上改进的一种规范,解决了AMD对依赖模块的执行时机的问题;

  • SeaJS模块化的顺序是:模块化预加载=》主逻辑调用模块时才执行模块中的代码

  • SeaJS的用法和AMD基本相同,并且融合了

CommonJS的写法:

3.2 使用

(对于模块的引入,具有同步和异步两中方式)

//module1.js

define(function (require, exports, module) {

console.log(‘module1.js’)

// module.exports = value;

// exports.xxx = value

exports.name=“i am module1”

})

//main.js

define(function (require, exports, module) {

//引入依赖模块(同步)

var module2 = require(‘./module2’);

console.log(module2.name)

//引入依赖模块(异步1)

require.async(‘./module3’, function (m3) {

//这里m3对应module3

})

//引入依赖模块(异步2)

var module4=require.async(‘./module4’);

console.log(module4.name)

})

总结:

SeaJS的出现,是CommonJS在浏览器的践行者,并吸收了RequireJS的优点

4. ES6中的Module模块

4.1 标准内容
  • 模块功能主要由两个命令构成:exportimport

  • export用于暴露接口,import用于引入模块

4.2 模块的定义

有如下3中方式

  • 方式1-----分别暴露

//module1.js

export var m=1

export var arr=[1,2,4]

export function fun(){

console.log(‘i am a fun’)

}

//引入与使用(结构引入):

import {m,arr,fun} from ‘./module1’

console.log(m);

fun()

  • 方式2—统一暴露

//module2.js

var m=1;

var arr=[1,2,4]

function fun() {

console.log(‘i am a fun’)

}

export {m,arr,fun}

//引入与使用(结构引入):

import {m,arr,fun} from ‘/module2.js’

console.log(arr);

fun()

  • 方式3----默认暴露

//这里默认暴露对象

//module3.js

//export default其实是导出一个叫做default的变量,所以其后面不能跟变量声明语句。

//错误

export default var a = 1;

//正确

export default {

m:1,

fun(){

console.log(‘i am a fun from export defalut’)

}

}

//person.js

export default function getName(){

}

//引入和使用(module为自定义任意名字)

import module from ‘./module3.js’

module.fun()

在这里插入图片描述

4.4 模块的引入

// 解构引入

import { firstName, lastName, year } from ‘a-module’;

// 为输入的变量重新命名

import { lastName as surname } from ‘a-module’;

// 引出模块对象(引入所有)

import * as ModuleA from ‘a-module’;

  • 在使用 ES Module 值得注意的是:import 和 export 命令只能在模块的顶层,在代码块中将会报错,这是因为 ES Module 需要在编译时期进行模块静态优化,import 和 export 命令会被 JavaScript 引擎静态分析,先于模块内的其他语句执行,这种设计有利于编译器提高效率,但也导致无法在运行时加载模块(动态加载)。

对于这个缺点,TC39 有了一个新的提案 – Dynamic Import,提案的内容是建议引入 import()方法,实现模块动态加载。

// specifier: 指定所要加载的模块的位置

import(specifier)

  • import()方法返回一个Promise对象

import(‘b-module’)

.then(module => {

module.helloWorld();

})

.catch(err => {

console.log(err.message);

});

PS:

  • import()函数可以用在任何地方,不仅仅是模块,非模块的脚本也可以使用。

它是运行时执行,也就是说,什么时候运行到这句话,就会加载到指定的模块。另外,import()函数所加载的模块没有静态链接关系,这点也是与import语法不同

  • 注意的时ES6 的Module语法有些浏览器是不支持的,因此需要Babel先进性转码,将import和export命令转成ES5语法才能被浏览器解析。

这里举例之前做过的一个小项目,就是使用了ES6语法中的module模块化思想结合axios库,将需要向服务端发送请求的操作封装到一个模块中,然后对于不同的请求数据操作,直接导入该模块调用即可

1)封装ajax请求函数(使用的时默认暴露)

//首先向外暴露一个函数

//默认为GET请求

import axios from ‘axios’

export default function ajax(url,data={},type=‘GET’) {

return new Promise(function (resolve, reject) {

//这里的return主要时结果的回调函数,即成功了则回调sesolve函数,失败了则回调reject函数

//即异步返回的数据是response.data

let promise

if (type === ‘GET’) {

//这里的目的主要是想将参数拼接成url?username=xx&password=XX

let dataString = ‘’;

Object.keys(data).forEach(key => {

dataString += key + ‘=’ + data[key] + ‘&’

})

if (dataString != null) {

dataString = dataString.substring(0, dataString.length - 1);

url = url + ‘?’ + dataString;

}

//使用axios发送get请求

promise = axios.get(url)

///console.log(promise)

} else {

//使用axios发送post请求

//post请求不用

promise = axios.post(url, data)

}

//response是axios发送请求后得到的promise对象中的response,

//最后因为响应体的数据杂多,这里只取response中的data

promise.then(function (response) {

//成功了则调用resolve

resolve(response.data);

}).catch(function (error) {

//失败了则调用reject

reject(error)

})

})

}

2)封装接口请求函数----使用的时分别暴露

(这个接口函数需要导入上面封装的ajax请求函数,调用,发送请求)

import ajax from ‘./ajax’

const BASE_URL=‘/api’

//注册接口

//注册时即向后台传送username与password---->一个user对象—参数

//需要ajax为桥梁发送请求,ajax返回的结果就是现所需要的结果

//再ajax中需要指定参数

//url—只需要指定后面部分

//2.获取食品分类列表

export const reqFootCategory=()=>ajax(BASE_URL+‘/index_category’)

//3.商店数组对象

export const reqShops=(longitude,latitude)=>ajax(BASE_URL+‘/shops’,{longitude,latitude})

//1.根据经纬度获取地址详情

export const reqAddress=(geohash)=>ajax(${BASE_URL}/position/${geohash})

//4.根据经纬度和关键字搜索商铺列表

export const reqSearchShop = (geohash, keyword) => ajax(BASE_URL+‘/search_shops’, {geohash, keyword})

//5.获取一次性验证码

export const reqGetcaptcha=()=>ajax(BASE_URL+‘/captcha’)

//6.用户名密码登录

export const reqPwdLogin=({name,pwd,captcha})=>ajax(BASE_URL+‘/login_pwd’,{name,pwd,captcha},‘POST’)

//7.发送短信验证码

export const reqSendCode=(phone)=>ajax(BASE_URL+‘/sendcode’,{phone})

//8.手机号验证码登录

export const reqSmsLogin=(phone,code)=>ajax(BASE_URL+‘/login_sms’,{phone,code},‘POST’)

//18813216310

//9.根据会话获取用户信息

export const reqUserInfo=()=>ajax(BASE_URL+‘/userinfo’)

//10.用户登出

export const reqLogout=()=>ajax(BASE_URL+‘logout’)

3)当其他模块需要调用发送请求时,直接使用import结构导入封装的接口函数即可

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
const reqUserInfo=()=>ajax(BASE_URL+‘/userinfo’)

//10.用户登出

export const reqLogout=()=>ajax(BASE_URL+‘logout’)

3)当其他模块需要调用发送请求时,直接使用import结构导入封装的接口函数即可

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

[外链图片转存中…(img-2LNjuvr1-1715542731844)]

[外链图片转存中…(img-zDvcUc1l-1715542731845)]

[外链图片转存中…(img-6Ud5Qwuu-1715542731845)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值