以下文章来源于web前端开发
ES6模块是一个仅在严格模式下执行的JavaScript文件。这意味着模块中声明的任何变量或函数都不会自动添加到全局范围中。
在Web浏览器上执行模块
首先,创建一个名为message.js的新文件并添加以下代码:
exportletmessage=ES6Modules;
message.js是ES6中包含message变量的模块。export语句将消息变量公开给其他模块。
其次,创建另一个名为app.js的新文件,该文件使用message.js模块。app.js模块创建一个新的标题1(h1)元素并将其附加到HTML页面。import语句从message.js模块导入消息变量。
import{message}from./message.js
consth1=document.createElement(h1);
h1.textContent=message
document.body.appendChild(h1)
第三,创建一个使用app.js模块的新HTML页面:
!DOCTYPEhtml
html
head
metacharset="utf-8"
titleES6Modules/title
/head
body
scripttype="module"src="./app.js"/script
/body
/html
请注意,我们在script标签中使用了type="module"来加载app.js模块。如果我们在Web浏览器上查看该页面,我们将看到以下页面:
让我们更详细地检查导出和导入语句。
Exporting
要导出变量、函数或类,请将export关键字放在其前面,如下所示:
//log.js
exportletmessage=Hi;
exportfunctiongetMessage(){
returnmessage;
}
exportfunctionsetMessage(msg){
message=msg;
}
exportclassLogger{
}
在这个例子中,我们有一个带有一个变量、两个函数和一个类的log.js模块。我们使用export关键字来导出模块中的所有标识符。
请注意,export关键字要求函数或类具有要导出的名称。我们不能使用此语法导出匿名函数或类。
JavaScript允许我们先定义变量、函数或类,然后再将其导出,如下所示:
//foo.js
functionfoo(){
console.log(foo);
}
functionbar(){
console.log(bar);
}
exportfoo;
在本例中,我们先定义了foo()函数,然后将其导出。由于我们没有导出bar()函数,因此,我们无法在其他模块中访问它。bar()函数在模块外部是不可访问的,或者我们说它是私有的。
Importing
一旦定义了带有导出的模块,就可以使用import关键字访问另一个模块中导出的变量、函数和类。下面说明了语法:
import{what,ever}from./other_module.js;
在这种语法中:
首先,在大括号内指定要导入的内容,称为绑定。
然后,指定从中导入给定绑定的模块。
请注意,当我们从模块导入绑定时,绑定的行为就像使用const定义的一样。这意味着我们不能拥有另一个具有相同名称的标识符或更改绑定的值。
请参见以下示例:
//greeting.js
exportletmessage=Hi;
exportfunctionsetMessage(msg){
message=msg;
}
导入message变量和setMessage()函数时,可以使用setMessage()函数更改message变量的值,如下所示:
//app.js
import{message,setMessage}from./greeting.js;
console.log(message);//Hi
setMessage(Hello);
console.log(message);//Hello
但是,我们不能直接更改message变量的值。以下表达式会导致错误:
message=Hallo;//error
在幕后,当我们调用setMessage()函数时。JavaScript返回到greeting.js模块并在其中执行代码并更改消息变量。然后,更改会自动反映在导入的消息绑定上。
app.js中的消息绑定是导出消息标识符的本地名称。所以,基本上app.js和greeting.js模块中的消息变量是不一样的。
导入单个绑定
假设我们有一个带有foo变量的模块,如下所示:
//foo.js
exportfoo=10;
然后,在另一个模块中,我们可以重用foo变量:
//app.js
import{foo}from./foo.js;
console.log(foo);//10;
但是,我们不能更改foo的值。如果我们尝试这样做,我们会得到一个错误:
foo=20;//throwsanerror
导入多个绑定
假设我们有cal.js模块,如下所示:
//cal.js
exportleta=10,
b=20,
result=0;
exportfunctionsum(){
result=a+b;
returnresult;
}
exportfunctionmultiply(){
result=a*b;
returnresult;
}
并且我们想从cal.js中导入这些绑定,我们可以显式列出它们,如下所示:
import{a,b,result,sum,multiply}from./cal.js;
sum();
console.log(result);//30
multiply();
console.log(result);//
将整个模块作为对象导入
要将模块中的所有内容作为单个对象导入,请使用星号(*)模式,如下所示:
import*ascalfrom./cal.js;
在此示例中,我们从cal.js模块中导入了所有绑定作为cal对象。
在这种情况下,所有绑定都成为cal对象的属性,因此,我们可以访问它们,如下所示:
cal.a;
cal.b;
cal.sum();
这种导入称为命名空间导入。
重要的是要记住,导入的模块只执行一次,甚至多次导入。考虑这个例子:
import{a}from./cal.js;
import{b}from./cal.js;
import{result}from./cal.js;在第一个import语句之后,cal.js模块被执行并加载到内存中,并在后续import语句引用的任何时候被重用。输入输出的报表限制
请注意,我们必须在其他语句和函数之外使用import或export语句。以下示例导致SyntaxError:
if(requiredSum){
exportsum;
}
因为我们在if语句中使用了export语句。同样,以下import语句也会导致SyntaxError:
functionimportSum(){
import{sum}from./cal.js;
}
因为我们在函数内部使用了import语句。
错误的原因是JavaScript必须静态确定要导出和导入的内容。
请注意,ES引入了类似函数的对象import(),它允许我们动态导入模块。
Aliasing
JavaScript允许我们在导出和导入时为变量、函数或类创建别名。请参阅以下math.js模块:
//math.js
functionadd(a,b){
returna+b;
}
export{addassum};
在此示例中,我们没有导出add()函数,而是使用as关键字为sum()函数分配别名。
所以当我们从math.js模块中导入add()函数时,我们必须使用sum来代替:
import{sum}from./math.js;
如果要在导入时使用不同的名称,可以使用as关键字,如下所示:
import{sumastotal}from./math.js;
重新导出绑定
可以导出我们已导入的绑定。这称为重新导出。例如:
import{sum}from./math.js;
export{sum};
在此示例中,我们从math.js模块导入sum并重新导出。以下语句等效于上述语句:
export{sum}from./math.js;
如果我们想在重新导出之前重命名绑定,请使用as关键字。
以下示例从math.js模块导入sum并将其重新导出为add。
export{sumasadd}from./math.js;
如果要从另一个模块导出所有绑定,可以使用星号(*):
export*from./cal.js;
无绑定导入
有时,我们想要开发一个不导出任何内容的模块,例如,我们可能想要向内置对象(如Array)添加新方法。
//array.js
if(!Array.prototype.contain){
Array.prototype.contain=function(e){
//containimplementation
//...
}
}
现在,我们可以在没有任何绑定的情况下导入模块并使用array.js模块中定义的contains()方法,如下所示:
import./array.js;
[1,2,3].contain(2);//true
默认导出
一个模块可以有一个且只有一个默认导出。默认导出更容易导入。模块的默认值可以是变量、函数或类。
以下是带有默认导出的sort.js模块。
//sort.js
exportdefaultfunction(arr){
//sortinghere
}
请注意,我们不需要为函数指定名称,因为模块代表函数名称。
importsortfromsort.js;
sort([2,1,3]);
如上所见,排序标识符代表sort.js模块的默认功能。请注意,我们没有在排序标识符周围使用花括号{}。
让我们更改sort.js模块以包含默认导出以及非默认导出:
//sort.js
exportdefaultfunction(arr){
//sortinghere
}
exportfunctionheapSort(arr){
//heapsort
}
要同时导入默认和非默认绑定,请在import关键字之后使用以下规则指定绑定列表:
默认绑定必须先出现。
非默认绑定必须用花括号括起来。
请参见以下示例:
importsort,{heapSort}from./sort.js;
sort([2,1,3]);
heapSort([3,1,2]);
要重命名默认导出,我们还可以使用as关键字,如下所示:
import{defaultasquicksort,heapSort}from./sort.js;