[web]ES6学习笔记(二)
来源:互联网 发布:电视直播软件电脑版 编辑:程序博客网 时间:2024/06/08 14:15
一.module语法
1.概述
在 ES6 之前,社区制定了一些模块加载方案,最主要的有 CommonJS 和 AMD 两种。前者用于服务器,后者用于浏览器。ES6 在语言标准的层面上,实现了模块功能,而且实现得相当简单,完全可以取代 CommonJS 和 AMD 规范,成为浏览器和服务器通用的模块解决方案。
ES6 模块不是对象,而是通过export命令显式指定输出的代码,再通过import命令输入。
// ES6模块import { stat, exists, readFile } from 'fs';
上面代码的实质是从fs模块加载3个方法,其他方法不加载。这种加载称为“编译时加载”或者静态加载,即 ES6 可以在编译时就完成模块加载,效率要比 CommonJS 模块的加载方式高。当然,这也导致了没法引用 ES6 模块本身,因为它不是对象。
2.严格模式
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)
其中,尤其需要注意this的限制。ES6 模块之中,顶层的this指向undefined,即不应该在顶层代码使用this。
3.export命令
模块的功能主要由两个命令构成:export和import。export命令用于规定模块的对外接口,import命令用于输入其他模块输入的功能。
一个模块就是一个独立的文件。该文件内部的所有变量,外部无法获取。如果你希望外部能够读取模块内部的某个变量,就必须使用export关键字输出该变量。下面是一个 JS 文件,里面使用export命令输出变量。
// profile.jsexport var firstName = 'Michael';export var lastName = 'Jackson';export var year = 1958;
或者
// profile.jsvar firstName = 'Michael';var lastName = 'Jackson';var year = 1958;export {firstName, lastName, year};
export除了输出变量,还可输出函数或类
export function multiply(x, y) { return x * y;};
上面代码对外输出一个函数multiply
4.import命令
使用export命令定义了模块的对外接口以后,其他 JS 文件就可以通过import命令加载这个模块。
// main.jsimport {firstName, lastName, year} from './profile';function setName(element) { element.textContent = firstName + ' ' + lastName;}
上面代码的import命令,用于加载profile.js文件,并从中输入变量。import命令接受一对大括号,里面指定要从其他模块导入的变量名。大括号里面的变量名,必须与被导入模块(profile.js)对外接口的名称相同。
如果想为输入的变量重新取一个名字,import命令要使用as关键字,将输入的变量重命名。
由于import是静态执行,所以不能使用表达式和变量,这些只有在运行时才能得到结果的语法结构。(一般人也不会这么干吧…….)
5.模块的整体加载
除了指定加载某个输出值,还可以使用整体加载,即用星号(*)指定一个对象,所有输出值都加载在这个对象上面。
下面是一个circle.js文件,它输出两个方法area和circumference。
// circle.jsexport function area(radius) { return Math.PI * radius * radius;}export function circumference(radius) { return 2 * Math.PI * radius;}
现在加载这个模块:
// main.jsimport { 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));
注意,模块整体加载所在的那个对象(上例是circle),应该是可以静态分析的,所以不允许运行时改变。下面的写法都是不允许的。
import * as circle from './circle';// 下面两行都是不允许的circle.foo = 'hello';circle.area = function () {};
6.export与import的复合写法
如果在一个模块之中,先输入后输出同一个模块,import语句可以与export语句写在一起。
export { foo, bar } from 'my_module';// 等同于import { foo, bar } from 'my_module';export { foo, bar };
7.跨模块常量
const声明的常量只在当前代码块有效。如果想设置跨模块的常量(即跨多个文件),或者说一个值要被多个模块共享,可以采用下面的写法。
// constants.js 模块export const A = 1;export const B = 3;export const C = 4;// test1.js 模块import * as constants from './constants';console.log(constants.A); // 1console.log(constants.B); // 3// test2.js 模块import {A, B} from './constants';console.log(A); // 1console.log(B); // 3
8.import()
前面介绍过,import命令会被 JavaScript 引擎静态分析,先于模块内的其他模块执行(叫做”连接“更合适)。所以,下面的代码会报错。
// 报错if (x === 2) { import MyModual from './myModual';}
上面代码中,引擎处理import语句是在编译时,这时不会去分析或执行if语句,所以import语句放在if代码块之中毫无意义,因此会报句法错误,而不是执行时错误。也就是说,import和export命令只能在模块的顶层,不能在代码块之中(比如,在if代码块之中,或在函数之中)。
这样的设计,固然有利于编译器提高效率,但也导致无法在运行时加载模块。从语法上,条件加载就不可能实现。如果import命令要取代 Node 的require方法,这就形成了一个障碍。因为require是运行时加载模块,import命令无法取代require的动态加载功能。
因此,有一个提案,建议引入import()函数,完成动态加载。
import(specifier)
上面代码中,import函数的参数specifier,指定所要加载的模块的位置。import命令能够接受什么参数,import()函数就能接受什么参数,两者区别主要是后者为动态加载。
const main = document.querySelector('main');import(`./section-modules/${someVariable}.js`) .then(module => { module.loadPageInto(main); }) .catch(err => { main.textContent = err.message; });
import()类似于 Node 的require方法,区别主要是前者是异步加载,后者是同步加载
参考网址:
http://es6.ruanyifeng.com/#docs/module-loader
- [web]ES6学习笔记(二)
- ES6学习笔记(二)
- ES6学习笔记(二)
- 【Web】ES6学习笔记(一)
- ES6学习笔记(二)--解构赋值
- es6 学习笔记(二)Symbol
- 《ES6深入浅出》学习笔记(二)
- ES6学习笔记(二)变量的解构赋值
- es6学习过程(二)
- ES6学习笔记(一)
- ES6学习笔记(三)
- ES6学习笔记(一)
- ES6学习笔记(一)
- es6开发:ES6学习笔记
- ES6笔记(二)Promise对象
- ES6学习笔记(ES6新增的数组方法)
- Java Web 学习笔记(二)servlet
- ES6学习笔记二之数组的扩展
- Redis集群_3.redis主从自动切换Sentinel
- Linux下非root用户如何安装软件
- 【java-分布式系统】消息中间件学习-jms(以ActiveMQ为例)
- C#中多线程里面如何调用控件
- 射线检测
- [web]ES6学习笔记(二)
- ORACLE 创建视图时,出现权限不足 ORA-01031:权限不足
- linux安装c++版本eclipse以及编译增加指定库
- JavaWeb
- 深入理解AudioService
- 168题引出的思考
- Mac 解压rar格式文件(附解压工具包)
- ubuntu14.04右键菜单添加sublime打开选项
- DAM debug