吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1143|回复: 9
收起左侧

[学习记录] 【前端学习】-彻底理解JavaScript ES6中的import和export

[复制链接]
cheekhan 发表于 2023-4-8 11:26
本帖最后由 cheekhan 于 2023-4-8 13:50 编辑

0、前言

    前端工程,在最早的时候是没有模块的概念的。随着前端工程的发展,前端开发也越来越规范化,更像是软件工程了。那么随之而来的,为了解决工程化的问题,就引入了模块的概念。
    但是在早期,因为ecmascript原本是没有模块语法的,所以采用的都是社区的各种版本协议,其中影响最深的,就是nodejs使用的CommonJS规范
    当模块化的概念越来越重要的时候,在es6中,引入了模块的语法:import ,下面我们简单了解一下,import是怎么使用的。以下内容,参考 官方文档
1、export
    一个js文件,可以理解成一个模块,这个模块可以被任意其他的模块引入,引入的结果,就是对这个模块进行执行后,所持有的对象。
    那么随之而来就有一个问题,文件模块被引入后,所有的东西,都是在自己的作用域中,主动发起引入行为的那个文件,虽然获取到了被引入的对象,但是并不能访问作用域里的东西,所以提供了export,来决定一个模块对外暴露什么东西。
    export的作用,就是用于从模块中导出函数、对象或原始值,以便其他程序可以通过 import 语句使用它们.在import 一个文件的时候,会获取这个文件对象,默认是空对象,代表我们不能访问文件的东西。使用export,来给这个对象添加内容用法,module1.js :
   
[JavaScript] 纯文本查看 复制代码
function f1 (){
    console.log("module - 1 : functino 1")
}

let b = {
    name:"test_obj"
}

let str = "hell绿绿绿"

export {
    f1,b,str
}

module1.js :
function f1 (){    console.log("module - 1 : functino 1")}let b = {    name:"test_obj"}let str = "hell绿绿绿"export {    f1,b,str}
    在main.js 中进行引入
[JavaScript] 纯文本查看 复制代码
// 先忽略 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 :
[JavaScript] 纯文本查看 复制代码
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导出的内容完全一致。
3、文件导出的总结
   那么到这里,我们明白了,一个js文件被当做一个模块引入,会暴露为一个对象(也就是被导入后,可以当做一个对象来操作)。
    export的作用,是在这个文件对象中添加属性,export出来的东西,全部会添加到文件对象中。
    export default 的作用,是给文件对象的 default 属性,添加值。
4、import
    在上面的例子中,我们明白了模块对外暴露的都是什么东西,那么我们如何来使用文件对外暴露的东西呢?
    首先我们已经明白,文件对象是什么。
    4.1导出整个文件对象
        那么首先,我们就导出整个文件对象,看一看是什么样子的。就是上面例子中,我们使用到的语法,import * 来导出文件模块的所有接口,as m_name 来指定一个命名空间对象。
        main.js :
        
[JavaScript] 纯文本查看 复制代码
import * as m1 from "./m1.js"
console.log(m1)

        示例中的m1 命名空间对象,可以访问到文件对象的所有对外接口,包括export,和export default。

    4.2 导出export的部分接口
        在实际开发中,我们并不需要导出所有的接口。例如在vue项目中,使用某个组件库中的某个组件,我们只需要引入这一个组件,不必要引入所有组件。我们知道,import 导出的是整个文件对象,那么我们直接在 import 语句中,对这个对象进行解构,就可以获得其中某一部分接口:
main.js :
        
[JavaScript] 纯文本查看 复制代码
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 文件内容为:
      
[JavaScript] 纯文本查看 复制代码
import d from "./m1.js"
console.log(d)

       打印出来,惊奇的发现,d 竟然和 export default 的内容一样。
       所以,现在可以这么理解,所谓的默认导入,就是毫无花哨的直接导入一个模块,然后赋值给一个命名空间,这种时候,这个命名空间,持有的就是 文件对象的default 对象,也就是export default 出来的东西。其实,默认导入可以理解为也是解构的一个语法糖(仅仅用作理解,实际是语法错误的):
[JavaScript] 纯文本查看 复制代码
import d from "./m1.js"  可以等价为 import {default as d} from "./m1.js"

5、import动态导入
    还有一种高端的玩法,在项目中也是很有用处的。
    import不光是一个关键字,同时也是一个函数,函数的参数是需要导入模块的路径,函数返回一个promise对象。
[JavaScript] 纯文本查看 复制代码
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 :
[JavaScript] 纯文本查看 复制代码
import './lib/init.js';

    使用import直接引用一个文件时,会执行一遍这个文件,而不获取任何文件对象。

免费评分

参与人数 2吾爱币 +2 热心值 +2 收起 理由
0106yingzi + 1 + 1 热心回复!
blindcat + 1 + 1 谢谢@Thanks!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

Tongmmy 发表于 2023-4-8 12:40
本帖最后由 Tongmmy 于 2023-4-8 12:42 编辑

如何使用ES6的Map和Set数据结构?
忆魂丶天雷 发表于 2023-4-8 12:46
这图片水印都叠多少层了 文章不排版 转载也不说明
云烟成雨 发表于 2023-4-8 13:17
beyondchampion 发表于 2023-4-8 13:35
还是支持下吧,多输出点
 楼主| cheekhan 发表于 2023-4-8 13:40
抱歉抱歉,不是转载的,是以前写过的文章,直接复制过来,排版乱了
 楼主| cheekhan 发表于 2023-4-8 14:10
Tongmmy 发表于 2023-4-8 12:40
如何使用ES6的Map和Set数据结构?

[JavaScript] 纯文本查看 复制代码
const s = new Set(); // 创建一个set对象
s.add(1); // 向set插入数据

const m = new Map(); // 创建一个map
m.set({}, {}) ; // 向map添加数据
lovelyelfpop 发表于 2023-4-8 14:33
多谢楼主分享这么有用的东西
yizhimei123 发表于 2023-4-8 15:00
支持一下,鼓励鼓励!
qqa911 发表于 2023-4-8 20:25
支持一下
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-24 23:35

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表