• [转]模块化——Common规范及Node模块实现(二)


    模块的循环加载

    如果发生模块的循环加载,即A加载B,B又加载A,则B将加载A的不完整版本。

    // 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);

    上面代码是三个JavaScript文件。其中,a.js加载了b.js,而b.js又加载a.js。这时,Node返回a.js的不完整版本,所以执行结果如下。

    修改main.js,再次加载a.js和b.js。

    // main.js
    console.log('main.js ', require('./a.js').x);
    console.log('main.js ', require('./b.js').x);
    console.log('main.js ', require('./a.js').x);
    console.log('main.js ', require('./b.js').x);

    执行上面代码,结果如下。

    
    

    上面代码中,第二次加载a.js和b.js时,会直接从缓存读取exports属性,所以a.js和b.js内部的console.log语句都不会执行了。

    require.main

    require方法有一个main属性,可以用来判断模块是直接执行还是被调用执行

    直接执行的时候(node module.js),require.main属性指向模块本身。

    
    

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

    模块的加载机制

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

    下面是一个模块文件lib.js

    // lib.js
    var counter = 3;
    function incCounter() {
      counter++;
    }
    module.exports = {
      counter: counter,
      incCounter: incCounter,
    };

    上面代码输出内部变量counter和改写这个变量的内部方法incCounter

    然后,加载上面的模块。

    // main.js
    var counter = require('./lib').counter;
    var incCounter = require('./lib').incCounter;
    
    console.log(counter);  // 3
    incCounter();
    console.log(counter); // 3

    上面代码说明,counter输出以后,lib.js模块内部的变化就影响不到counter了。

    require的内部处理流程

    require命令是CommonJS规范之中,用来加载其他模块的命令。它其实不是一个全局命令,而是指向当前模块的 module.require 命令,而后者调用Node的内部命令Module._load

    上面的第4步,采用module.compile()执行指定模块的脚本,逻辑如下。

    上面的第1步和第2步,require函数及其辅助方法主要如下。

    一旦require函数准备完毕,整个所要加载的脚本内容,就被放到一个新的函数之中,这样可以避免污染全局环境。该函数的参数包括requiremoduleexports,以及其他一些参数。

    (function (exports, require, module, __filename, __dirname) {
      // YOUR CODE INJECTED HERE!
    });

    Module._compile方法是同步执行的,所以Module._load要等它执行完成,才会向用户返回module.exports的值。

  • 相关阅读:
    2017年10月9日 冒泡&去重复习
    2017 年9月29日 弹出层特效
    2017 年9月28日 三级联动
    2017 年 9 月 27 日 js(文本框内容添加到select)
    2017 年 9 月 27 日 js(1.两个select 内容互换 2.单选按钮 同意可点击下一步 3. 全选框)
    2017 年 9 月26 日
    linux运维的认知及RHEL7 Unix/Linux 系统 介绍和安装
    Zabbix配置文件详解之服务端zabbix_server
    LoadRunner安装+汉化+破解
    zabbix告警“Zabbix poller processes more than 75% busy”
  • 原文地址:https://www.cnblogs.com/xuzhudong/p/8947837.html
Copyright © 2020-2023  润新知