• 模块化理解 CommonJS AMD CMD ES6模块


    模块化就是将系统分解成一个一个独立的功能模块,模块是独立的,可复用的,模块之间是解耦的。

    CommonJS

    Commonjs模块是一个可复用的js块,通过exports输出这个特定对象,其他模块通过require()引用此对象;

    CommonJS支持无封装的模块(即没有定义的相关语句),把我们从AMD的define()封装中解放出来;

    CommonJS只支持对象作为模块;

     1 //package/lib is a dependency we require
     2 var lib = require("package/lib");
     3 
     4 //behaviour for our module
     5 function foo(){
     6    lib.log("hello world!")
     7 }
     8 
     9 //export (expose) foo to other modules
    10 exports.foo = foo

     Node应用由模块组成,采用commonjs模块规范,每个文件是一个模块,有自己的作用域。

    commonjs规范规定,每个模块内部,module变量代表当前模块。这个变量是一个对象,它的

    exports属性(module.exports)是对外的接口。require方法用于加载模块

     1 //example.js
     2 var x=5;
     3 var foo = function(v){
     4   return v + x;
     5 };
     6 module.exports.x = x;
     7 module.exports.foo = foo;
     8 
     9 //test.js
    10 var example = require('./example.js');
    11 console.log(example.x);//5
    12 console.log(example.foo(1))//6

    不同的实现对require时的路径有不同要求,一般情况可以省略js拓展名,可以使用相对路径,也可以使用绝对路径,甚至可以省略路径直接使用模块名(前提是该模块是系统内置模块)

    commonJs模块特点:

    1.所有代码都运行在模块作用域,不会污染全局作用域

    2.模块可多次加载,但只在第一次加载运行,运行结果会存储在缓存,后面加载直接读取缓存,必须清除缓存才能让模块再次运行;

    3.模块采用同步运行方式,按照在代码中出现但顺序进行加载

    module.exports属性

    module.exports属性表示当前模块对外输出但接口,其他文件加载该模块就是读取module.exports变量;

    exports变量

    为了方便,Node为每个模块提供一个exports变量,指向module.exports;这等同于在每个模块的头部都有一行一下命令:

     1 var exports = module.exports 

     即,在对外输出模块接口时,可以向exports对象添加方法

    1 exports.area = function (r) {
    2   return Math.PI * r * r;
    3 };

    注意,不能直接将exports变量指向一个值,因为这样等于切断了exportsmodule.exports的联系。

    即 exports = function(r){return Math.PI*r*r;}是无效的。

    1 exports.hello = function(){
    2     return 'hele';
    3 }
    4 module.exports = 'Hello world';

    上面代码中,hello函数是无法输出的,因为下面module.exports被重新赋值了。

    AMD(Asynchronous Module Defination,浏览器端js模块化)

    异步模块定义规范,使用异步方式加载模块,通过define方法定义模块,require方法加载模块。

    由于不是JavaScript原生支持,使用AMD规范进行页面开发需要用到对应的库函数RequireJS,实际上AMD 是 RequireJS 在推广过程中对模块定义的规范化的产出;

    异步加载模块,模块的加载不影响它后面语句的运行,所有依赖这个模块的语句,都定义在回调函数中,等加载完成

    后,这个回调函数才会运行。

     1 //定义模块myModule.js
     2 define(['dependency'],function(){
     3    var name = 'Bily';
     4    function printName(){
     5         console.log(name);
     6     }
     7     return {
     8        printName: printName
     9     }
    10 })
    11 //加载模块
    12 require(['myModule],function(my){
    13     my.printName();
    14 })  

    requireJS定义了一个函数define,它是全局变量,用来定义模块

    define(id?, dependencies? factory)

    id:可选参数,用来定义模块的标识,如果没有提供该参数,就用脚本文件名(去掉扩展名)

    dependencies: 当前模块依赖的模块名称数组

    factory: 工厂方法,模块初始化要执行的函数或对象。如果是函数,它应该只被执行一次。如果是对象,此对象应该

    为模块的输出值

    在文件中使用require函数加载模块

    require([dependencies],function(res){})

    [dependencies] :第一个参数是数组,表示所依赖的模块

    function : 第二个参数是一个回调函数,当前面指定的模块都加载成功后,它会被调用;加载的模块会以参数形式传入该函数,从而在回调函数内部可以使用这些模块;

    require()函数在加载依赖的函数的时候是异步加载的,这样浏览器不会失去响应,它指定的回调函数,只有在前面的

    模块都加载成功后,才会运行,解决了依赖性的问题;

    模块化就是将系统分解成一个一个独立的功能模块,模块是独立的,可复用的,模块之间是解耦的。

    CommonJS

    Commonjs模块是一个可复用的js块,通过exports输出这个特定对象,其他模块通过require()引用此对象;

    CommonJS支持无封装的模块(即没有定义的相关语句),把我们从AMD的define()封装中解放出来;

    CommonJS只支持对象作为模块;

     1 //package/lib is a dependency we require
     2 var lib = require("package/lib");
     3 
     4 //behaviour for our module
     5 function foo(){
     6    lib.log("hello world!")
     7 }
     8 
     9 //export (expose) foo to other modules
    10 exports.foo = foo

     Node应用由模块组成,采用commonjs模块规范,每个文件是一个模块,有自己的作用域。

    commonjs规范规定,每个模块内部,module变量代表当前模块。这个变量是一个对象,它的

    exports属性(module.exports)是对外的接口。require方法用于加载模块

     1 //example.js
     2 var x=5;
     3 var foo = function(v){
     4   return v + x;
     5 };
     6 module.exports.x = x;
     7 module.exports.foo = foo;
     8 
     9 //test.js
    10 var example = require('./example.js');
    11 console.log(example.x);//5
    12 console.log(example.foo(1))//6

    不同的实现对require时的路径有不同要求,一般情况可以省略js拓展名,可以使用相对路径,也可以使用绝对路径,甚至可以省略路径直接使用模块名(前提是该模块是系统内置模块)

    commonJs模块特点:

    1.所有代码都运行在模块作用域,不会污染全局作用域

    2.模块可多次加载,但只在第一次加载运行,运行结果会存储在缓存,后面加载直接读取缓存,必须清除缓存才能让模块再次运行;

    3.模块采用同步运行方式,按照在代码中出现但顺序进行加载

    module.exports属性

    module.exports属性表示当前模块对外输出但接口,其他文件加载该模块就是读取module.exports变量;

    exports变量

    为了方便,Node为每个模块提供一个exports变量,指向module.exports;这等同于在每个模块的头部都有一行一下命令:

     1 var exports = module.exports 

     即,在对外输出模块接口时,可以向exports对象添加方法

    1 exports.area = function (r) {
    2   return Math.PI * r * r;
    3 };

    注意,不能直接将exports变量指向一个值,因为这样等于切断了exportsmodule.exports的联系。

    即 exports = function(r){return Math.PI*r*r;}是无效的。

    1 exports.hello = function(){
    2     return 'hele';
    3 }
    4 module.exports = 'Hello world';

    上面代码中,hello函数是无法输出的,因为下面module.exports被重新赋值了。

    AMD(Asynchronous Module Defination,浏览器端js模块化)

    异步模块定义规范,使用异步方式加载模块,通过define方法定义模块,require方法加载模块。

    由于不是JavaScript原生支持,使用AMD规范进行页面开发需要用到对应的库函数RequireJS,实际上AMD 是 RequireJS 在推广过程中对模块定义的规范化的产出;

    异步加载模块,模块的加载不影响它后面语句的运行,所有依赖这个模块的语句,都定义在回调函数中,等加载完成

    后,这个回调函数才会运行。

     1 //定义模块myModule.js
     2 define(['dependency'],function(){
     3    var name = 'Bily';
     4    function printName(){
     5         console.log(name);
     6     }
     7     return {
     8        printName: printName
     9     }
    10 })
    11 //加载模块
    12 require(['myModule],function(my){
    13     my.printName();
    14 })  

    requireJS定义了一个函数define,它是全局变量,用来定义模块

    define(id?, dependencies? factory)

    id:可选参数,用来定义模块的标识,如果没有提供该参数,就用脚本文件名(去掉扩展名)

    dependencies: 当前模块依赖的模块名称数组

    factory: 工厂方法,模块初始化要执行的函数或对象。如果是函数,它应该只被执行一次。如果是对象,此对象应该

    为模块的输出值

    在文件中使用require函数加载模块

    require([dependencies],function(res){})

    [dependencies] :第一个参数是数组,表示所依赖的模块

    function : 第二个参数是一个回调函数,当前面指定的模块都加载成功后,它会被调用;加载的模块会以参数形式传入该函数,从而在回调函数内部可以使用这些模块;

    require()函数在加载依赖的函数的时候是异步加载的,这样浏览器不会失去响应,它指定的回调函数,只有在前面的

    模块都加载成功后,才会运行,解决了依赖性的问题;

    CMD(Common Module Definition,通用模块定义)

    cmd在模块定义和模块加载时机上和amd不同,并且CMD需要额外引入第三方的库文件,SeaJS;

    seaJS推崇一个模块一个文件

    define是一个全局函数,用来定义模块

    define (id? , dependences?, factory)

     参数id:可选,字符串类型,模块标识,如果没有提供参数,默认是文件名;

     参数dependences:可选,字符串数组,当前模块依赖的模块,CMD推崇依赖就近;

     参数factory:回调函数,工厂方法,初始化模块需要执行的函数或对象,如果为函数,它只被执行

    一次,如果为对象,此对象会作为模块的输出值;

     1 // cmd1.js
     2 define(function(require,exports,module){
     3   // ...
     4   module.exports={
     5     // ...
     6   }
     7 })
     8 
     9 // cmd2.js
    10 define(function(require,exports,module){
    11   var cmd2 = require('./cmd1')
    12   // cmd2.xxx  依赖就近书写
    13   module.exports={
    14      // ...
    15   }
    16 })

    对外提供接口:给exports对象添加成员,或者使用retutn直接向外提供接口

    ADM和CMD区别,AMD提前执行依赖的模块即依赖前置,而后者是在用的之前,即依赖就近,只有在需要用到

    某个模块的时候才requrie;

    ES6模块化

     ES6在语言标准的层面上,实现了模块功能,可取代commonjs和AMD规范,成为浏览器和服务器通用的模块解决方案;

    ES6设计思想是尽量静态化,使得在编译时就能确定模块的依赖关系,以及输入和输出变量;而CommonJS和AMD

    只能在运行时才能确定;

    Es6模块不是对象,而是通过export命令显示指定输出的代码,再通过import命令输入;

    // ES6模块
    import { stat, exists, readFile } from 'fs';

    上面代码实质是从fs模块加载3个方法,其他方法不加载,这种加载称为“编译时加载”或静态加载,即ES6可以在编译时就完成

    模块加载,效率要比CommonJS模块的加载方式高,这也导致没法引用ES6模块本身,因为它不是对象。

    ES6的模块自动采用严格模式,不管你有没有在模块头部加‘use strict’;

    尤其注意,在模块中,顶层this指向undefined,即不可在顶层代码使用this;

     
  • 相关阅读:
    前端模板引擎编译
    h5与app混合开发,jsbridge
    vuex
    async await promise
    node端口被占用
    npm工作流 与webpack 分同环境配置
    GraphQL
    mybatis批量删除、插入
    Oracle数据库速查知识文档
    Oracle刷新物化视图
  • 原文地址:https://www.cnblogs.com/Janejxt/p/12981223.html
Copyright © 2020-2023  润新知