简单聊聊模块

首席Bug官
• 阅读 1186

模块

JavaScript 中,模块只不过是基于函数某些特性的代码组织方式。

在《你不知道的 JavaScript》中,给出了模块模式因具备的两个必要条件:

  1. 必须有外部的封闭函数,该函数必须至少被调用一次(每次调用都会创建一个新的模块实例)。
  2. 封闭函数必须返回至少一个内部函数,这样内部函数才能在私有作用域中形成闭包,并且可以访问或者修改私有的状态。

从中我们可以看到一个比较重要的一点,从函数调用所返回的只有数据属性而没有闭包函数的对象并不是真正的模块。

你看?,理解闭包的重要性再次体现出来了。

从以上要求的两点来看,只要满足相应的条件,我们很容易写出一个模块。

const userModule = ((name = 'module') => {
  let id = 1,moduleName = name;
  const sayName = () => {
      console.log('moduleName: %s', moduleName);
  };
  const sayId = () => {
    console.log('id: %s', id);
  };
  const changeName = value => {
      moduleName = value;
  };
  const changePublicAPI = () => {
    publicAPI.sayIdentification = sayId
  };
  const publicAPI = {
    sayIdentification: sayName,
    changeName,
    changePublicAPI,
  }
  return publicAPI;
})();

以上在满足两个必要的基础上转换成了 IIFE(立即执行函数表达式)。同时可以看出,基于函数的模块可以在运行时通过内部保留着公共 API 对象的引用,从而对模块实例进行修改。

模块机制

模块的出现也是为了能够提高代码的复用率,方便代码管理。复用模块,自然会出现模块依赖的问题,所以说我们需要一个管理模块依赖的模块。

const moduleManage = (() => {
  let modules = {};
  const define = (name, deps, module) => {
    deps = deps.map(item => modules[item])
    modules[name] = module(...deps);
  };
  const exports = (name) => {
    return modules[name];
  }
  return {
    define,
    exports,
  }
})();

moduleManage.define('a', [], () => {
  const sayName = name => {
    console.log('name: %s', name);
  };
  return {
    sayName,
  }
});
moduleManage.define('b', ['a'], (a) => {
  let name = 'b';
  const sayName = () => {
    a.sayName(name)
  };
  return {
    sayName,
  }
});

var b = moduleManage.exports('b');
b.sayName();

模块依赖管理器也依然是个模块,这里的实现其实很简单。modules[name] = module(...deps),使用 modules 缓存各个模块,对于依赖模块的模块,则把依赖作为参数使用。

规范

CommonJS 规范服务于服务端,同步阻塞,在写法风格上是依赖就近。但是在浏览器上,CommonJS 就不好使了,浏览器需要从服务器请求数据,下载完成后才会有下一步的执行。如果采用 CommonJS 的同步方式,指不定什么时候文件才会下载完成。

为了推广到浏览器上,AMD 规范采用异步方式加载模块。先异步加载模块,加载完成后就可以在回调中使用依赖模块了。这样就保证了在使用依赖时,依赖已经加载完成。AMD 规范是早早地下载,早早地执行,在回调里 require 的是依赖的引用。在写法风格上是依赖前置,这种风格已经不同于 CommonJS 了。还有,这里早早地执行会带来一个问题,如果存在某个依赖某些条件不成立,导致没有用上。那么,这里的早早地执行岂不是多此一举了?

CMD 规范是 sea.js 推崇的规范,它采用的也是异步加载模块的方式,只是在依赖模块的执行时机上有所不同。在写法风格上,又回归到 CommonJS,依赖就近。sea.js 是早早地下载,延迟执行。

到了 ES6,终于从语法上支持模块化了,ES6 模块是编译时加载,使得在编译时就能确定模块的依赖关系,而且在将来服务器和浏览器都会支持 ES6 的模块化方案。

点赞
收藏
评论区
推荐文章
blmius blmius
4年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
Wesley13 Wesley13
4年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Python进阶者 Python进阶者
4年前
浅析Python模块的引入和调用
大家好,我是IT共享者,人称皮皮。这篇文章我们来浅析Python模块的引入和调用。一、前言Python中的模块,有过C语言编程经验的朋友都知道在C语言中如果要引用sqrt函数,必须用语句include引入math.h这个头文件,否则是无法正常进行调用的。那么在Python中,如果要引用一些其他的函数,该怎么处理呢?在Python中有一个概念叫做模块(mod
CuterCorley CuterCorley
4年前
C语言入门系列之7.函数的定义、参数、调用和存储类别
一、概述1.函数基本概念一个较大的程序可分为若干个程序模块,每一个模块用来实现一个特定的功能。在高级语言中用子程序实现模块的功能,子程序由函数来完成。一个C程序可由一个主函数和若干个其他函数构成。函数间的调用关系可能如下:由主函数调用其他函数,其他函数也可以互相调用,同一个函数可以被一个或多个函数调用任意多次。简单测试如下:cinclude
Stella981 Stella981
4年前
Python之time模块的时间戳、时间字符串格式化与转换
Python处理时间和时间戳的内置模块就有time,和datetime两个,本文先说time模块。关于时间戳的几个概念时间戳,根据1970年1月1日00:00:00开始按秒计算的偏移量。时间元组(struct_time),包含9个元素。 time.struct_time(tm_y
Stella981 Stella981
4年前
Python基础(六)
1函数1.1函数的分类函数可以分成三种:内置函数(BIF):解释器中内置的函数,可以直接通过函数名调用,如len().模块函数:定义在模块中的函数,通过模块名调用,如math.sin().用户自定义函数.1.2函数与方法函数是指在类外定义的,可以独立调用的
Stella981 Stella981
4年前
HIVE 时间操作函数
日期函数UNIX时间戳转日期函数: from\_unixtime语法:   from\_unixtime(bigint unixtime\, string format\)返回值: string说明: 转化UNIX时间戳(从19700101 00:00:00 UTC到指定时间的秒数)到当前时区的时间格式举例:hive   selec
小万哥 小万哥
2年前
Python 模块:创建、导入和使用
什么是模块?将模块视为代码库。模块是一个包含一组函数的文件,您想要在应用程序中包含这些函数。创建一个模块要创建一个模块,只需将要包含在其中的代码保存在扩展名为.py的文件中:示例:将以下代码保存在名为的文件中:pythondefgreeting(name)
Python进阶者 Python进阶者
2年前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这