简朴聊聊模块

模块

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 的模块化计划。

    原文作者:夜暁宸
    原文地址: https://segmentfault.com/a/1190000018635558
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞