宝哥软件园

javascript中UMD规范的代码推导

编辑:宝哥软件园 来源:互联网 时间:2021-08-30

1.UMD规格

地址:https://github.com/umdjs/umd

UMD规格是所有规格中最丑的,没有之一!它似乎使该模块同时兼容AMD和CommonJs规范,并被一些需要同时支持浏览器端和服务器端引用的第三方库使用。UMD是一个时代的产物,当各种环境最终实现ES和谐的统一标准时,它将退出历史舞台。

乍一看,UMD规范的结构非常复杂,主要是因为它需要一些javascript的基础知识来理解这个范式,其基本结构如下:

(函数(根,工厂){ if(type of define==' function ' define . AMD){//AMD define([' jquery ','下划线'],工厂);} else if(导出类型===' object '){//节点,模块。exports=factory,例如commonjs (require ('jquery ')、require('下划线'));} else {//browser全局变量(root是window)root . return exports=factory(root . jquery,root。_);}}(这个,函数($,_) {//方法函数a(){ };//私有方法,因为它没有返回(见下文)函数b(){ };//公共方法,因为返回了函数c(){ };//公共方法,因为它被返回//暴露的公共方法返回{b: b,c : c } });2.源代码范例的推导2.1基本结构

我们先来看看最外层的结构:

(function(){ }();很简单,它是一个自动执行的函数。由于它是一个模块化标准,这意味着这个自执行函数最终可以导出一个模块,从代码的角度来看,实际上有两种常见的实现:

Return返回模块;实际参数传入一个对象,函数内部生成的需要导出的东西挂在这个对象的属性上;可以看到上面的函数体里面没有return语句,所以可以猜测UMD是用第二种方式实现的。由于UMD是一个模块化规范,它的功能是根据使用要求生产模块,也就是说,它的职责定位叫做模块工厂。我们可以定义一个工厂方法,每次执行这个方法,都会返回一个模块,所以它的基本结构变成如下:

(函数(工厂){ //假设没有使用模块化方案,执行工厂函数后返回的内容直接挂载到全局窗口。some _ Attr=factory();}(function(){ //模块体的自定义内容/* var a,b,c function a1(){ } function B1(){ } function C1(){ } return { a : a1,b:b1} */})),也就是说我们定义了一个匿名函数。然后作为参数传递给自执行函数,再通过自执行函数内部的形式参数访问factory方法(或者你会更熟悉回调函数或者回调的名字),简单的挂在全局对象上,这样就完成了基本的模块导出。

有时候,我们也希望模块可以在非全局环境下挂载,通过动态导入挂载的对象,让代码更加灵活。这涉及到一个基础知识,即浏览器环境中的全局对象有父、顶、自三个属性,来跟踪iframe嵌入页面后引入的新Window对象。单页Window.self指向自身,代码通常通过包含self属性来标识全局对象,因此这里的编写可以改进为兼容:

(函数(根,工厂){根。some _ Attr=factory();}(自我!==未定义?self :这个,函数(){ });2.2适应AMD

那么我们就先加入AMD的规范适配,规范地址:AMD规范github地址:https://github.com/amdjs/amdjs-api/blob/master/AMD.md

/* * amd规范的模块定义格式是define(id?依赖性?factory),factory是实际的模块内容*/(函数(factory){ //判断全局环境是否支持AMD标准IF(类型为define==' function' define。AMD){//定义一个AMD模块定义([/*依赖项*/],工厂);}}(函数(/*形式参数*/){//自定义模块体的内容/* var a、b、c函数a1 () {}函数B1 () {}函数C1 () {}返回{a:a1、b : B1 } */}))2.3 adaption Comm

然后我们首先加入CommonJs规范的改编:

/** CommonJs规范使用require('moduleName ')的格式来引用模块,并使用module.exports对象来输出模块,因此只要模块的输出内容安装在module.exports上,模块定义就完成了.*/(函数(工厂){ //判断全局环境是否支持CommonJs标准if(导出类型==' object '类型的define!==' function '){ module . exports=factory(/* require(moduleA),require(moduleB)*/);}} (function (/*形式参数*/){//自定义模块体/* var a,b,c函数a1(){ } function B1(){ } function C1(){ } return { a : a1,B:b1} */})加入对CommonJs的适配后,函数体(通常是一个对象)中的return内容就挂载到了module.exports上,如果你写过node.js的代码,你会比较熟悉。

把上面的片段搓在一起,你就会明白UMD长什么样了。

3.更有针对性的UMD范式

UMD在其github主页上提供了一个更有针对性的范例,适用于不同的场景,感兴趣的读者可以查看(地址在第一部分给出)。

发布一个对大多数开发人员可能有用的jqueryPlugin开发范例。如果您理解以上分析,下面的代码应该不难理解:

//使用CommonJS、AMD或浏览器全局创建jQuery插件。(函数(工厂){ if(type of define==' function ' define . AMD){//AMD。注册为匿名模块。define(['jquery'],工厂);} else if(type of module==' object ' module . exports){//Node/CommonJS module . exports=function(root,jQuery){ if(jQuery===undefined){//require(' jQuery ')返回一个需要window来//构建jQuery实例的工厂,我们规范化了我们使用需要这个模式的模块//的方式,但是提供的窗口是一个noop //如果定义了(jQuery如何工作)if (typeof window!==' undefined '){ jQuery=require(' jQuery ');} else { jQuery=require(' jQuery ')(root);} }工厂(jQuery);返回jQuery};} else {//Browser globals factory(jQuery);} }(function($){ $ . fn . jqueryplugin=function(){ return true;};}));4.模块化开发

前端模块化本身是一个稍微有些混乱的话题,作者自己一开始也是在require()和request . js之间搞混的,但是,模块化是前端开发中非常重要的一个话题。如果你不想一辈子只写一页代码,那就必须通过这一关,感兴趣的读者可以按照以下几个基本类别分块学习。

更多资讯
游戏推荐
更多+