欢迎光临本站简介什么是模块?模块只不过是写在文件中的一段JavaScript代码。模块中的函数或变量不可用,除非模块文件导出它们。简而言之,这些模块帮助您在模块中编写代码,并且仅公开应由代码的其他部分访问的部分代码。为什么要使用模块来增加可维护性:由于每个模块都是独立的,所以每个人写的代码不会互相影响。维护代码的时候很容易查到是哪个模块出错了。复用性:在日常开发中,尤其是比较大的项目,代码的复用性就显得尤为重要。也许您会使用复制和粘贴,但可以直接使用导入命令来完成。不是很快吗?.避免命名污染:在javascript脚本中,在所有js文件的顶级作用域内创建的变量,都会被添加到共享的全局作用域中,这可能会导致不同人开发的代码使用相同的变量名,造成变量名污染。如何使用exportmodules用于导出模块的命令是export。如前所述,模块是一个javascript文件。该模块中定义的变量无法从外部获取。只有通过export导出的变量才能被其他模块使用。最简单的导出方式就是声明变量、函数,在类前面加一个导出//export1.js//导出变量exportletname='TaoWeng';//导出函数exportfunctionprint(){console.log("欢迎关注公众号:前端桃源");}//exportclassPerson{constructor(name){this.name=name;}}//privatefunctionfunctionprivateFunction(){console.log('我是一个privatefunction,我不能被外部访问');}注意:1、导出的函数或类必须要有名字,也就是说匿名函数或匿名类不能以这种方式导出。2.privateFunction函数,没有export命令,被视为本模块的私有变量,不能被其他模块访问。除了上面的export方法,还有一个//export2.js//exportvariableletname='TaoWeng';//exportfunctionfunctionprint(){return'欢迎关注公众号:前端桃园';}//导出类类Person{constructor(name){this.name=name;}}//privatefunctionfunctionprivateFunction(){return'我是一个私有函数,不能被外部访问';}export{name,print,Person}上面的方法导入了一组变量,相当于export1.js。导入的模块可以理解为生产者(或服务提供者),使用导入模块的模块就是消费者。导入模块的命令是import,import的基本形式如下:import{var1,var2}from'./example.js'import语句包含两部分:一是导入需要的标识符,二是other是模块的来源。注意:浏览器中的模块源必须以“/”或“./”或“../”开头或url形式,否则会报错。例如,如果我们导入export1.js模块,我们可以这样导入它//import1.jsimport{name,print,Person}from'./export1.js';控制台日志(名称);//陶翁console.log(print());//欢迎关注公众号:前端桃园//报错,不能定义同名变量letname=2333;//报错,无法重新赋值name="LittlePig";可以看到importbinding(这里的binding我不太懂,后面会在文章中解释),形式上和对象解构类似,但其实并无关联。导入绑定的时候,绑定类似于使用const定义,也就是说不能定义相同的变量名,但是没有临时死区特性(但是在深入理解ES6这本书里面说有临时死区限制,我在chrome上测试过,希望读者也来试试,毕竟没有限制)。让名字=2333;上面这行代码会报错。命名空间导入这种类型的导入将整个生产者模块作为单个对象导入,所有导出都被视为该对象的属性。//import2.jsimport*asnamespacefrom'./export1.js'console.log(namespace.name);//陶翁console.log(namespace.print());//欢迎关注公众号:前端桃源重命名导入导出有时候不想导出变量的原名,需要重命名。这时候你只需要使用as关键字来制定一个新的名字即可。Renameexport//export3.jsfunctionprint(){return'欢迎关注公众号:前端桃源';}export{打印成广告}importrenameintoexportedabove//import3.jsimport{打印广告}来自'./export3.js'console.log(广告类型);//“未定义”console.log(print());//欢迎关注公众号:前端桃源这段代码引入了广告功能,重命名为print,表示该模块不再存在广告标识。default关键字default关键字用于默认导入和导出。defaultexport//defaultExport.js//第一种默认导出方法exportdefaultfunctionprint(){return'欢迎关注公众号:前端桃源';}//第二种默认导出方法functionprint(){return'欢迎关注公众号:前端桃园';}exportdefaultprint;//第三种默认导出方法functionprint(){return'欢迎关注公众号:前端桃园';}export{printasdefault}defaultthiskey这个词在JS中有特殊含义,可以同名导出,表示模块需要使用默认值。注意:一个模块中只能有一个默认导出。默认导入默认导入和一般导入的区别在于不需要写花括号,看起来更简洁。以上面导出的defaultExport.js模块为例importprintfrom'./defaultExport.js'console.log(print());//欢迎关注公众号:前端桃源,如果同时有默认和非默认怎么导入呢?看例子就明白了//defaultImport1.jsletname='PeachWeng';functionprint(){return'欢迎关注公众号:前端桃园';}export{name,printasdefault}//defaultImport2.jsimportprint,{name}from'./defaultImport1.js'console.log(print());//欢迎关注公众号:前端桃源console.log(name);//淘翁混合导入需要把默认导入的名称放在前面,然后用逗号隔开,后面是非默认导出。想了很久要不要加高级内容。本来想写成入门系列的,后来想了想还是应该全部写进去。初学者入门前看基础,深入理解看高级。进阶部分主要介绍模块的几个特点。静态执行和动态关联模块不会重复执行。所谓静态执行,其实就是在编译阶段需要确定模块的依赖关系,所以import命令会优先于其他模块。内容的执行会提前到编译阶段执行。//static1.jsconsole.log('Page');import{nouse}from'./static2.js'//static2.jsexportfunctionnouse(){return'我不需要它';}console.log('小猪');可以看出最终的输出应该是先输出“小猪”,再输出“Page”,由此可以断定,后面虽然引入了static2.js,但是会提升到模块最前面实现。这也是我之前说不受临时死区影响的原因之一。这里可以写个例子试试://static3.jsconsole.log(nouse());import{nouse}from'./static2.js'//result://piggy//我不需要。导入前已经验证导入的绑定是可以使用的。静态执行也会导致无法动态导入模块的问题。//errorif(flag){import{nouse}from'./static3.js'}//errorimport{'no'+'use'}from'./static3.js'因为import是静态执行的,所以在静态(词法)分析阶段,不可能得到表达式或变量的值。但是为了解决这个问题,因为有import()函数,这算是一个扩展内容。写多了怕没人看,后面会有延伸阅读链接。动态关联所谓动态关联,其实就是一种绑定关系。这是ES6的一个非常重要的特性,所以一定要仔细阅读。在ES6模块中,输出的不是对象的副本,无论是引用类型还是基本类型,都是动态关联模块中的值。//dynamic1.jsexportletname='TaoWeng';exportfunctionsetName(name){name=name;}//dynamic2.jsimport{name,setName}from'./dynamic1.js'console.log(name);//陶翁setName('不要脸');console.log(name);//无耻奇迹般的发现在dynamic2.js模块中可以修改dynamic1.js模块中的值,并体现在namebinding中(这是重点,在consumer模块中体现),于是我们调用导入的变量绑定。生产者模块导出的变量和消费者模块导入的变量之间会存在绑定关系。无论是前者还是后者发生变化,都会相互影响。注意区分文件或模块中基本类型的赋值,两者相互独立。模块不会重复执行这个特性更容易理解,即如果绑定是从生产者模块单独导入而不是一次性导入,生产者模块不会被执行多次。//noRepeat1.jsexportletname='陶翁';exportletage='22';console.log('我正在执行...');//noRepeat2.jsimport{name}from'./noRepeat1.js';import{age}from'./noRepeat1.js';console.log(name);console.log(age);//结果//我正在执行。..//陶翁//22虽然导入了两次,但是noRepeat1.js只执行了一次。如果在同一个应用中导入同一个模块(注意同一个应用不是模块),那么这些模块都会使用一个模块实例,也就是单例。后记码字不易,写技术文章真的很累,作者花的时间至少是读者的十倍。在这里我觉得阮老师写了那么多文章,不知道花了多少时间,居然还有人那么讨厌他,攻击他的网站。文章里给公众号打了很多广告,不好意思,刚上线的公众号需要吸粉,不喜欢就看内容吧。扩展原生ECMAScript模块:动态import()
