精华内容
下载资源
问答
  • 2022-03-01 13:58:49

    了解

    node应用由模块组成,采用的commonjs模块规范。每一个文件就是一个模块,拥有自己独立的作用域,变量,以及方法等,对其他的模块都不可见。CommonJS规范规定,每个模块内部,module变量代表当前模块。这个变量是一个对象,它的exports属性(即module.exports)是对外的接口。加载某个模块,其实是加载该模块的module.exports属性。require方法用于加载模块。

    CommonJS模块的特点

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

    模块可以多次加载,但是只会在第一次加载时运行一次,然后运行结果就被缓存了,以后再加载,就可以直接读取缓存结果,要是想让模块再次运行,必须清除缓存

    为什么指定CommonJS规范

    在后端,javascript的规范远远落后并且有很多缺陷,这使的难以使用javascript开发大型应用

    没有模块系统

    标准库较少

    没有标准接口

    缺少包管理系统

    列表内容

    CommonJS规范的提出主要是为了弥补javascript没有标准的缺陷

    使用CommonJS模块规范的好处

    CommonJS模块规范很好地解决变量污染问题,每个模块具有独立空间,互不干扰,命名空间等方案与之相比相形见绌。

    CommonJS规范定义模块十分简单,接口十分简洁。

    CommonJS模块规范支持引入和导出功能,这样可以顺畅地连接各个模块,实现彼此间的依赖关系

    更多相关内容
  • CommonJS规范

    2021-03-08 22:37:35
    CommonJS规范CommonJS模块的导出模块的导入CommonJS规范nodejs对CommonJS的实现 CommonJS 在nodejs中,由于有且仅有一个入口文件(启动文件),而开发一个应用肯定会涉及到多个文件配合,因此,nodejs对模块化的需求...

    CommonJS

    在nodejs中,由于有且仅有一个入口文件(启动文件),而开发一个应用肯定会涉及到多个文件配合,因此,nodejs对模块化的需求比浏览器端要大的多

    在这里插入图片描述

    由于nodejs刚刚发布的时候,前端没有统一的、官方的模块化规范,因此,它选择使用社区提供的CommonJS作为模块化规范

    在学习CommonJS之前,首先认识两个重要的概念:模块的导出模块的导入

    模块的导出

    要理解模块的导出,首先要理解模块的含义

    什么是模块?

    模块就是一个JS文件,它实现了一部分功能,并隐藏自己的内部实现,同时提供了一些接口供其他模块使用

    模块有两个核心要素:隐藏暴露

    隐藏的,是自己内部的实现

    暴露的,是希望外部使用的接口

    任何一个正常的模块化标准,都应该默认隐藏模块中的所有实现,而通过一些语法或api调用来暴露接口

    暴露接口的过程即模块的导出

    在这里插入图片描述

    模块的导入

    当需要使用一个模块时,使用的是该模块暴露的部分(导出的部分),隐藏的部分是永远无法使用的。

    当通过某种语法或api去使用一个模块时,这个过程叫做模块的导入

    CommonJS规范

    CommonJS使用exports导出模块,require导入模块

    具体规范如下:

    1. 如果一个JS文件中存在exportsrequire,该JS文件是一个模块
    2. 模块内的所有代码均为隐藏代码,包括全局变量、全局函数,这些全局的内容均不应该对全局变量造成任何污染
    3. 如果一个模块需要暴露一些API提供给外部使用,需要通过exports导出,exports是一个空的对象,你可以为该对象添加任何需要导出的内容
    4. 如果一个模块需要导入其他模块,通过require实现,require是一个函数,传入模块的路径即可返回该模块导出的整个内容

    nodejs对CommonJS的实现

    为了实现CommonJS规范,nodejs对模块做出了以下处理

    1. 为了保证高效的执行,仅加载必要的模块。nodejs只有执行到require函数时才会加载并执行模块

    2. 为了隐藏模块中的代码,nodejs执行模块时,会将模块中的所有代码放置到一个函数中执行,以保证不污染全局变量。

       (function(){
           //模块中的代码
       })()
      
    3. 为了保证顺利的导出模块内容,nodejs做了以下处理

      1. 在模块开始执行前,初始化一个值module.exports = {}
      2. module.exports即模块的导出值
      3. 为了方便开发者便捷的导出,nodejs在初始化完module.exports后,又声明了一个变量exports = module.exports
       (function(module){
           module.exports = {};
           var exports = module.exports;
           //模块中的代码
           return module.exports;
       })()
      
    4. 为了避免反复加载同一个模块,nodejs默认开启了模块缓存,如果加载的模块已经被加载过了,则会自动使用之前的导出结果

    5. nodejs中导入模块,使用相对路径,并且必须以“./”或“…/”开头

    展开全文
  • 本篇文章主要介绍了深入理解Commonjs规范及Node模块实现,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • CommonJs规范 详解

    2020-03-17 21:04:40
    1. CommonJs规范 关于模块: 每个文件就是一个模块,有自己的作用域。在一个文件里面定义的变量、函数、类,都是私有的,对其他文件不可见。 在模块中使用global 定义全局变量,不需要导出,在别的文件中可以访问到...

    CommonJs可以做以下内容:
    1、服务端应用程序
    2、命令行工具
    3、基于桌面的应用程序
    4、混合开发

    1. CommonJs规范

    关于模块:

    • 每个文件就是一个模块,有自己的作用域。在一个文件里面定义的变量、函数、类,都是私有的,对其他文件不可见。
    • 在模块中使用global 定义全局变量,不需要导出,在别的文件中可以访问到。
    • 每个模块内部,module变量代表当前模块。这个变量是一个对象,它的exports属性(即module.exports)是对外的接口
    • 通过 require加载模块,读取并执行一个js文件,然后返回该模块的exports对象
    • 所有代码都运行在模块作用域,不会污染全局作用域。
    • 模块可以多次加载,但是只会在第一次加载时运行一次,然后运行结果就被缓存了,以后再加载,就直接读取缓存结果。要想让模块再次运行,必须清除缓存。
    • 模块加载的顺序,按照其在代码中出现的顺序

    2. module对象

    node内部提供一个Module构建函数。所有的模块其实都是Module的实例。

    每一个模块内部,都有一个Module对象,代表当前模块。它有以下属性:

    • module.id,模块的识别符,通常是带有绝对路径的模块文件名;
    • module.filename,模块的文件名,带有绝对路径;
    • module.loaded,返回一个boolean值,表示模块是否已经完成加载;
    • module.parent,返回一个对象,表示调用该模块的模块;
    • module.children,返回一个数组,表示该模块内用到的其他模块;
    • module.exports,表示模块对外输出的值;

    下图中打印module的结果:
    commonJs

    2.1 module.exports属性和exports变量

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

    为了方便,node为每一个模块提供了一个exports变量,指向module.exports。这等同在每个模块头部,有一条这样的命令。

    var exports = module.exports;
    

    所以我们在对外输出模块接口时,可以向exports对象中添加方法或者属性。下面这么写都是可以的。

    module.exports.name = "zhangsan";
    exports.name = 'lisi'
    exports.age = 18;
    

    但是注意,不可以直接将exports变量指向一个值,因为这样等于切断了exports和module.exports的联系。这意味着,如果一个模块的对外接口,是一个单一的值,这种情况就不能使用exports输出,只能使用module.exports输出。

    exports = "lisi"; //错误的
    exports = function(){return "lisi"}; //错误的
    

    下面这种写法中,hello函数是无法对外输出的,因为module.exports被重新赋值了

    exports.hello = function() {
      return 'hello';
    };
    module.exports = 'Hello world';
    

    如果你觉得exports 和 module.exports 之间的区别很难分清,一个简单的处理方法,就是放弃使用exports ,只使用 module.exports。

    3. require

    require命令用于加载模块文件。它的基本功能是,读取并执行一个Javascript文件,然后返回该模块的exports对象。如果没有发现指定模块,会报错。

    CommonJS模块的加载机制是,输入的是被输出的值的拷贝。也就是说,一旦输出一个值,模块内部的变化就影响不到这个值。

    3.1 require的内部处理流程

    当使用require加载模块时,在node内部,会做如下处理:

    1. 先检查Moducle._cache, 看里面有没有对应模块的缓存;
    2. 如果缓存没有的话,就创建一个新的module实例,并把它添加到缓存中,缓存的是它exports导出的值;
    3. 如果缓存中有的话,使用module.load()这个方法,去加载这个模块,读取文件内容后,使用module.compile()执行文件代码;
    4. 如果解析的过程中,出现异常,就从缓存中删除这个模块;
    5. 如果没有出现异常,最后返回这个模块的module.exports;

    require命令用于加载文件,后缀名默认为.js

    var user = require('./user');
    //等同于
    var user = require('./user.js');
    

    3.1 加载规则

    根据参数的不同格式,require命令会去不同路径寻找模块文件。

    1. 如果参数字符串以“/”开头,表示加载的是一个位于绝对路径的模块文件。
    2. 如果参数字符串以“./”开头,表示加载的是一个位于相对路径(跟当前执行脚本的位置相比)的模块文件。
    3. 如果参数字符串不以“/”或者“./”开头,则表示加载的是一个默认提供的核心模块(位于Node的系统安装目录中),或者一个位于各级node_modules目录的已安装模块(全局安装或局部安装)。
    4. 如果参数字符串不以“/”或者“./”开头,而是一个路径,则会先找到该路径目录,然后再以它为参数找到后续路径。
    5. 如果指定的模块文件没有被发现,Node会尝试为文件添加.js、.json、.node后,再去搜索。.js文件会以文本格式的javascript脚本文件解析,.json文件会以JSON格式的文本文件解析,.node文件会以编译后的二进制文件解析。
    6. 如果想得到require命令加载的确切文件名,使用require.resolve()方法。

    3.2 模块的缓存

    第一次加载某个模块时,Node会缓存该模块。以后再加载该模块,就直接从缓存取出该模块的module.exports属性。

    3.2.1 模块缓存的案例1

    require('./user.js');
    require('./user.js').message = "hello";
    require('./user.js').message
    // "hello"
    

    上面代码中,连续三次使用require命令,加载同一个模块。第二次加载的时候,为输出的对象添加了一个message属性。但是第三次加载的时候,这个message属性依然存在,这就证明require命令并没有重新加载模块文件,而是输出了缓存。

    3.2.1 模块缓存的案例2

    再来看下面这个案例:

    // a.js
    exports.x = 'a1';
    console.log('a.js ', require('./b.js').x);
    exports.x = 'a2';
    
    // b.js
    exports.x = 'b1';
    console.log('b.js ', require('./a.js').x);
    exports.x = 'b2';
    
    // main.js
    console.log('main.js ', require('./a.js').x);
    console.log('main.js ', require('./b.js').x);
    

    上面的例子中,当执行main.js时,加载了a.js,先输出x为a1,又加载了b.js,b.js中输出x为b1,又加载a.js,此时因为之前已经加载过a.js了,所以直接从缓存中读取,a.js的x为a1,所以先打印出"b.js a1";然后b.js输出x为b2,所以a.js中打印“a.js b2",然后a.js中又输出x为a2;所以main.js中打印”main.js a2",第二次再打印的时候,因为a.js和b.js都已经被缓存了,所以直接读取它们的exports的值,所以直接打印出“main.js b2"。
    commonjs
    所有缓存的模块保存在require.cache之中,如果想删除模块的缓存,可以像下面这样写。

    // 删除指定模块的缓存
    delete require.cache[moduleName];
    
    // 删除所有模块的缓存
    Object.keys(require.cache).forEach(function(key) {
      delete require.cache[key];
    })
    

    注意:缓存是根据绝对路径识别模块的,如果同样的模块名,但是保存在不同的路径,require命令还是会重新加载该模块。

    3.2.3 require.main

    require方法有一个main属性,可以用来判断模块是直接执行,还是被调用执行。
    直接执行的时候(node module.js),require.main属性指向模块本身。

    require.main === module
    // true
    

    调用执行的时候(通过require加载该脚本执行),上面的表达式返回false。

    4. 深入了解模块原理

    hello.js

    var s = 'Hello';
    var name = 'world';
    console.log(s + ' ' + name + '!');
    

    Node.js加载了hello.js后,它可以把代码包装一下,变成这样执行:

    (function () {
        // 读取的hello.js代码:
        var s = 'Hello';
        var name = 'world';
        console.log(s + ' ' + name + '!');
        // hello.js代码结束
    })();
    

    这样一来,原来的全局变量s现在变成了匿名函数内部的局部变量。如果Node.js继续加载其他模块,这些模块中定义的“全局”变量s也互不干扰。

    所以,Node利用JavaScript的函数式编程的特性,轻而易举地实现了模块的隔离。

    但是,模块的输出module.exports怎么实现?

    这个也很容易实现,Node可以先准备一个对象module:

    // 准备module对象:
    var module = {
        id: 'hello',
        exports: {}
    };
    var load = function (module) {
        // 读取的hello.js代码:
        function greet(name) {
            console.log('Hello, ' + name + '!');
        }
        
        module.exports = greet;
        // hello.js代码结束
        return module.exports;
    };
    
    var exported = load(module);
    var exports= module.exports;
    //exports="hellworld"; 错误
    // 保存module:
    save(module, exported);
    

    可见,变量module是Node在加载js文件前准备的一个变量,并将其传入加载函数,我们在hello.js中可以直接使用变量module原因就在于它实际上是函数的一个参数:

    module.exports = greet;
    

    通过把参数module传递给load()函数,hello.js就顺利地把一个变量传递给了Node执行环境,Node会把module变量保存到某个地方。

    由于Node保存了所有导入的module,当我们用require()获取module时,Node找到对应的module,把这个module的exports变量返回,这样,另一个模块就顺利拿到了模块的输出。

    参考链接:https://javascript.ruanyifeng.com/nodejs/module.html

    展开全文
  • AMD是RequireJS在推广过程中对模块定义的规范化产出,它是一个概念。 RequireJS是对AMD概念的实现,就好比JavaScript语言是对ECMAScript规范的实现。 RequireJS解决了什么问题? js加载会阻塞网页渲染,加载...

    AMD-异步模块定义

    AMD是RequireJS在推广过程中对模块定义的规范化产出,它是一个概念。

    RequireJS是对AMD概念的实现,就好比JavaScript语言是对ECMAScript规范的实现。

    RequireJS解决了什么问题?

    1. js加载会阻塞网页渲染,加载文件越多,网页失去响应的时间就会越长。

    2. js文件之间存在依赖关系,因此必须严格保证加载顺序,代码的编写和维护都会变得困难。

    require.js的诞生,就是为了解决这两个问题。

    用法

    1.加载require.js,一个是把它放在网页底部加载,另一个是写成下面这样:

    代码块

     
     
     <script src="js/require.js" defer async="true" ></script>

    async属性表明这个文件需要异步加载,避免网页失去响应。IE不支持这个属性,只支持defer,所以把defer也写上。

    2.假定我们自己的代码文件是main.js,那么,只需要写成下面这样就行了:

    代码块

     
     
    <script src="js/require.js" data-main="js/main"></script>

    data-main属性的作用是,指定网页程序的主模块。由于require.js默认的文件后缀名是js,所以可以把main.js简写成main。

    3.常见的情况是,主模块依赖于其他模块,这时就要使用AMD规范定义的的require()函数。

    代码块

     
     
    // main.js
    require(['moduleA', 'moduleB', 'moduleC'], function (moduleA, moduleB, moduleC){
      // some code here
    });

    require()函数接受两个参数。第一个参数是一个数组,表示所依赖的模块,上例就是['moduleA', 'moduleB', 'moduleC'],即主模块依赖这三个模块;第二个参数是一个回调函数,当前面指定的模块都加载成功后,它将被调用。加载的模块会以参数形式传入该函数,从而在回调函数内部就可以使用这些模块。

    4.require.js加载的模块,采用AMD规范。也就是说,模块必须按照AMD的规定来写。具体来说,就是模块必须采用特定的define()函数来定义。如果一个模块不依赖其他模块,那么可以直接定义在define()函数之中。

    ⚠️ 注意:只是模块要用define函数定义,main文件用require。

    假定现在有一个math.js文件,它定义了一个math模块。那么,math.js就要这样写:

    代码块

     
     
    // math.js
    define(function (){
      var add = function (x,y){
        return x+y;
      };
      return {
        add: add
      };
    });

    如果这个模块还依赖其他模块,那么define()函数的第一个参数,必须是一个数组,指明该模块的依赖性。当require()函数加载上面这个模块的时候,就会先加载myLib.js文件。

    代码块

     
     
    define(['myLib'], function(myLib){
      function foo(){
        myLib.doSomething();
      }
      return {
        foo : foo
      };
    });

    CMD-同步模块定义

    CMD---SeaJS在推广过程中对模块定义的规范化产出,是一个同步模块定义,是SeaJS的一个标准,SeaJS是CMD概念的一个实现,SeaJS是淘宝团队提供的一个模块开发的js框架。

    和requireJS相似的,seaJS 也是用JavaScript编写的JS框架,主要功能是可以按不同的先后依赖关系对 JavaScript 等文件的进行加载工作,可简单理解为JS文件的加载器,确保各个JS文件的先后加载顺序,确保避免了以前因某些原因某个文件加载慢而导致其它加载快的文件需要依赖其某些功能而出现某函数或某变量找不到的问题。

    用法

    1.在 hello.html 页尾,通过 script 引入 sea.js 并配置后,这样加载入口模块:

    代码块

     
     
    seajs.use("../static/hello/src/main")

    2.main文件和模块文件遵循统一的写法:

    代码块

     
     
    // 所有模块都通过 define 来定义
    define(function(require, exports, module) {
      // 通过 require 引入依赖
      var $ = require('jquery');
      var Spinning = require('./spinning');
      // 通过 exports 对外提供接口
      exports.doSomething = ...
      // 或者通过 module.exports 提供整个接口
      module.exports = ...
    });

    CMD是依赖就近,在什么地方使用到插件就在什么地方require该插件,即用即返,是这么一个同步的概念。

    ES6模块化特性

    在es6之前的javascript中是没有模块化概念的。自从有了这个特性,可以预见AMD和CMD将退出历史舞台,毕竟这是需要引入第三方类库实现的。

    在ES6中每一个模块即是一个文件,在文件中定义的变量,函数,对象在外部是无法获取的。如果你希望外部可以读取模块当中的内容,就必须使用export来对其进行暴露(输出)。以import的形式将这个变量进行引入。

    CommonJS规范

    实际上在前端浏览器里面并不支持module.exports,即模块化,前端浏览器一般使用AMD、CMD、ES6等定义模块化开发的。Nodejs端是使用CommonJS规范的,CommonJS规范---是通过module.exports定义的。

    node应用由模块组成,采用的commonjs模块规范。每一个文件就是一个模块,内容对其他的模块都不可见。

    CommonJS规范规定,每个模块内部,module变量代表当前模块。这个变量是一个对象,它的exports属性(即module.exports)是对外的接口。加载某个模块,其实是加载该模块的module.exports属性。require方法用于加载模块。

    展开全文
  • 浅谈CommonJs规范和Es6模块化

    千次阅读 2022-03-20 22:13:22
    (1)CommonJS规范是一种同步加载模块的方式,也就是说,只有当模块加载完成后,才能执行后面的操作。由于Nodejs主要用于服务器端编程,而模块文件一般都已经存在于本地硬盘,加载起来比较快, 因此同步加载模块的...
  • 下面小编就为大家分享一篇浅析AMD CMD CommonJS规范--javascript模块化加载学习心得总结。小编觉得写的非常不错,需要的朋友可以过来参考一下
  • 前不久 面试碰见了一个问题 请说下 export 和 ...在规范没出来之前 假设 每个人都有一个自己的 接口导出规范 每个公司有自己的模块导出规范 那么 js 就成什么 了 不是乱套了吗 不过肯定会有几个模块规范 会脱颖而...
  • 逼不得已,又熟悉了一波CommonJS规范,这里必须得感谢像阮一峰这样的大佬们(先驱们),在中国互联网迅速发展的大环境中,这些为我们指路的人,是值得尊敬的。 温故而知新,获益匪浅。CommonJS的规范制定是很有必要...
  • 首先,CommonJS规范的特点: 对于基本数据类型,属于复制。即会被模块缓存。同时,在另一个模块可以对该模块输出的变量重新赋值。 对于复杂数据类型,属于浅拷贝。由于两个模块引用的对象指向同一个内存空间,因此...
  • commonJS规范

    2017-03-27 22:21:00
    CommonJS 规范是为了解决 JavaScript 的作用域问题而定义的模块形式,可以使每个模块它自身的命名空间中执行。该规范的主要内容是,模块必须通过module.exports导出对外的变量或接口,通过require()来导入其他模块的...
  • 4、服务端向前端进军 Modules/1.0规范源于服务端,无法直接用于浏览器端,原因表现为: 1. 外层没有function包裹,变量全暴漏在全局。如上面例子中increment.js中的add。 2. 资源的加载方式与服务端完全不同。...
  • 一文搞懂CommonJs规范

    2021-11-29 22:21:33
    一文搞懂CommonJs规范,下次吹牛时这么说
  • 因此,需要将commonJS规范和ES6的模块规范区分开来。 一、为什么制定CommonJS规范? 在后端,JavaScript的规范远远落后并且有很多缺陷,这使得难以使用JavaScript开发大型应用。比如: 没有模块系统 标准库较少 ...
  • commonjs规范是什么?

    2021-01-28 21:55:30
    Node 应用由模块组成,采用 CommonJS 模块规范。 每个文件就是一个模块,有自己的作用域。在一个文件里面定义的变量、函数、类,都是私有的,对其他文件不可见。 // example.js var x = 5; var addX = function ...
  • commonJs规范,ES6规范 区别 和使用 commonJs规范: exports module.exports require() ES6规范: export export default {} import xxx from './components' import { xxx } from './components' @import "
  • webpack源码分析—模块的导入与导出详解前言CommonJS规范的导入和导出导入导出总结 前言 上一章我们说了webpack打包后代码的一个整体分析,这一章我们来详细说一下webpack打包后的代码是如何实现模块的导入和导出的...
  • js代码-面试题7:实现node内置CommonJS规范

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 22,026
精华内容 8,810
关键字:

commonjs规范

友情链接: Project44.zip