开发者社区> 大史不说话> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

javascript基础修炼(4)——UMD规范的代码推演

简介: javascript基础修炼(4)——UMD规范的代码推演 1. UMD规范 地址:https://github.com/umdjs/umd UMD规范,就是所有规范里长得最丑的那个,没有之一!!!它是为了让模块同时兼容AMD和CommonJs规范而出现的,多被一些需要同时支持浏览器端和服务端引用的第三方库所使用。
+关注继续查看

img_22affe5f2a623d2854c1ed16c31c6e8f.png

javascript基础修炼(4)——UMD规范的代码推演

1. UMD规范

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

UMD规范,就是所有规范里长得最丑的那个,没有之一!!!它是为了让模块同时兼容AMDCommonJs规范而出现的,多被一些需要同时支持浏览器端和服务端引用的第三方库所使用。UMD是一个时代的产物,当各种环境最终实现ES harmony的统一的规范后,它也将退出历史舞台。

UMD规范的结构乍一看非常复杂,主要是因为想要看懂这段范式需要一些javascript基础知识,它的基本结构是这样的:

(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        // AMD
        define(['jquery', 'underscore'], factory);
    } else if (typeof exports === 'object') {
        // Node, CommonJS之类的
        module.exports = factory(require('jquery'), require('underscore'));
    } else {
        // 浏览器全局变量(root 即 window)
        root.returnExports = factory(root.jQuery, root._);
    }
}(this, function ($, _) {
    //    方法
    function a(){};    //    私有方法,因为它没被返回 (见下面)
    function b(){};    //    公共方法,因为被返回了
    function c(){};    //    公共方法,因为被返回了

    //    暴露公共方法
    return {
        b: b,
        c: c
    }
}));

2. 源码范式推演

2.1 基本结构

先来看最外层的结构:

(function (){}());

非常简单,就是一个自执行函数。既然它是一个模块化的标准,也就意味着这个自执行函数最终可以导出一个模块,那么从代码的角度来讲实际上有两种常见的实现方式:

  1. return返回一个模块;
  2. 实参传入一个对象,把函数内部生成好的需要导出的东西挂在这个对象的属性上;

可以看到上面的函数体内部是没有return语句的,那么可以猜测UMD在实现时是采用了第二种方式。既然UMD是一种模块化的规范,那么它的功能就是根据使用要求生产模块,也就是说它的职责定位叫做模块工厂,我们可以定义一个factory方法,每当执行该方法时,就回返回一个模块,所以它的基本结构就变成了如下的样子:

(function (factory){
    //假设没有使用任何模块化方案,那么将工厂函数执行后返回的内容直接挂载到全局
    window.Some_Attr = factory();
}(function(){
    //自定义模块主体的内容
    /*
        var a,b,c
        function a1(){}
        function b1(){}
        function c1(){}
        return {
           a:a1,
           b:b1
        }
     */
}))

也就是说我们自定义一个匿名函数,然后把它当做实参传给了自执行函数,然后在自执行函数内部通过形参来访问这个工厂方法(或者你会更熟悉回调函数callback这样的叫法),把它简单地挂在到全局对象上,这样就完成了基本的模块导出。

有的时候我们也希望可以将模块挂载到非全局的环境,将挂载对象动态传入可以让代码变得更灵活,此处涉及到一个基础知识,就是浏览器环境中的全局对象拥有parent,top,self三个属性来追踪页面中嵌入<iframe>后引入的新的Window对象的,单页面Window.self是指向自己的,代码中常通过是否包含self属性来鉴别全局对象,所以此处的写法可以改进为兼容:

(function(root,factory){
    root.Some_Attr = factory();
}(self !== undefined ? self : this, function(){
    
}));

2.2 适配AMD

接着我们先来加入AMD的规范的适配,规范地址:AMD规范github地址

/*
* AMD规范的模块定义格式是define(id?, dependencies?, factory),factory就是实际的模块内容
*/
(function (factory){
    //判断全局环境是否支持AMD标准
    if(typeof define === 'function' && define.amd){
        //定义一个AMD模块
        define([/*denpendencies*/],factory);
    }
}(function(/*formal parameters*/){
    //自定义模块主体的内容
    /*
        var a,b,c
        function a1(){}
        function b1(){}
        function c1(){}
        return {
           a:a1,
           b:b1
        }
     */
}))

2.3 适配CommonJs

接着我们先来加入CommonJs的规范的适配:

/*
* CommonJs规范使用require('moduleName')的格式来引用模块,使用module.exports对象输出模块,所以只要把模块的输出内容挂载到module.exports上就完成了模块定义。
*/
(function (factory){
    //判断全局环境是否支持CommonJs标准
      if(typeof exports === 'object' && typeof define !== 'function'){
             module.exports = factory(/*require(moduleA), require(moduleB)*/);
      }
}(function(/*formal parameters*/){
    //自定义模块主体的内容
    /*
        var a,b,c
        function a1(){}
        function b1(){}
        function c1(){}
        return {
           a:a1,
           b:b1
        }
     */
}))

加入对CommonJs的适配后,函数主体中return的内容(一般是一个对象)就被挂载到了module.exports上,如果你编写过node.js代码,对此一定不会陌生。

把上面的片段揉到一块,你也就看懂UMD的样子了。

3. 更具针对性的UMD范式

UMD在其github主页上提供了更具针对性的范式,适用于不同的场景,感兴趣的读者可以自行查看(地址在第一节已经给出)。

img_3cb7a159401664da414485b737d5a6c3.png

在此贴一个可能对大多数开发者比较有用的jqueryPlugin的开发范式,如果看懂了上面的分析,那么下面的代码应该不难看懂:

// Uses CommonJS, AMD or browser globals to create a jQuery plugin.
(function (factory) {
    if (typeof define === 'function' && define.amd) {
        // AMD. Register as an anonymous module.
        define(['jquery'], factory);
    } else if (typeof module === 'object' && module.exports) {
        // Node/CommonJS
        module.exports = function( root, jQuery ) {
            if ( jQuery === undefined ) {
                // require('jQuery') returns a factory that requires window to
                // build a jQuery instance, we normalize how we use modules
                // that require this pattern but the window provided is a noop
                // if it's defined (how jquery works)
                if ( typeof window !== 'undefined' ) {
                    jQuery = require('jquery');
                }
                else {
                    jQuery = require('jquery')(root);
                }
            }
            factory(jQuery);
            return jQuery;
        };
    } else {
        // Browser globals
        factory(jQuery);
    }
}(function ($) {
    $.fn.jqueryPlugin = function () { return true; };
}));

4. 模块化开发

前端模块化本身是一个稍显混乱的话题,笔者自己最初也是require( )require.js傻傻分不清楚,但模块化是前端开发中非常重要的课题,如果你不想一辈子只是在一个页面内写代码,这一关是一定要过的,感兴趣的读者可以按照下面的基本类别划分分块进行学习。

img_8b319fba299db97e4a0c3f4e79859d90.png

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
Js实现网站常用的评分效果!
View Code DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">    网站评分特效            *        {            font-size: 50px;        }     ...
720 0
js操作的跨域问题:js实现自动设置框架载入页面高度的问题
*{border:0px; margin:0px; padding:0px;}首页   function setHeight(){  var iframe = document.getElementById("middle");     try{       var aHeight = iframe.
748 0
Asp.net+Xml+js实现无线级下拉菜单
地址如下:http://xucanzhao.cnblogs.com/archive/2005/09/01/228012.htmlAsp.net+Xml+js实现无线级下拉菜单
569 0
利用JS实现的根据经纬度计算地球上两点之间的距离
最近用到了根据经纬度计算地球表面两点间距离的公式,然后就用JS实现了一下。 计算地球表面两点间的距离大概有两种办法。 第一种是默认地球是一个光滑的球面,然后计算任意两点间的距离,这个距离叫做大圆距离(The Great Circle Distance)。
740 0
当前页居中分页效果的JS实现
function show_page(cur_pc){    var cp=cur_pc;    //curent page count    var tp=this.p;    //total page count    var sp=this.
739 0
JS+DIV实现自定义Title的显示方式
     自定义的title显示方式一直在华夏用,当你的鼠标悬停在带有提示的链接上时会有自定义的显示内容出现,显示的内容支持html代码,但是这个效果不支持firefox及其他浏览器,最近对之进行了改进,终于兼容了FF,Safari。代码如下:   var qTipTag = "a"; //Which tag do you want to qTip-ize? Keep it lowerc
1034 0
JS实现回调例子
function f_2(id){ return -id;}// func即回调函数function f_1(id,func){ id++; id=func(id); return id;}function f_3(){ var id=f_1(1,f_2); alert(id);}f_3();
617 0
用vbs、js 实现访问指定页面
在计划任务中添加Run.vbs 或 Run.jsRun.vbs ' Create an instance of IEDim IESet IE = CreateObject("InternetExplorer.
875 0
+关注
大史不说话
独爱大前端
30
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载