ES Module特性

一、ES Module特性

1、通过给 script 标签加上一个 type=“module” 的属性,就可以以ES Module的标准执行其中的js代码了

	<script type="module">
        console.log('this is a module');
    </script>

2、ES Module自动采用严格模式,忽略 'use strict’

	<script type="module">
        console.log(this); // undefined,严格模式下this指向undefined
    </script>

3、每个ES Module都是运行在单独的私有作用域中

	<script type="module">
        var foo = 100
        console.log(foo); // 100
    </script>
    <script type="module">
         console.log(foo);//Uncaught ReferenceError: foo is not defined
    </script>

4、ES Module是通过 CORS 的方式请求外部JS模块的

<script type="module" src="https://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>

请求的服务端需要支持CORS,否则会报一个跨域的错误,而且在Nerwork中可以看到这样一个请求被浏览器终止了

<script type="module" src="https://unpkg.com/jquery@3.4.1/dist/jquery.min.js"></script>

另外 CORS不支持文件的形式去访问,所以我们必须要使用http server的方式去让页面工作起来,这个问题一般我们在实际开发过程中不会遇到,因为我们实际开发最终的运行环境都是http server

5、ES Module会延迟执行脚本,类似于defer的效果

<script type="module" src="demo.js"></script> 
<p>需要显示的内容</p>
// demo.js
alert("hello")

报错了,报出了一个跨域的错误,与上面的不支持CORS错误一样。
因为我是直接在本地打开的html,所以我们其实是用file协议在本地打开的文件,根本就没有跨域请求需要的Origin(Origin:null),所以这种情况下报错了。
解决办法,使用serve在本地起个服务器,安装命令:npm i -g serve,启动服务命令:serve .
此时再打开html查看效果,可以看到p标签内容显示之后才会弹窗。

<!-- defer的效果与之类似 -->
<script defer src="demo.js"></script>
<p>需要显示的内容</p>

二、export

2.1、普通导出导入

// module.js
export const fo = 100
// app.js
// 接收module.js中的fo
import { fo } from './module.js'

// 通过as重命名fo,相当于以一个新的变量接收fo的值
import { fo as da } from "./module.js"

2.2、导出多个数据

// module.js
const fn = () => {
    console.log('this is fn');
}

const arr = [1, 2, 3]

export { fn, arr }
// app.js
import { fn, arr} from "./module.js"
fn()
console.log(arr);

2.3、重命名

// module.js
const fn = () => {
    console.log('this is fn');
}

const arr = [1, 2, 3]

// 将fn与arr重命名后暴露出去,外部就需要根据重命名来获取
export { fn as f, arr as list}
// app.js
import { f, list} from "./module.js"
f()
console.log(list);

2.4、default

// module.js

// 重命名为default,这个成员就会作为当前模块默认导出的成员
const d = "this is default"
export { d as default }
// export default d 这种写法与上面的效果一样
// app.js
import d from './module.js'
console.log(d) // this is default

// 如果通过{}方式接收,则必须对default重命名来接收值
import { default as d } from './module.js'

三、导入导出的注意事项

// module.js
var name = 'jack'
var age = 18
export { name, age }
// app.js
import { name, age } from "./module.js"

很多人会将这种导出方式误认为这是对象的里面量,即导出一个对象{ name: name, age: age},然后就认为导入的时候就是对这个字面量的解构。

export {}其实是一种固定的语法,在导出多项成员的时候必须这样使用。

如果一定想要导出一个对象,可以通过export default {},这样导出的就是一个对象了。

export default { name, age }
import { name, age } from "./module.js"

这时会报错,The requested module ‘./module.js’ does not provide an export named ‘age’,module.js暴露出来的并没有age成员,这说明import 后的{ }并不是对对象的解构,和export的{ }一样就是一个固定的用法,就是用来提取模块当中导出的成员。

还有一个需要注意的点,export导出一个成员的时候,它导出的其实是一个成员的引用。就是说模块当中定义了一个name的变量,内存当中有一个name的空间,里面放了name对应的值。export将name导出出去,并不是复制了它的值,而是将它对内存中值的引用关系导出去了,所以外部访问的name始终都是模块中的内存空间里的name的值。

可以通过以下代码来验证一下。

// module.js
var name = 'jack'
export { name }
setTimeout(function(){
	name = 'luckily'
},1000)
// app.js
import { name } from "./module.js"
console.log("第一次打印name",name) // jack
setTimeout(function(){
	console.log("第二次打印name",name) // luckily
},2000)

还有就是,export暴露出来的引用关系是只读的

// app.js
import { name } from "./module.js"
name = "luck"

报错Assignment to constant variable.说的是我们没有办法去修改一个常量,实际上我们声明的时候并不是以常量的方式去声明的。

总结

  1. export { }导出的成员并不是对象字面量,import { } 导入的时候并不是使用解构语法,都只是固定的语法。
  2. export导出的成员并不是导出成员的值,而是成员的引用关系,所以外部拿到的值会受模块内部值的变化所影响。
  3. 外部导入一个模块中的成员,导入的是一个只读的成员,并不能去修改
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值