彻底理解JavaScriptES6中的import和export
0、前⾔
前端⼯程,在最早的时候是没有模块的概念的。随着前端⼯程的发展,前端开发也越来越规范化,更像是软件⼯程了。那么随之⽽来的,为了解决⼯程化的问题,就引⼊了模块的概念。但是在早期,因为ecmascript原本是没有模块语法的,所以采⽤的都是社区的各种版本协议,其中影响最深的,就是nodejs使⽤的。
当模块化的概念越来越重要的时候,在es6中,引⼊了模块的语法:import ,下⾯我们简单了解⼀下,import是怎么使⽤的。⼀下内容,参考
1、export
⼀个js⽂件,可以理解成⼀个模块,这个模块可以被任意其他的模块引⼊,引⼊的结果,就是对这个模块进⾏执⾏后,所持有的对象。那么随之⽽来就有⼀个问题,⽂件模块被引⼊后,所有的东西,都是在⾃⼰的作⽤域中,主动发起引⼊⾏为的那个⽂件,虽然获取到了被引⼊的对象,但是并不能访问作⽤域⾥的东西,所以提供了export,来决定⼀个模块对外暴露什么东西。
的作⽤,就是⽤于从模块中导出函数、对象或原始值,以便其他程序可以通过 import 语句使⽤它们.
在import ⼀个⽂件的时候,会获取这个⽂件对象,默认是空对象,代表我们不能访问⽂件的东西。使⽤export,来给这个对象添加内容
⽤法:
module1.js :
function f1 (){
console.log("module - 1 : functino 1")
}
let b = {
name:"test_obj"
}
let str = "hell绿绿绿"
export {
f1,b,str
}
在main.js中进⾏引⼊
// 先忽略 import 的写法,后⾯再说明
import * as m1 from "./m1.js"
console.log(m1)
在这个⽂件中,我们对外暴露了⼀个函数,⼀个变量,⼀个对象。所以,在使⽤ import 导⼊的⽂件对象,就不在是⼀个空对象,⽽是包含了export 内容的对象,所以,我们打印出m1.js⽂件对象,也就是m1:
所以,我们知道,export 导出的内容,都会添加到⽂件对象中,可以简单的先理解为深拷贝。
2、export default
很多初学者很困惑,既然有了 export ,为什么还要有个 export default 呢?⽹上给出的答案往往是,作为⽂件的默认导出接⼝。那什么⼜是⽂件的默认导出接⼝呢?
其实这个问题很简单,我们先抛开 import ,不考虑import 的语法,仅考虑 export default具体做了什么。
修改module1.js :
function f1 (){
console.log("module - 1 : functino 1")
}
let b = {
name:"test_obj"
}
let str = "hell绿绿绿"
export {
f1,b,str
}
export default{
name:"default"
}
main.js不变,在执⾏⼀遍,继续查看打印出来的⽂件对象:
发现了吗,export default 的作⽤,是给⽂件对象,添加⼀个 default属性,default属性的值也是⼀个对象,且和export default导出的内容完全⼀致。
import语句
3、⽂件导出的总结
那么到这⾥,我们明⽩了,⼀个js⽂件被当做⼀个模块引⼊,会暴露为⼀个对象(也就是被导⼊后,可以当做⼀个对象来操作)。
export的作⽤,是在这个⽂件对象中添加属性,export出来的东西,全部会添加到⽂件对象中。
export default 的作⽤,是给⽂件对象的default属性,添加值。
4、import
在上⾯的例⼦中,我们明⽩了模块对外暴露的都是什么东西,那么我们如何来使⽤⽂件对外暴露的东西呢?
⾸先我们已经明⽩,⽂件对象是什么。
4.1导出整个⽂件对象
那么⾸先,我们就导出整个⽂件对象,看⼀看是什么样⼦的。就是上⾯例⼦中,我们使⽤到的语法,import * 来导出⽂件模块的所有接⼝,as m_name来指定⼀个命名空间对象。
main.js:
import * as m1 from "./m1.js"
console.log(m1)
⽰例中的m1命名空间对象,可以访问到⽂件对象的所有对外接⼝,包括export,和export default。
4.2 导出export的部分接⼝
在实际开发中,我们并不需要导出所有的接⼝。例如在vue项⽬中,使⽤某个组件库中的某个组件,我们只需要引⼊这⼀个组件,不必要引⼊所有组件。
我们知道,import 导出的是整个⽂件对象,那么我们直接在import语句中,对这个对象进⾏解构,就可以获得其中某⼀部分接⼝:main.js :
import {f1,b} from "./m1.js"
console.log(f1)
console.log(b)
打印结果,就是:
但是这种⽅式,仅限于获取⽂件对象的正常属性,default属性是获取不到的,原因有两个:
未解构的对象全部进⾏了丢弃
default是关键字,不能再解构中当做变量进⾏使⽤
4.3 导⼊export default 的接⼝
export default是⽂件的默认导⼊,其实这句话的重点,并不在于 export default,⽽是在于 import 语句是如何处理⽂件默认导⼊的。
修改main.js⽂件内容为:
import d from "./m1.js"
console.log(d)
打印出来,惊奇的发现,d 竟然和 export default 的内容⼀样。
所以,现在可以这么理解,所谓的默认导⼊,就是毫⽆花哨的直接导⼊⼀个模块,然后赋值给⼀个命名空间,这种时候,这个命名空间,持有的就是⽂件对象的default 对象,也就是export default 出来的东西。
其实,默认导⼊可以理解为也是解构的⼀个语法糖(仅仅⽤作理解,实际是语法错误的):
import d from "./m1.js"  可以等价为 import {default as d} from "./m1.js"
5、import动态导⼊
还有⼀种⾼端的玩法,在项⽬中也是很有⽤处的。
import不光是⼀个关键字,同时也是⼀个函数,函数的参数是需要导⼊模块的路径,函数返回⼀个promise对象。
import("./m1.js").then(m=>{
console.log('then:',m)
})
在这段代码中,then中回调的m,就是⽂件模块的整个⽂件对象(包括export和export default)。
6、import不导⼊⽂件对象
import还可以不导⼊⽂件对象,仅仅是使⽤⽂件模块提供的功能。也就是传说中的,import将⽂件模块仅仅最为副作⽤进⾏导⼊,⽽不获取⽂件模块的接⼝。
在项⽬中,实践的地⽅,例如⼀个vue项⽬,我们需要给vue对象挂载很多东西,但是全部写在src/main.js⽂件中,⼜会显得特别啰嗦,不利于维护,也没能体现⼯程化的理念。所以我们常常单独新建⼀个⽂件lib/init.js ,然后在这个init.js⽂件中,编写相关逻辑。这个⽂件的作⽤,仅仅是执⾏⼀遍,我们不期望这个⽂件暴露什么变量,所以没必要获取⽂件对象。那么这个时候,import关键字的另⼀个作⽤就体现出来了:main.js:
import './lib/init.js';
使⽤import直接引⽤⼀个⽂件时,会执⾏⼀遍这个⽂件,⽽不获取任何⽂件对象。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。