zoukankan      html  css  js  c++  java
  • ES6的模块化语法

    ES6的模块化语法

    在模块化被写入 ECMAScript 标准之前, 已经存在各种模块化的实现方式和对应的语法, 例如 AMD, CMD, commonJS 等. 本文只讨论 ES6 标准下的模块化语法.

    模块化的必要性

    当我们希望全局作用域更加干净,而不是到处都有命名冲突之类的问题;

    当我们希望一段代码拥有自己的作用域, 而且不要被其他代码所污染;

    当我们希望自己的程序更加井然有序;

    当......

    这也是 ES6 希望解决的问题, 所以将模块化定为了标准.

    模块的概念

    模块是一段JavaScript代码, 这段代码会自动运行、而且是在严格模式下、并且无法退出运行。

    模块的特点

    • 模块内定义的变量不会被自动添加到全局作用域
    • 由于上面的原因, 模块要向外面暴露一些自己的数据, 这些数据可以被外界访问到
    • 一个模块可以从另外一个模块中导入数据(即可以使用其他模块的数据)
    • 模块顶层的 this 是 undefined, 并不是 window 或 global

    模块和脚本的区别

    模块和脚本初看起来很相似, 他们都可以存在一个单独的文件中, 都可以被其他模块(脚本)引入, 也可以引入其他模块(脚本)的数据, 似乎很难说出他们之间的区别.

    但是其实他们的区别非常明显, 用一句话就可以概括: 我们可以按需导入模块中的数据, 但是不能按需导入脚本中的数据。

    对于脚本,我们一旦导入了它, 就会将脚本中的所有数据全都导入到了全局作用域中, 这样看起来还是挺乱的。

    而对于模块, 则可以只导入我们需要的数据。虽然一个模块可能会暴露出很多的变量、函数和对象, 但我们可以只把需要的那一部分导入进来使用。

    从其他模块导入数据和将模块中的数据暴露出去给其他模块的语法 export 和 import

    将模块中的数据暴露(导出)给其他模块 export

    将模块中的数据暴露给其他模块使用的语法有两种, 分别如下:

    1. 先定义一个值,然后将其暴露出去
    
    // 定义一个变量
    let name = 'doug';
    // 暴露这个变量
    export name;
    
    // 定义一个函数
    function say(){
        console.log('hello ' + name);
    }
    // 暴露这个函数
    export say;
    
    // 定义一个类
    class Student {
        constructor(name, age){
            this.name = name;
            this.age = age;
        }
    }
    // 暴露这个类
    export Student;
    
    // 定义一个函数,而且不把它暴露出去
    function privateFunc(){
        console.log('我是私有成员,没有被暴露出去,所以别人没有办法访问到我');
    }
    

    上面的操作可以分为两个过程, 先定义、再暴露。其实可以简化为一句代码: 2. 在定义变量的同时暴露数据, 只要在声明符之前加上 export 就可以.

    // 定义一个变量并暴露
    export let name = 'doug';
    
    // 定义一个函数并暴露
    export function say(){
        console.log('hello ' + name);
    }
    
    // 定义一个类并暴露
    export class Student {
        constructor(name, age){
            this.name = name;
            this.age = age;
        }
    }
    
    // 定义一个函数,并不把它暴露出去, 其他模块从外部无法访问这个函数
    function privateFunc(){
        console.log('我是私有成员,没有被暴露出去,所以别人没有办法访问到我');
    }
    

    注意, 不暴露出去的数据是从外部访问不到的, 例如上面例子中的 privateFunc 函数.

    从别的模块导入数据 import

    从别的模块得到数据以供自己使用, 要用 import 关键字。在导入之前, 要先明确两个问题: 一是从哪个模块导入? 二是想导入模块中的什么数据?

    在明确从哪导入和导入什么之后,就可以按照下面的语法来写了:

    import { 数据1, 数据2, ... , 数据n } from 模块名
    

    例如,从 a 模块中导入 name 变量 和 say 函数:

    import { name, say } from './a.js';
    

    这样就把 name 和 say 从 a 模块导入进本模块中了,现在就可以使用它们了, 例如输出 name 的值, 或者调用 say 这个函数:

    console.log(name);
    
    say();
    

    关于导入的注意事项

    导入的数据是没有办法直接改变的。比如,我们无法直接给 name 重新赋值, 这样会报错。

    import { name } from './a.js';
    
    name = 'new name';  // Error 错误
    

    但是可以间接的修改这个变量的值. 假如在模块 a 中定义了一个可以修改 name 值的函数, 则可以通过调用这个函数来修改 name 的值了. a 模块中的内容:

    ... 包括 name 在内的其他数据
    
    function updateName(newName){
        name = newName;
    }
    

    导入 a模块的 updateName 函数来修改 name 的值:

    import { name, updateName } from './a.js';
    
    updateName('new Name'); // name的值已经被修改为了 "new name"
    

    一次性导入一个模块暴露出来的所有数据

    当想用一行代码导入一个模块暴露出来的所有数据时, 用上面的方法可能比较困难, 因为一个模块暴露出来的方法可能很多, 把每个变量名都写出来的方法就不够灵活了.

    这个时候可以用命名空间导入的方法, 即将一个模块暴露出来的所有的数据挂载到一个对象上,通过这个对象来调用这些数据, 例如:

    import * as aObj from './a.js'; // a 模块所有暴露出的数据都挂到了 aObj 上
    
    // 通过 aObj 来访问和调用 a 模块中的变量和方法
    console.log(aObj.name);
    aObj.say();
    

    使用 as 对导入和要暴露出去的数据重命名

    如果想将数据以别的名称暴露出去, 可以使用 as 关键字, 语法为: export { 原名称 as 新名称 } .

    这样在其他模块中就可以用这个新的名称来导入这个数据了, 例如将函数 say 以 speak 为名称暴露出去:

    export {say as speak};
    

    那么其他模块就要用 speak 来导入这个函数了: import { speak } from './a.js'

    在导入一个数据时, 也可以对它重命名, 并使用重命名之后的名称来访问它, 例如将它命名为 Howling, 之后就可以使用 howling 来访问这个函数了:

    import { speak as howling} from './a.js';  // 导入时重命名
    
    howling(); // 用新名字调用这个函数
    

    将一个值作为默认值暴露出去 default

    每个模块可以将一个变量、函数或者类作为默认值暴露出去.

    将一个值作为默认值暴露出去的语法有3种,分别是:

    1. 定义的时候就暴露
    2. 先定义后暴露
    3. 将这个值用 as 命名为 default 后暴露
    // 1. 定义的时候就暴露
    export default function(){
        console.log('方法1暴露函数为默认值');
    }
    
    // 2. 先定义后暴露
    let name = 'doug';
    export default name;
    
    // 3. 将这个值用 as 命名为 default 暴露
    class Student{ // ... }
    export {Student as default};
    

    导入其他模块暴露出的默认值

    导入默认值的语法和导入非默认值的语法略有不同. 导入一个模块暴露出的默认值, 并不用 {} 来包裹, 而且不用使用 as 关键字就可以将这个默认值重命名: 例如导入上面例子中的 name, 并将其重命名为 familyName

    import familyName from './a.js';
    

    同时导入默认值和非默认值的语法

    在一行语句中同时导入默认值和非默认值的语法非常简单, 就是将这两种导入的方式结合起来, 非默认值用{}括起来, 而默认值不用. 语法为:

    import 默认值 { 非默认值 } from './a.js';
    

    将从其他模块导入的数据暴露出去

    有时候需要将从其他模块导入的某些数据再暴露出去, 这有两种语法

    1. 先导入, 再暴露
    import { name } from './a.js';   // 导入
    
    export {name};   // 暴露
    
    1. 一行代码之内同时导入和暴露
    export { name } from './a.js';
    

    也可以重命名后再暴露出去

    export { name as lastName } from './a.js';
    

    #完. 文章或有疏漏之处, 欢迎指正.

    在模块化被写入 ECMAScript 标准之前, 已经存在各种模块化的实现方式和对应的语法, 例如 AMD, CMD, commonJS 等. 后面的文章会对这些标准进行对比.

    来源:https://juejin.cn/post/6844903810549170190

  • 相关阅读:
    Asp.net 默认配置下,Session莫名丢失的原因及解决办法
    回发或回调参数无效。在配置中使用 enableEventValidation=true或在页面中使用 启用了事件验证。
    SQL Server事务日志意外增大的处理方法
    SQLServer数据库设计表和字段(转)
    关于SQL Server数据库设计的感悟
    如何动手组建WiFi网络
    教你在SQL Server数据库中设计表和字段
    SQL Server数据库设计表和字段的经验
    SQL Server 的通用分页显示存储过程
    翻译: jQuery1.4官方文档
  • 原文地址:https://www.cnblogs.com/nxmxl/p/14900814.html
Copyright © 2011-2022 走看看