ES6之模块入门(一)

    ES6以前,一个Web应用的每一个JS文件所定义的全部内容都由全局做用域共享。当Web应用变得愈来愈复杂,须要更多的JS代码时,此种方式会致使命名冲突、安全等不少问题。javascript

    如何解决?html

    ES6的设计目标之一就是要解决做用域问题,并让JS应用变得更有调理。 这即是模块的切入点。java

 

  1. 什么是模块(What are Modules)?

    Modules are JavaScript files that are loaded in a different mode (as opposed to scripts, which are loaded in the original way JavaScript worked).

    模块( Modules )是使用不一样方式加载的 JS 文件(与 JS 原先的脚本加载方式相对)es6

    简单来讲,能够认为一个模块就是一个js文件,该模块中有变量、函数、类。

    →模块(Modules)与脚本(Script)的语义有很大的不一样:

      一、模块代码自动运行在严格模式下,而且没有任何办法跳出严格模式;

      二、在模块的顶级做用域建立的变量,不会自动添加到共享的全局做用域,它们只会在模块顶级做用域的内部存在

           三、模块顶级做用域的this值为undefined

           四、模块不容许在代码中使用HTML风格的注释;

           五、对于须要让模块外部访问的内容,模块必须导出它们;

           六、容许模块从其余模块导入绑定;

    web

    咱们这里定义一个模块文件(calc.js)放到modules目录下,内容以下:
    function add(a, b) {
        return a + b;
    }
    
    function sub(a, b) {
        return a - b;
    }
    
    function multi(a, b) {
        return a * b;
    }
    
    function divide(a, b) {
        return a / b;
    }
    //先定义,后导出
    export { add, sub, multi, divide }

     

  2. 如何加载模块?
    ES6规范中定义了模块的语法以及抽象的加载机制,但没有定义如何加载他们,所以具体的实现环境(例如web浏览器、Node.js)能够自行决定用什么方式实现,以便契合各自的环境。

    →在Web浏览器中使用模块(使用script标签)

    方式一:
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <!--告诉浏览器 要将内联代码当作模块,这是一个直接嵌入到网页内的模块-->
        <script type="module">
            import { add, sub, multi, divide } from './modules/calc.js';
    
            let result = add(10, 20);
            console.log('result=' + result);
        </script>
    </head>
    <body>
    </body>
    </html>

    在这里,result变量没有暴露到全局,由于它只在<script>元素定义的这个模块内部存在,所以也没有被添加为window对象的属性。浏览器

    输出结果为:
    安全


    方式二:
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <!--告诉浏览器 要将指定文件中的代码当作模块,而不是当作脚本,这里使用src加载了外部模块文件-->
        <script type="module" src="./modules/calc.js"></script>
    </head>
    <body>
        
    </body>
    </html>

     



  3. 模块加载次序

    模块相对脚本的独特之处在于:它们能使用 import 来指定必需要加载的其余文件,以保证正确执行。为了支持此功能, <script type="module"> 老是表现得像是已经应用了 defer 属性。ide

    defer 属性是加载脚本文件时的可选项,但在加载模块文件时老是自动应用的。当 HTML 解析到拥有 src 属性的 <script type="module"> 标签时,就会当即开始下载模块文件,但并不会执行它,直到整个网页文档所有解析完为止。
    模块也会按照它们在 HTML 文件中出现的顺序依次执行,这意味着第一个 <script type="module"> 老是保证在第二个以前执行,即便其中有些模块不是用 src 指定而是包含了内联脚本。函数

    例如:
    第一步:新建一个模块foo.js在modules目录下,foo.js内容以下:测试

    function hello(){
        console.log('foo.hello...');
    }
    
    console.log('foo.js模块执行了');

    第二步:新建测试网页foo.html,内容以下:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <!--外部文件方式加载模块-->
        <!--first执行-->
        <script type="module" src="./modules/foo.js"></script>
        <!--second执行-->
        <script type="module">
            console.log('second模块执行了...');
        </script>
        
    </head>
    <body>
        <h1>Foo</h1>
        <script type="text/javascript">
            //模拟加载数据耗时2秒
            setTimeout(() => {
                console.log('网页模拟加载数据执行了...');
            }, 2000);
        </script>
    
        <!--third执行-->
        <script type="module">
            console.log('third模块执行了...');
        </script>
    </body>
    </html>

    观察执行结果:

     

     

     

  4. 总结

    ES6 为 JS 语言添加了模块,做为打包与封装功能的方式。

    模块的行为异于脚本,它们不会用自身顶级做用域的变量、函数或类去修改全局做用域,而模块的 this 值为 undefined 。为了实现这些行为,模块在被加载时使用了一种不一样的方式。

    你必须将模块中须要向外提供的任何功能都导出,变量、函数与类均可以,而且每一个模块容许存在一个默认导出。
    在导出以后,另外一个模块就能导入该模块所导出的一个或多个名称了。这些导入的名称就像是被 let 所定义的,会被看成块级绑定,而且不允在同一模块内重复声明。


    因为模块必须用与脚本不一样的方式运行,浏览器就引入了 <script type="module"> ,以表示资源文件或内联代码须要做为模块来执行。


    使用 <script type="module"> 加载的模块文件会默认应用 defer 属性。一旦包含模块的页面文档彻底被解析,模块就会按照它们在文档中的出现顺序依次执行。

 

 

参考资料:《Understanding ECMAScript 6》,做者:Nicholas C. Zakas ,在线阅读地址:https://leanpub.com/understandinges6/read#leanpub-auto-what-are-modules

相关文章
相关标签/搜索