ES6 模块加载export 、import、export default 、import() 语法与区别,笔记总结

ES6模块加载export 、import、export default 、import() 语法与区别
在 ES6 之前,社区制定了一些模块加载方案,最主要的有 CommonJS 和 AMD 两种。
CommonJS 用于服务器,AMD 用于浏览器。
ES6 在语言标准层面上,实现了模块功能,而且简单,完全可以取代 CommonJS 和 AMD 规范,成为浏览器和服务器通用的模块解决方案。

ES6 的模块自动采用严格模式,不管你有没有在模块头部加上"use strict";。
严格模式主要有以下限制。
变量必须声明后再使用
函数的参数不能有同名属性,否则报错
不能使用with语句
不能对只读属性赋值,否则报错
不能使用前缀 0 表示八进制数,否则报错
不能删除不可删除的属性,否则报错
不能删除变量delete prop,会报错,只能删除属性delete global[prop]
eval不会在它的外层作用域引入变量
eval和arguments不能被重新赋值
arguments不会自动反映函数参数的变化
不能使用arguments.callee
不能使用arguments.caller
禁止this指向全局对象
不能使用fn.caller和fn.arguments获取函数调用的堆栈
增加了保留字(比如protected、static和interface)
上面这些限制,模块都必须遵守。由于严格模式是 ES5 引入的,不属于 ES6,所以请参阅相关 ES5 书籍。

其中,尤其需要注意this的限制。ES6 模块之中,顶层的this指向undefined,即不应该在顶层代码使用this。

//index.js
//export 命令
            var a = 'a';
            var b = 'b';
            var c = 'c';
            //命令规定的是对外的接口,必须与模块内部的变量建立一一对应关系。用大括号
            export {
                a,b,c
            }
            export var d = 'd';
            export {d}
            export function f(){}
            export {f}
            //报错
            export 1;
            // 报错
            var m = 1;
            export m;
            // 报错
            function f() {}
            export f;
--------------------------------------------------------------------------------------------
            //export重命名语句 原命名 as 新命名
            export {
                a as m,
                b as n
            }
--------------------------------------------------------------------------------------------
            //export语句输出的接口,与其对应的值是动态绑定关系,即通过该接口,可以取到模块内部实时的值。
            //输出变量foo,值为bar,500 毫秒之后变成baz。
            //这一点与 CommonJS 规范完全不同。CommonJS 模块输出的是值的缓存,不存在动态更新
            export var foo = 'bar';
            setTimeout(() => foo = 'baz', 500);
--------------------------------------------------------------------------------------------
            //export命令可以在模块的任何位置,必须处于模块顶层,如果在块级作用域没法静态化会报错。
            //报错
            function foo() {
                export default 'bar' 
            }
            foo()
//main.js
//import命令
            import {a} from 'index.js';
            import {b} from 'index.js';
            import {c} from 'index.js';
            //等同于
            import {a,b,c} from 'index';//以上两种写法相同,import语句是独生模式
--------------------------------------------------------------------------------------------
            import {a} from 'index';
            //报错 变量a是只读的,可以改写a的属性
            var a = '1';
            //合法操作,但是其他模块输入读到改写后的值,不推荐使用难以查错,可用于特殊场景路由控制等等
            var a.foo = 'ok';
--------------------------------------------------------------------------------------------
            //import 有提升效果,会提升到模块头部执行
            foo();
            import { foo } from 'my_module';//ok
--------------------------------------------------------------------------------------------
            //import 是静态执行,不可以用变量和表达式,不能使用这些只有在运行时才能得到结果的语法结构。
            // 报错
            import { 'f' + 'oo' } from 'my_module';
            // 报错
            let module = 'my_module';
            import { foo } from module;
            // 报错
            if (x === 1) {
              import { foo } from 'module1';
            } else {
              import { foo } from 'module2';
            }
//模块使用整体加载
            //circle.js
            export function area(radius) {
              return Math.PI * radius * radius;
            }
            export function circumference(radius) {
              return 2 * Math.PI * radius;
            }
                    //index.js
            //逐一加载下面写法
            import { area, circumference } from './circle';
            console.log('圆面积:' + area(4));
            console.log('圆周长:' + circumference(14));
            //使用整体加载,即用星号(*)指定一个对象,所有输出值都加载在这个对象上面。
            import * as circle from './circle';
            console.log('圆面积:' + circle.area(4));
            console.log('圆周长:' + circle.circumference(14));
//export default 命令
            //方便加载,import命令可以为该匿名函数指定任意名字。
            // export-default.js
            export default function () {
                console.log('foo');
            }
            // import-default.js
            import customer from './export-default';
            customer(); // 'foo'
--------------------------------------------------------------------------------------------
            //对应的import语句不需要使用大括号
            import customName from './index';
            customName(); // 'foo'
            //两种写法
            export default function () {
                console.log('foo');
            }
            //或者写成
            function foo() {
                console.log('foo');
            }
            export default foo;
--------------------------------------------------------------------------------------------
            //export default 就是输出一个叫做default的变量或方法
            // 正确
            export var a = 1;
            // 正确
            var a = 1;
            export default a;
            // 错误
            export default var a = 1;
            //export default命令输出变量时,本质是将后面值,赋给default变量,所以可以直接将一个值写在export default之后
            // 正确
            export default 42;
            // 报错
            export 42;
--------------------------------------------------------------------------------------------
            //export default 允许用 as 任意命名,重命名为 default 有效
            function add(x, y) {
                return x * y;
            }
            export {add as default};
            // 等同于
            export default add;
            //main.js 引用
            import { default as add } from './index';
            //等同于
            import add from './index';
--------------------------------------------------------------------------------------------
            //有了export default命令,import 可以同时输入默认方法和其他接口
            //moudle.js
            export default function (obj) {
                
            }
            export function each(obj, iterator, context) {
                
            }
            export { each as forEach };
            //index.js
            import a, { each, forEach } form 'moudle';
--------------------------------------------------------------------------------------------
            //export default也可以用来输出类
            // MyClass.js
            export default class {
                
            }
            // main.js
            import MyClass from 'MyClass';
            let o = new MyClass();
//import 和 export 复合写法
            //export和import语句可以结合写成一行。相当于对外转发了接口,导致当前模块不能直接使用foo和bar。
            export { foo, bar } from 'my_module';
            // 可以简单理解为
            import { foo, bar } from 'my_module';
            export { foo, bar };
--------------------------------------------------------------------------------------------
            //模块的接口改名和整体输出,也可以采用这种写法。
            // 接口改名
            export { foo as myFoo } from 'my_module';
            // 整体输出
            export * from 'my_module';
--------------------------------------------------------------------------------------------
            //默认接口的写法如下。
            export { default } from 'foo';
--------------------------------------------------------------------------------------------
            //具名接口改为默认接口的写法如下。
            export { es6 as default } from './someModule';
            // 等同于
            import { es6 } from './someModule';
            export default es6;
--------------------------------------------------------------------------------------------
            //默认接口也可以改名为具名接口。
            export { default as es6 } from './someModule';
--------------------------------------------------------------------------------------------
            //注意下面三种import语句,没有对应的复合写法。为了做到形式的对称,现在有提案。
            import * as someIdentifier from "someModule";//*号重命名整体加载
            import someIdentifier from "someModule";//默认接口重命名
            import someIdentifier, { namedIdentifier } from "someModule";//同时输入默认方法和其他接口
//模块继承
            //circleplus模块 继承 circle模块。
            // circle.js
            export function area(radius) {
              return Math.PI * radius * radius;
            }
            export function circumference(radius) {
              return 2 * Math.PI * radius;
            }
            export default function(){
                
            }
            // circleplus.js
            //这里是复合写法,export *,表示再输出circle模块所有属性和方法。注意,export *命令会忽略circle模块的default方法。然后,上面代码又输出了自定义的e变量和默认方法。
            export * from 'circle';
            export var e = 2.71828182846;
            export default function(x) {
              return Math.exp(x);
            }
            //也可以将circle的属性或方法,改名后再输出。将其改名为circleArea。
            // circleplus.js
            export { area as circleArea } from 'circle';
            //加载模块 import exp表示,将circleplus模块的默认方法加载为exp方法。
            // main.js
            import * as math from 'circleplus';
            import exp from 'circleplus';
            console.log(exp(math.e));
//跨模块常量
            //const声明的常量只在当前代码块有效。建一个专门的constants目录,将各种常量写在不同的文件里面,保存在该目录下。
            // constants/db.js
            export const db = {
              url: 'http://my.couchdbserver.local:5984',
              admin_username: 'admin',
              admin_password: 'admin password'
            };
            // constants/user.js
            export const users = ['root', 'admin', 'staff', 'ceo', 'chief', 'moderator'];
            //将这些文件输出的常量,合并在index.js里面。
            // constants/index.js
            export {db} from './db';
            export {users} from './users';
            //使用的时候,直接加载index.js就可以了。
            // script.js
            import {db, users} from './constants/index';

上面的总结,更加清晰明了,细节上还有很多地方需要注意,建议多敲代码,明天再更、、、

上一篇:从“Wi-Fi之父”到重新定义“物联网”


下一篇:JavaScript中的函数基础