Ranking(2) Modules
本章节讲述在ES6中如何构建Modules
1、开始。
在ECMAScript 6中,modules 是存储在文件中,一般而言是一个文件一个模块。
有两种方式将模块中的方法暴露给外部使用
1.1 Multiple named exports
//多个暴露的方法或者属性
//------ lib.js ------ export const sqrt = Math.sqrt; export function square(x) { return x * x; } export function diag(x, y) { return sqrt(square(x) + square(y)); }
说明:
const 声明创建一个只读的常量。这不意味着常量指向的值不可变,而是变量标识符的值只能赋值一次;
详询:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/const
let声明了一个块级域的本地变量,并且可以同时初始化该变量;
let 允许把变量的作用域限制在块级域中。
与 var 不同处是:var 申明变量要么是全局的,要么是函数级的,而无法是块级的。
详细参考请 详询:
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/let
//------ main.js ------ import { square, diag } from 'lib'; console.log(square(11)); // 121 console.log(diag(4, 3)); // 5
你也可以引入整个模块:
//------ main.js ------ import * as lib from 'lib'; console.log(lib.square(11)); // 121 console.log(lib.diag(4, 3)); // 5
1.2 Single default export
有如下两种方式
//------ myFunc.js ------ export default function () { ··· } // //------ main1.js ------ import myFunc from 'myFunc'; myFunc();
或是定义一个类 class:
//------ MyClass.js ------ export default class { ··· } // //------ main2.js ------ import MyClass from 'MyClass'; let inst = new MyClass();
1.3 Browsers: scripts versus modules
Scripts Modules
HTML element <script> <script type="module">
2 Modules in JavaScript
2.1 ECMAScript 5 module systems
代表有AMD CMD 方式,这里就不再细说。
对于COMMOM js 上述例子的表现形式如下:
//------ lib.js ------ var sqrt = Math.sqrt; function square(x) { return x * x; } function diag(x, y) { return sqrt(square(x) + square(y)); } module.exports = { sqrt: sqrt, square: square, diag: diag, }; //------ main.js ------ var square = require('lib').square; var diag = require('lib').diag; console.log(square(11)); // 121 console.log(diag(4, 3)); // 5
2.2 ECMAScript 6 module systems
ES6 模块加载兼容CMD AMD 的优势。
另外,ES6 模块语法比commonJS 更加严格
基于 promise的module loader,接收单个模块模型
System.import('some_module') .then(some_module => { // Use some_module }) .catch(error => { ··· });
也可以接收多个模块,使用 Promise.all()
Promise.all( ['module1', 'module2', 'module3'] .map(x => System.import(x))) .then(([module1, module2, module3]) => { // Use module1, module2, module3 });
2.3 More loader methods
ES6 loader 拥有更多的load 方法,其中最为重要的是以下3个 System.module(source, options?)
//evaluates the JavaScript code in source to a module (which is delivered asynchronously via a Promise).
System.set(name, module)
//is for registering a module (e.g. one you have created via System.module()).
System.define(name, source, options?)
//both evaluates the module code in source and registers the result.
2.4 细节讲述
讲述 CommonJS vs ES6:
In CommonJS, imports 只是export的备份.
In ES6, imports 是只读read-only 类型.
下面通过demo说明
2.4.1 IN COMMONJS
//------ lib.js ------ var counter = 3; function incCounter() { counter++; } module.exports = { counter: counter, // (A) incCounter: incCounter, }; //------ main1.js ------ var counter = require('./lib').counter; // (B) var incCounter = require('./lib').incCounter; // The imported value is a (disconnected) copy of a copy console.log(counter); // 3 incCounter();// console.log(counter); // 3 // The imported value can be changed counter++; console.log(counter); // 4
另外一种表现形式也无法改变
//------ main2.js ------ var lib = require('./lib'); // The imported value is a (disconnected) copy console.log(lib.counter); // 3 lib.incCounter(); console.log(lib.counter); // 3 // The imported value can be changed lib.counter++; console.log(lib.counter); // 4
2.4.2 In ES6
//------ lib.js ------ export let counter = 3; export function incCounter() { counter++; } //------ main1.js ------ import { counter, incCounter } from './lib'; // The imported value `counter` is live console.log(counter); // 3 incCounter(); console.log(counter); // 4 // The imported value can’t be changed counter++; // TypeError If you import the module object via the asterisk (*), you get the same results: //------ main2.js ------ import * as lib from './lib'; // The imported value `counter` is live console.log(lib.counter); // 3 lib.incCounter(); console.log(lib.counter); // 4 // The imported value can’t be changed lib.counter++; // TypeError
再来看一例子 ,你不能改变imports ,但是可以改变它的属性方法
//------ lib.js ------ export let obj = {}; //------ main.js ------ import { obj } from './lib'; obj.prop = 123; // OK obj = {}; // TypeError
下一节 讨论 Destructuring.