龙空技术网

JS模块化详解

鼠鼠游戏 41

前言:

今天朋友们对“jsload函数”大约比较关怀,咱们都需要剖析一些“jsload函数”的相关知识。那么小编在网络上搜集了一些有关“jsload函数””的相关资讯,希望大家能喜欢,小伙伴们快快来了解一下吧!

CommonJS AMD CMD UMD ES6 Module

模块化开发的优点:

Ø 模块化开发中,通常一个文件就是一个模块,有自己的作用域,只向外暴露特定的变量和函数,并且可以按需加载。

Ø 依赖自动加载,按需加载。

Ø 提高代码复用率,方便进行代码的管理,使得代码管理更加清晰、规范。

Ø 减少了命名冲突,消除全局变量。

Ø 目前流行的js模块化规范有CommonJS、AMD、CMD以及ES6的模块系统

CommonJS

CommonJS是服务器模块的规范,Node.js采用了这个规范。

根据 CommonJS 规范,一个单独的文件就是一个模块,每一个模块都是一个单独的作用域,在一个文件定义的变量(还包括函数和类),都是私有的,对其他文件是不可见的。

CommonJS规范加载模块是同步的,也就是说,只有加载完成,才能执行后面的操作。

CommonJS 中,加载模块使用 require 方法。该方法读取一个文件并执行,最后返回文件内部的 exports 对象。

var x = 5;var addX = function(value) {return value + x;};module.exports.x = x;module.exports.addX = addX;// 也可以改写为如下module.exports = {x: x,addX: addX,};let math = require('./math.js');console.log('math.x',math.x);console.log('math.addX', math.addX(4));

AMD

Ø AMD = Asynchronous Module Definition,RequireJS异步模块定义。

Ø AMD 规范加载模块是异步的,并允许函数回调,不必等到所有模块都加载完成,后续操作可以正常执行。

Ø AMD 中,使用 require 获取依赖模块,使用 exports 导出 API

Ø 可异步加载,require([module], callback) 中 callback 为模块加载完成后的回调函

//规范 APIdefine(id?, dependencies?, factory);define.amd = {};// 定义无依赖的模块define({add: function(x,y){return x + y;}});// 定义有依赖的模块define(["alpha"], function(alpha){return {verb: function(){return alpha.verb() + 1;}}});

RequireJS

RequireJS 是一个前端模块化管理的工具库,遵循 AMD 规范,RequireJS 是对 AMD 规范的阐述。

RequireJS 基本思想为,通过一个函数来将所有所需的或者所依赖的模块装载进来,然后返回一个新的函数(模块)。后续所有的关于新模块的业务代码都在这个函数内部操作。

RequireJS 要求每个模块均放在独立的文件之中,并使用 define 定义模块,使用 require 方法调用模块。

按照是否有依赖其他模块情况,可以分为 独立模块 和 非独立模块。

独立模块,不依赖其他模块,直接定义define({method1: function(){},method2: function(){}});//等价于define(function() {return {method1: function(){},method2: function(){}}});非独立模块,依赖其他模块define([ 'module1', 'module2' ], function(m1, m2) {...});//等价于define(function(require) {var m1 = require('module1');var m2 = require('module2');...});require 方法调用模块require(['foo', 'bar'], function(foo, bar) {foo.func();bar.func();});

特点:对于依赖的模块,AMD推崇依赖前置,提前执行。也就是说,在define方法里传入的依赖模块(数组),会在一开始就下载并执行

CMD

CMD = Common Module Definition,即 通用模块定义。CMD 是 SeaJS 在推广过程中对模块定义的规范化产出。

CMD规范和AMD类似,都主要运行于浏览器端,写法上看起来也很类似。主要是区别在于 模块初始化时机

Ø AMD中只要模块作为依赖时,就会加载并初始化

Ø CMD中,模块作为依赖且被引用时才会初始化,否则只会加载。

Ø CMD 推崇依赖就近,AMD 推崇依赖前置。

Ø AMD 的 API 默认是一个当多个用,CMD 严格的区分推崇职责单一。例如,AMD 里 require 分全局的和局部的。CMD里面没有全局的 require,提供 seajs.use() 来实现模块系统的加载启动。CMD 里每个 API 都简单纯粹。

//AMDdefine(['./a','./b'], function (a, b) {//依赖一开始就写好a.test();b.test();});//CMDdefine(function (requie, exports, module) {//依赖可以就近书写var a = require('./a');a.test();...//软依赖if (status) {var b = requie('./b');b.test();}});
SeaJS

Ø 通过 exports 暴露接口。这意味着不需要命名空间了,更不需要全局变量。这是一种彻底的命名冲突解决方案。

Ø 通过 require 引入依赖。这可以让依赖内置,开发者只需关心当前模块的依赖,其他事情 Sea.js 都会自动处理好。对模块开发者来说,这是一种很好的 关注度分离,能让程序员更多地享受编码的乐趣。

Ø 通过 define 定义模块

//a.js/** define 接受 factory 参数,factory 可以是一个函数,也可以是一个对象或字符串,* factory 为对象、字符串时,表示模块的接口就是该对象、字符串。* define 也可以接受两个以上参数。字符串 id 表示模块标识,数组 deps 是模块依赖.*/define(function(require, exports, module) {var $ = require('jquery');exports.setColor = function() {$('body').css('color','#333');};});//b.js//数组中声明需要加载的模块,可以是模块名、js文件路径seajs.use(['a'], function(a) {$('#el').click(a.setColor);});

特点:对于依赖的模块,CMD推崇依赖就近,延迟执行。也就是说,只有用到时依赖模块才执行

UMD

Ø UMD = Universal Module Definition,即通用模块定义。UMDAMDCommonJS的糅合

Ø UMD 先判断是否支持 Node.js 的模块(exports)是否存在,存在则使用 Node.js 模块模式。再判断是否支持 AMD(define 是否存在),存在则使用 AMD 方式加载模块。

(function (window, factory) {if (typeof exports === 'object') {module.exports = factory();} else if (typeof define === 'function' && define.amd) {define(factory);} else {window.eventUtil = factory();}})(this, function () {//module ...});

ES6 Module

Ø ES6 Module是编译时输出接口;

Ø ES6 Module可以单独加载其中的某个接口;

Ø ES6 Module输出的是值的引用,被输出模块的内部的改变会影响引用的改变;

Ø ES6 Module this指向undefined;

//a.jsvar name = 'lin';var age = 13;var job = 'ninja';export { name, age, job};//b.jsimport { name, age, job} from './a.js';console.log(name, age, job);// lin 13 ninja//或者//a2.jsexport default function () {console.log('default ');}//b2.jsimport customName from './a2.js';customName(); // 'default'

CMD(SeaJS)与AMD(RequireJS)区别

二者的区别主要表现在模块初始化时机

Ø AMD(RequireJS)中只要模块作为依赖时,就会加载并初始化。即尽早地执行(依赖)模块。相当于所有的require都被提前了,而且模块执行的顺序也不一定100%就是require书写顺序。

Ø CMD(SeaJS)中,模块作为依赖且被引用时才会初始化,否则只会加载。即只会在模块真正需要使用的时候才初始化。模块加载的顺序是严格按照require书写的顺序。

ES6 Module与CommonJS区别

Ø ES6 模块输出的是值的引用,输出接口动态绑定,而 CommonJS 输出的是值的拷贝。

Ø CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。

CommonJS 模块输出的是值的拷贝(类比于基本类型和引用类型的赋值操作)。对于基本类型,一旦输出,模块内部的变化影响不到这个值。对于引用类型,效果同引用类型的赋值操作

// lib.jsvar counter = 3;var obj = {name: 'David'};function changeValue() {counter++;obj.name = 'Peter';};module.exports = {counter: counter,obj: obj,changeValue: changeValue,};// main.jsvar mod = require('./lib');console.log(mod.counter); // 3console.log(mod.obj.name); // 'David'mod.changeValue();console.log(mod.counter); // 3console.log(mod.obj.name); // 'Peter'// Orconsole.log(require('./lib').counter); // 3console.log(require('./lib').obj.name); // 'Peter'

ES6 模块是动态关联模块中的值,输出的是值得引用。原始值变了,import 加载的值也会跟着变

// lib.jsexport let counter = 3;export function incCounter() {counter++;}// main.jsimport { counter, incCounter } from './lib';console.log(counter); // 3incCounter();console.log(counter); //

defer与async的区别

deferasync的区别是:

Ø defer要等到整个页面在内存中正常渲染结束(DOM 结构完全生成,以及其他脚本执行完成),才会执行;

Ø async一旦下载完,渲染引擎就会中断渲染,执行这个脚本以后,再继续渲染。

Ø 一句话,defer是“渲染完再执行”,async是“下载完就执行”。

Ø 如果有多个defer脚本,会按照它们在页面出现的顺序加载,而多个async脚本是不能保证加载顺序的。

标签: #jsload函数