博客园首页新随笔联系订阅 管理
随笔 - 256 文章 - 1 评论 - 266
ES6新特性:使用export和import实现模块化
阅读目录
ES6的模块化的基本规则或特点:
下面列出几种import和export的基本语法:
ES6导入的模块都是属于引用:
循环依赖的问题:
浏览器兼容:
参考:
在ES6前, 前端就使用RequireJS或者seaJS实现模块化, requireJS是基于AMD规范的模块化库, 而像seaJS是基于CMD规范的模块化库, 两者都是为了为了推广前端模块化的工具, 更多有关AMD和CMD的区别, 后面参考给了几个链接;
现在ES6自带了模块化, 也是JS第一次支持module, 在很久以后 ,我们可以直接作用import和export在浏览器中导入和导出各个模块了, 一个js文件代表一个js模块;
现代浏览器对模块(module)支持程度不同, 目前都是使用babelJS, 或者Traceur把ES6代码转化为兼容ES5版本的js代码;
回到顶部
ES6的模块化的基本规则或特点:
ES6的模块化的基本规则或特点, 欢迎补充:
1:每一个模块只加载一次, 每一个JS只执行一次, 如果下次再去加载同目录下同文件,直接从内存中读取。 一个模块就是一个单例,或者说就是一个对象;
2:每一个模块内声明的变量都是局部变量, 不会污染全局作用域;
3:模块内部的变量或者函数可以通过export导出;
4:一个模块可以导入别的模块
运行下面代码
复制代码
//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));
}
//main.js
import { square, diag } from './lib';
console.log(square(11)); // 121
console.log(diag(4, 3)); // 5
复制代码
回到顶部
下面列出几种import和export的基本语法:
第一种导出的方式:
在lib.js文件中, 使用 export{接口} 导出接口, 大括号中的接口名字为上面定义的变量, import和export是对应的;
运行下面代码
复制代码
//lib.js 文件
let bar = "stringBar";
let foo = "stringFoo";
let fn0 = function() {
console.log("fn0");
};
let fn1 = function() {
console.log("fn1");
};
export{ bar , foo, fn0, fn1}
//main.js文件
import {bar,foo, fn0, fn1} from "./lib";
console.log(bar+"_"+foo);
fn0();
fn1();
复制代码
第二种导出的方式:
在export接口的时候, 我们可以使用 XX as YY, 把导出的接口名字改了, 比如: closureFn as sayingFn, 把这些接口名字改成不看文档就知道干什么的:
运行下面代码
复制代码
//lib.js文件
let fn0 = function() {
console.log("fn0");
};
let obj0 = {}
export { fn0 as foo, obj0 as bar};
//main.js文件
import {foo, bar} from "./lib";
foo();
console.log(bar);
复制代码
第三种导出的方式:
这种方式是直接在export的地方定义导出的函数,或者变量:
运行下面代码
复制代码
//lib.js文件
export let foo = ()=> {console.log("fnFoo") ;return "foo"},bar = "stringBar";
//main.js文件
import {foo, bar} from "./lib";
console.log(foo());
console.log(bar);
复制代码
第四种导出的方式:
这种导出的方式不需要知道变量的名字, 相当于是匿名的, 直接把开发的接口给export;
如果一个js模块文件就只有一个功能, 那么就可以使用export default导出;
运行下面代码
复制代码
//lib.js
export default "string";
//main.js
import defaultString from "./lib";
console.log(defaultString);
复制代码
第五种导出方式:
export也能默认导出函数, 在import的时候, 名字随便写, 因为每一个模块的默认接口就一个:
运行下面代码
复制代码
//lib.js
let fn = () => "string";
export {fn as default};
//main.js
import defaultFn from "./lib";
console.log(defaultFn());
复制代码
第六种导出方式:
使用通配符* ,重新导出其他模块的接口 (其实就是转载文章, 然后不注明出处啦);
运行下面代码
复制代码
//lib.js
export * from "./other";
//如果只想导出部分接口, 只要把接口名字列出来
//export {foo,fnFoo} from "./other";
//other.js
export let foo = "stringFoo", fnFoo = function() {console.log("fnFoo")};
//main.js
import {foo, fnFoo} from "./lib";
console.log(foo);
console.log(fnFoo());
复制代码
其他:ES6的import和export提供相当多导入以及导出的语法;
在import的时候可以使用通配符*导入外部的模块:
运行下面代码
import * as obj from "./lib";
console.log(obj);
回到顶部
ES6导入的模块都是属于引用:
每一个导入的js模块都是活的, 每一次访问该模块的变量或者函数都是最新的, 这个是原生ES6模块 与AMD和CMD的区别之一,以下代码修改自http://exploringjs.com/es6/ch_modules.html#_imports-are-read-only-views-on-exports
运行下面代码
复制代码
//lib.js
export let counter = 3;
export function incCounter() {
counter++;
}
export function setCounter(value) {
counter = value;
}
//main.js
import { counter, incCounter ,setCounter} from './lib';
// The imported value `counter` is live
console.log(counter); // 3
incCounter();
console.log(counter); // 4
setCounter(0);
console.log(counter); // 0
复制代码
在main.js中, counter一直指向lib.js中的局部变量counter, 按照JS的尿性, 像数字或者字符串类型或者布尔值的原始值要被复制, 而不是赋址;
回到顶部
循环依赖的问题:
NodeJS的循环依赖是这么处理的:打开;
循环依赖是JS模块化带来的问题, 在浏览器端, 使用RequireJS测试模块化, 比如有一个文件file0.js依赖于file1.js, 而file1.js又依赖于file0.js, 那么file0.js和file1.js到底谁先执行?
运行下面代码
复制代码
//index.html
复制代码
在控制台的依次输出为:
运行下面代码
undefined
Object { file1: "file1" }
Object { file0: "file0" }
在执行file1.js的时候file0.js还没执行完, 所以输出了undefined, 这种输出结果和NodeJS输出的情况是一样的;
然后我又使用了司徒大神的mass-framework框架试了一下, 司徒大神的框架直接提示我: "模块与之前的某些模块存在循环依赖", 这样还比较好点, requireJS对于循环依赖是直接执行循环依赖的模块, 会导致在开发的时候给自己挖坑....;
接下来我又在babel-node下进行测试:下面是几个测试,可以无视:
我使用ES6的模块试一试, 只要每一个模块被引用, 无论模块是否执行完毕, 该模块的export已经被导出了, 如果导出的是函数:
运行下面代码
复制代码
//cyclic.js
import fn0 from "./file0";
fn0();
//file0.js
import fn1 from "./file1";
fn1();
console.log("file0.js runs");
export default function() {console.log("file0 export runs")}
//file1.js
import fn0 from "./file0";
fn0();
console.log("file1.js runs");
export default function() {console.log("file1 export runs")}
复制代码
如果导出的是字符串:
运行下面代码
复制代码
//cyclic.js
import str from "./file0";
console.log(str);
//file0.js
import str1 from "./file1";
console.log(str1)
console.log("file0.js runs");
export default "str0";
//file1.js
import str0 from "./file0";
console.log(str0)
console.log("file1.js runs");
export default "str1";
复制代码
如果导出的是对象:
那么第一行会先输出一个初始值{},在最后等待file0.js和file1.js执行完毕以后, 才输出file0.js导出的对象;
如果是数组:
那么第一行会输出一个被静态分析过的初始值undefined,在最后等待file0.js和file1.js执行完毕以后, 才输出file0.js导出的对象;
如果是布尔值:
那么第一行会输出一个被静态分析过的初始值undefined,在最后等待file0.js和file1.js执行完毕以后, 才输出file0.js导出的布尔值;
为什么会这样呢? 我好像在这边找到了答案:http://exploringjs.com/es6/ch_modules.html#_modules ,ES6的import和export被提前到js的最顶层, 在函数或者对象,或者基本值被导出去的时候提前被静态分析过,参考:http://www.ecma-international.org/ecma-262/6.0/#sec-parsemodule , http://www.ecma-international.org/ecma-262/6.0/#sec-toplevelmoduleevaluationjob
结论:用ES6的export导出数据接口的时候, 最好统一用函数, 避免在循环依赖的时候, 因为JS会把不同类型的对象静态解析成不同的初始值;
1
1
回到顶部
浏览器兼容:
chrome浏览器目前不支持import,和export;
火狐的支持也有限, 比chrome好;
我都用babel;
回到顶部
参考:
ecma-262:http://www.ecma-international.org/ecma-262/6.0/#sec-imports
import:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import
export:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export
babelJS:http://babeljs.io/
Exploring ES6(Dr.Axel Rauschmayer):http://exploringjs.com/es6/ch_modules.html
SeaJS和RequireJS的异同:https://github.com/seajs/seajs/issues/277
SeaJS与RequireJS最大的区别:https://www.douban.com/note/283566440/
阮老师es6#module:http://es6.ruanyifeng.com/#docs/module
AMD 和 CMD 的区别有哪些:https://www.zhihu.com/question/20351507/answer/14859415
作者: NONO
出处:http://www.cnblogs.com/diligenceday/
QQ:287101329
微信:18101055830
天道酬勤
分类: ES5和ES6
好文要顶 关注我 收藏该文 方方和圆圆
关注 - 23
粉丝 - 179
+加关注
3 0
« 上一篇:ES6新特性:Javascript中内置的延迟对象Promise
» 下一篇:JS中的进制转换以及作用
posted @ 2016-06-24 00:26 方方和圆圆 阅读(8527) 评论(3) 编辑 收藏
评论列表
#1楼 2016-06-24 16:52 wdwwtzy
我就是想知道node啥时候支持。。。。。。。
支持(1)反对(0)
#2楼[楼主] 2016-06-25 00:39 方方和圆圆
@ wdwwtzy
直接用babelJS转码, nodeJS的支持你要看版本
支持(0)反对(0)
#3楼 2016-06-27 11:58 wdwwtzy
@ 方方和圆圆
太麻烦 我要原生支持import。。。。。
支持(0)反对(0)
刷新评论刷新页面返回顶部
注册用户登录后才能发表评论,请 登录 或 注册,访问网站首页。
【推荐】50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
【推荐】融云发布 App 社交化白皮书 IM 提升活跃超 8 倍
【邀请】网易云渠道合作伙伴招商大会,邀您共创未来
最新IT新闻:
· 互联网步入下半场,内容平台的烧钱战在重演O2O的疯狂?
· 忘掉众包,让我们把专业的事情做好
· Uber将在乘客下车后继续跟踪五分钟
· 风投行业怎样自我创新?来自全球20家创新型风投的分享
· ofo张严琪:我们的目标是连接全世界所有单车
» 更多新闻...
最新知识库文章:
· 高质量的工程代码为什么难写
· 循序渐进地代码重构
· 技术的正宗与野路子
· 陈皓:什么是工程师文化?
· 没那么难,谈CSS的设计模式
» 更多知识库文章...
公告
昵称:方方和圆圆
园龄:3年9个月
粉丝:179
关注:23
+加关注
< 2016年12月 >
日 一 二 三 四 五 六
27 28 29 30 1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
1 2 3 4 5 6 7
搜索
找找看
谷歌搜索
常用链接
我的随笔
我的评论
我的参与
最新评论
我的标签
我的标签
chrome(1)
chromium(1)
github(1)
handlebarsJs(1)
js的坑系列(1)
JS模版(1)
web前端(1)
布局(1)
图片(1)
移动(1)
更多
随笔分类
angularJS(19)
bug(2)
C 和C++(15)
chromium(1)
emberjs(1)
ES5和ES6(13)
html和css相关(31)
java(24)
js_Games(11)
js备忘(10)
js插件(8)
JS基础入门(13)
js设计模式的代码(14)
js收藏(4)
JS书籍(9)
knockout(2)
learn(50)
my_first_blog(2)
myPoppin_me(3)
NODEJS(6)
python(1)
ReactJS(1)
SQL
TypeScript(2)
其他(4)
系统(1)
项目(4)
源代码(4)
随笔档案
2016年11月 (16)
2016年10月 (3)
2016年9月 (4)
2016年8月 (9)
2016年7月 (1)
2016年6月 (6)
2016年5月 (11)
2016年4月 (1)
2016年3月 (12)
2016年2月 (4)
2016年1月 (3)
2015年12月 (5)
2015年11月 (3)
2015年9月 (1)
2015年8月 (5)
2015年7月 (5)
2015年6月 (3)
2015年5月 (4)
2015年4月 (8)
2015年3月 (4)
2015年2月 (9)
2015年1月 (7)
2014年12月 (18)
2014年11月 (8)
2014年10月 (11)
2014年9月 (7)
2014年8月 (5)
2014年6月 (1)
2014年5月 (8)
2014年4月 (15)
2014年3月 (9)
2014年2月 (4)
2014年1月 (3)
2013年12月 (23)
2013年11月 (19)
2013年8月 (1)
最新评论
1. Re:mac上安装ubuntu双系统
@L-H?...
--方方和圆圆
2. Re:mac上安装ubuntu双系统
兄台 真是逗
--L-H
3. Re:angular的splitter案例学习
良心博客
--pumpkins
4. Re:sublime3安装liveload,实现前端自动F5刷新html界面
@小陆豪客不会, 更改引用的js文件,不会自动刷新...
--方方和圆圆
5. Re:sublime3安装liveload,实现前端自动F5刷新html界面
如果是更改了html页面引入的外部js文件,保存这个js会自动刷新吗?
--小陆豪客
阅读排行榜
1. ES6新特性:使用export和import实现模块化(8525)
2. HTML5射击类游戏----【地球保卫战】(3844)
3. 基于springMVC+angular+bootstrap+mysql的简易购物网站搭建(3265)
4. 让nodeJS支持ES6的词法----babel的安装和使用(3020)
5. angular指令大全(2400)
评论排行榜
1. HTML5射击类游戏----【地球保卫战】(35)
2. 用JS写了一个打字游戏,反正我是通不了关(20)
3. 使用ARP欺骗, 截取局域网中任意一台机器的网页请求,破解用户名密码等信息(11)
4. Base64原理解析(10)
5. Javascript写了一个2048的游戏(9)
推荐排行榜
1. HTML5射击类游戏----【地球保卫战】(52)
2. 用JS写了一个打字游戏,反正我是通不了关(14)
3. 使用ARP欺骗, 截取局域网中任意一台机器的网页请求,破解用户名密码等信息(12)
4. Base64原理解析(8)
5. 2010-2014总结 ____V_V____ hello-world(8)
Copyright ©2016 方方和圆圆
再过一百年, 我会在哪里?