美文网首页
Module的加载实现

Module的加载实现

作者: Rules_5de5 | 来源:发表于2017-11-02 11:32 被阅读0次

    浏览器加载

    标签的async属性也可以打开,这时只要加载完成,渲染引擎就会中断渲染立即执行。执行完成后,再恢复渲染。

    ES6模块允许内嵌在网页中,语法行为与加载外部脚本一致;

    importutils from"./utils.js";// other code

    外部的模块脚本(foo.js),有几点需要注意:

    (1) 代码是在模块作用域之中运行,而不是在全局作用域运行,模块内部的顶层变量,外部不可见。

    (2) 模块之中,可以使用import命令加载其他模块(.js后缀不可省略,也可以使用export命令输出对外接口)

    (3)模块之中,顶层的this关键字返回undefined,而不是指向window,也就是说:在模块顶层使用this关键字是无意义的;

    (4)同一个模块如果加载多次只执行一次;

    //实例模块importutilsfrom"https://www.baidu.com/js/utils.js";constx=1;console.log(x===window)// falseconsole.log(this===undefined)//truedeletex;//语法错误,不能删除x

    利用顶层的this等于undefined这个语法点,可以侦测当前代码是否在 ES6 模块之中。

    constisNotModuleScript=this!==undefined;

    ES6模块与CommonJS模块的差异

    (1)CommonJS模块输出的是一个值的拷贝,ES6模块输出得失值的引用;

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

    CommonJS模块输出的是值的拷贝,也就是说一旦输出一个值,模块内部的变化就影响不到这个值;

    //lib.jsvarcounter=3;functioninCounter(){counter++;}module.exports={counter:counter,inCounter:inCounter,};//在main.js里面加载这个模块varmod=require(".lib");console.log(mod.counter);//3mod.inCounter();console.log(mod.counter);//3

    lib.js模块加载以后,他的内部变化就影响不到输出的mod.counter了,这是因为mod.counter是一个元素类型的值;

    ES6模块的运行机制与CommonJS不一样,js引擎对脚本静态分析的时候,遇到模块加载命令import,就会生成一个只读引用。等到脚本真正执行时,再根据这个只读引用,到被加载的那个模块里面去取值。原始值变了,import加载的值也会跟着变。因此,ES6 模块是动态引用,并且不会缓存值,模块里面的变量绑定其所在的模块。

    //lib.jsexportlet counter=3;exportfunctioninCounter(){counter++;}//main.jsimport{counter,inCounter}from"./lib";console.log(counter);//3inCounter();console.log(counter);//4

    ES6 模块输入的变量counter是活的,完全反应其所在模块lib.js内部的变化。

    内部变量

    ES6 模块应该是通用的,同一个模块不用修改,就可以用在浏览器环境和服务器环境。为了达到这个目标,Node 规定 ES6 模块之中不能使用 CommonJS 模块的特有的一些内部变量。

    首先,就是this关键字。ES6 模块之中,顶层的this指向undefined;CommonJS 模块的顶层this指向当前模块,这是两者的一个重大差异。

    其次,以下这些顶层变量在 ES6 模块之中都是不存在的。

    arguments

    require

    module

    exports

    filename

    dirname

    CommonJS模块的加载原理

    CommonJS的一个模块,就是一个脚本文件,require命令第一次加载该脚本,就会执行这个脚本,然后在内存生成一个对象。

    {id:"...",exports:{...},loaded:true,...}

    Node内部加载模块后生成的一个对象,该对象的id属性是模块名,exports属性是模块输出的各个接口,loaded属性是一个布尔值,表示该模板的脚本是否执行完毕,等等属性;

    以后需要用到这个模块的时候就会到export属性上面取值,即使再次执行require命令,也不会再次执行该模块,而是到缓存之中取值,也就是说:CommonJS模块无论加载多少次,只在第一次加载时运行一次,以后再加载,就返回第一次运行的结果;

    作者: MGT360124

    链接:http://www.imooc.com/article/20630?block_id=tuijian_wz

    转载来源:慕课网

    相关文章

      网友评论

          本文标题:Module的加载实现

          本文链接:https://www.haomeiwen.com/subject/slsopxtx.html