记录--你真的能区分JavaScript的各种导入导出方式吗?

news2024/10/5 17:28:40

这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助

前言 🛰🛰

我们在无论是在查阅别人的代码,还是在实际项目开发的过程中,肯定都会使用导入导出的功能,有时候我们会搞混这几种方式到底有什么区别,今天我们就来细致的区分一下:

导入导出方式⚔️⚔️

我们都知道最常见的几种导出方式无非是exportexportsexport defaultmodule.exports这几种,常见的导入方式则就是importrequire,那么他们到底有什么区别呢?我们一起来看一下:

最为新手小白的我们在看到第一眼的时候肯定会一脸懵,其实我们可以将他们根据不同的JavaScript规范来分开来看

export和export default

exportexport default是ES6的规范

这两种方式其实没有什么本质的区别,我们一起来看一下示例:

使用export default这种导出方式叫做默认导出(暴露)

var name = "小明";
var fun = function () {
  console.log(name);
};
export default { name, fun };
-----------------------
export default  function() {
    console.log ('export 不能这样子')
}

这里我们可以看到我们声明了一个函数,里面打印了变量name的值,然后我们使用export default导出了一个函数对象,也可以直接默认的导出一个函数。

值得注意的是,在一个js文件中只能有一个export default,不能重复的书写,否则会报错,而我们在接收这个导出的对象的中的内容的时候我们需要使用import来进行导入。

几个容易错误的点:

export default const name3 = 'error'; //这样导出的方式是错误的
-----------------------
var name3="小红";
export default name3;//这样是正确的

当然接收导出的值的时候也需要注意

import接收导出的值:

我们在使用export default导出的时候我们在接受值的时候需要注意

import text from "app.js"

我们假设需要导出内容的是app.js这个文件,我们在接收的时候可以自己定义一个变量名称,就像示例中的test,当然如果想要获取导出对象中的内容就可以使用解构的语法。这一点与export是有区别的

export导出示例:

var age=20; var open=true;
export {age,open} //等同于下边
export {age}
export {open}
export const fun=()=>{console.log("hhh")}
export const age1 = 23 //let 也行

在export中我们可以一口气导出多个变量或者对象,函数等而且我们也可以向最后一行代码那样在导出的时候定义变量名称,有一点需要注意使用export导出的内容必须有名称,就比如导出函数的时候不能像默认暴露那样直接导出一个匿名函数。

导入时的注意点:

import {age,open} from "app.js"
import {fun} from "app.js"
import {age1 as age2} form "app.js"

这里要注意我们在导入的时候一定要加上花括号,而且花括号中的名称必须和导出的变量或者函数名称一样,这一点时与export default不同的,还有我们导入在age1可以将其重命名为age2.

module.export 和exports

首先这两种方式是基于Common.js的规范来定义的,而这个规范是在Node.js中,因此这两种方式主要是在Node.js中使用

在上下文中提供了exports对象用于导出当前模块的方法或者变量,他是唯一导出的出口,当然在模块中还存在module对象,他代表模块自身,exports就是module的属性(默认的值是一个空对象),而在Node.js中一个文件就是一个模块,所以我们导出

在模块之中上下文提供require来引入外部的模块,

首先我们先来查看module.exports这种方式。

const a = 1;
const fun = () => {
  console.log(2);
};
module.exports = { a, fun };
var req = require ('../app.js');
console.log(req.a1,req.a)
//1 [Function: fun]

我们在导出的时候需要注意导出的先后循序,当然这也可以当作面试出题,比如一下这几行代码导出的先后顺序不一样就会打印出不同的值,我们可以一起来看一下:

const a = 1;
const fun = () => {
  console.log(2);
};
// console.log(fun);
module.exports.a2 = 4;
module.exports = { a, fun };
const req = require("./module.exports");
console.log(req.a, req.fun, req.a2);
//1 [Function: fun] undefined

为什么会有undefined呢?

我们在开始的时候说了我们其实发通过exports这中方式默认是导出一个空的对象,所以我们通过module.exports.a2这种方式导出其实是在这个空的对象上面添加了一个a2属性并且值为4,但是下来通过module.exports导出的时候,我们通过赋值的方式将之前的对象给覆盖了,因此之前的a2值就没有了,

同样如果我们给这两种导出的方式换一下先后顺序,比如我们这样写

module.exports = { a, fun };
module.exports.a2 = 4;

我们就可以获取到a2的值,因为我们先进行了对象的覆盖,然后在新对象上面增加了一个a2的属性并且值为4。

exports导出

其实exportsmodule.exports的一个引用,可以认为是 var exports = module.exports

我们来讲解一下他们二者的区别:

  1. 直接赋值和替换对象的行为不同:

    • module.exports = value;:将 module.exports 直接赋值为一个新的值,这个新值会成为模块的导出内容。例如:module.exports = { a: 1 };,地址发生了改变直接替换之前的所有内容。
    • exports.key = value;:将一个新的属性和值添加到 exports 对象中。例如:exports.a = 1;
  2. module.exports 优先级高于 exports

    • 如果在模块中同时使用 module.exportsexports,那么最终导出的内容以 module.exports 为准。也就是说,exports 对象的变化不会影响最终导出的内容。

使用exports的误区

直接上一个例子来给大家演示一下:

const a = 1;
const fun = () => {
  console.log(2);
};
exports.a3 = { a, fun };
const req = require("./module.exports");
console.log(req);
console.log(req.a, req.fun);
//{}
//undefined undefined

为什么会出现这种情况呢?

我们知道在最初的时候module.exportsexports最初是指向同一个对象,也就是他们的地址是相同的,但是在这里我们通过对象给exports赋值的时候实际上已经改变了exports的地址,但是module.exports还是默认的地址指向还是一个空的对象,而我们执行导出的时候实际上还是通过module.exports,所以最终还是导出了一个空对象。

因此我们在module.exportsexports混用的时候要注意地址的问题,不要直接改变module.exports的地址,如果直接改变了,那么exports的操作就会不生效,如果你想混用,那最好全部用module.exports.x = xxx和exports.xx = xxxx这种写法,这样的写法就没有改变默认的地址。

exports.a2 = 4;
module.exports.fun = fun;
module.exports.a = a;
--------------------
const req = require("./module.exports");
console.log(req);
//{ a2: 4, fun: [Function: fun], a: 1 }

本文转载于:

https://juejin.cn/post/7241111319591452729

如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/618304.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

有哪些比较好的游戏图标推荐

游戏图标设计在游戏UI中占有非常重要的地位。例如,当我们看到一个游戏的启动图标时,很容易区分它是哪个游戏。设计游戏图标不仅是一个图形,也是一个标志。 本文将通过各种游戏图标设计素材分享游戏图标的类别和设计游戏图标的思考。 1. 游戏…

基于SSM+JSP的大学生校园兼职系统设计与实现

博主介绍: 大家好,我是一名在Java圈混迹十余年的程序员,精通Java编程语言,同时也熟练掌握微信小程序、Python和Android等技术,能够为大家提供全方位的技术支持和交流。 我擅长在JavaWeb、SSH、SSM、SpringBoot等框架下…

wsl连接usb设备,以及挂载u盘

目录 wsl连接usb设备 安装usbinpd-win 配置 在kali中做写的配置 在wsl中的配置 在kali中查看附加结果 报错 挂载u盘,查看u盘的内容 wsl连接usb设备 安装usbinpd-win winget install --interactive --exact dorssel.usbipd-win 配置 在kali中做写的配置 s…

Java 21 将不再有public static void main !

之前的Java是这样: Java 21会是这样: 看到这个消息,我最大的感受是: 卧槽,怎么就Java 21了?!我还在用Java 8 呢! 实际上,从Java 8 到Java 21,中间也就是Java…

“Pull”和“Push”支付的区别

下图展示了“Pull”和“Push”支付的工作原理。 当我们在商家处刷信用卡/借记卡时,这是一种“Pull”支付,资金从持卡人的账户发送到商家。商家从持卡人的账户中取款,而持卡人批准交易。 通过Visa Direct或Mastercard Send,推送支付…

WebRTC实战 | 视频云

前言 WebRTC是当前实时通信领域的重要技术之一,具有广泛的应用前景。可以实现音频、视频和数据的实时传输。支持点对点通信、多方会议、屏幕共享等多种应用场景,同时具有高质量、低延迟、强安全性等特点,是开发实时通信应用的理想选择。可以应…

从“嘿,Siri”到元宇宙,苹果还有多远距离要走?

‍数据智能产业创新服务媒体 ——聚焦数智 改变商业 在当前的科技浪潮中,元宇宙的概念凭借其无限的想象力和可能性,像一颗耀眼的新星吸引着世界的目光。巨大的发展潜力,吸引着一波又一波的企业,前赴后继地向元宇宙发起冲锋。 在这…

27.打包项目

目录 1 打包成dist 2 flask配合dist 3 以文件形式打开 1 打包成dist 项目路径下输入 npm run build 在项目路径下会出现一个dist 打包后直接双击打开index.html是没有用的 因为你双击打开是file协议,你需要一个http协议 2 flask配合dist 我们可以搞一个fla…

「企业信息架构」EA874:信息架构治理概述

信息治理是一个程序,它实现决策权和支持机制,以确保整个企业信息的准确性、完整性、一致性、可访问性和安全性。为了维持信息治理,需要在业务(而不是IT)中确定和建立几个角色。这三个角色可能单独存在,也可…

分布式光伏消纳的微电网群共享储能配置策略研究(Matlab代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…

【AUTOSAR】Bootloader说明(四)---- 升级主函数

刷新主函数uds_refresh_main() 当执行完初始化后,DSP进入刷新主函数。 主函数是一个无穷循环函数,完成诊断消息的接收、处理,诊断状态的刷新等。 函数原型 void bblk_normal_isr(void) 函数作用 完成看门狗服务,清楚定时器中…

如何在ImageSpan上面绘制文本?

简介:TextOnImageSpan 前阵子碰到一个需求:在文本中内嵌图标,并在图标上面绘制特定文本。很自然就会想到用SpannableString去实现,但经过一系列的研究捣鼓,发现根本就没有能在图标上绘制文本的span类,于是乎…

单马达可换档六足机器人前进功能的实现

1. 运动功能说明 本文示例将实现R046样机单马达可换档六足机器人前进的功能。 2. 结构说明 本样机只有一个圆周舵机,却可以通过换挡机构实现前进和转向两种行走姿态。 样机由一个圆周舵机带动一个等速齿轮组(下图所示两枚蓝色齿轮)&#xff0…

C#,码海拾贝(26)——求解“一般带状线性方程组”之C#源代码

在大型稀疏方程组中,最常见的是带状方程组,其系数矩阵是带状矩阵,非零元素仅集中在对角线附近的带状区域内。 特别的,当上下带宽相等时我们A称方程组为等带宽方程组。总带宽为3的等带宽方程组我们又叫三对角方程组。 using Syste…

如何在 Elasticsearch 论坛/社群上提出高质量的技术问题?

在网络的海洋中寻求帮助,有时可能会让你感到茫然。你可能已经准备好详细描述你的问题,但如果你不知道如何有效地提问,你可能会发现自己在等待回答时感到挫败。 这篇文章的目标是为你提供一些提示,让你更快地获取你在论坛上的技术问…

数据库管理-第八十二期 EMCC升级教程(20230606)

数据库管理 2023-06-06 第八十二期 EMCC升级教程1 升级EMCC1.1 升级概览1.2 拷贝相关文件1.3 升级OPatch1.4 升级OMSPatcher1.5 升级WLS1.6 升级OMS 2 升级Agent2.1 升级概览2.2 拷贝相关文件2.3 安装或升级AgentPatcher2.4 升级agent 3 升级Oracle数据库ASH包总结 第八十二期 …

2. 分布式文件系统 HDFS

2. 分布式文件系统 HDFS 1. 引入HDFS【面试点】 问题一:如果一个文件中有 10 个数值,一行一个,并且都可以用 int 来度量。现在求 10 个数值的和 思路: 逐行读取文件的内容把读取到的内容转换成 int 类型把转换后的数据进行相加…

一文打通基于注解管理Bean

目录 开启组件扫描 情况一:最基本的扫描方式 情况二:指定要排除的组件 情况三:仅扫描指定组件 使用注解定义 Bean Autowired注入 ①场景一:属性注入 ②场景二:set注入 ③场景三:构造方法注入 ④…

Hbase安装指南

Hbase简介 HBase是一个高可靠性、高性能、面向列、可伸缩的分布式存储系统,利用HBase技术可在廉价PC Server上搭建起大规模结构化存储集群。 HBase是Google Bigtable的开源实现,类似Google Bigtable利用GFS作为其文件存储系统,HBase利用Had…

Java基础学习+面向对象(一)

一,基础概念介绍 1.1Java跨平台原理(一次编译,处处运行) Java 源代码经过编译,生成字节码文件,交由 Java 虚拟机来执行,不同得系统有不同得JVM,借助JVM 实现跨平台。就比如说我们在 Windows 下…