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

前言

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

导入导出方式⚔️⚔️

我们都知道最常见的几种导出方式无非是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

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

记录--你真的能区分JavaScript的各种导入导出方式吗?的更多相关文章

  1. MySQL问题记录——导入导出权限设置

    MySQL问题记录——导入导出权限设置 摘要:本文主要记录了在使用MySQL的过程中导入导出权限设置时遇到的问题以及解决方案. 相关日志 [Note] --secure-file-priv is se ...

  2. JavaScript Array 对象方法 以及 如何区分javascript中的toString()、toLocaleString()、valueOf()方法

    1.concat() 2.join() 3.pop() 4.push() 5.reverse() 6.shift() 7.unshift() 8.slice() 9.sort() 10.splice( ...

  3. 我想这次我真的理解了 JavaScript 的单线程机制

    今天面试的时候被问到一个问题,是关于 JS 异步的.当时我脑海中闪过了一个单线程的概念,但却没有把真正的原理阐述清楚.所以回来特意重新回顾了前面单线程和异步相关的一些知识点. 虽然之前学习的时候也接触 ...

  4. JavaScript动态加载script方式引用百度地图API 拓展---JavaScript的Promise

    上一篇博客JavaScript动态加载script方式引用百度地图API,Uncaught ReferenceError: BMap is not defined 这篇文章中我接触到一个新的单词:Pr ...

  5. mysql数据库导入导出 查询 修改表记录

    mysql数据导入导出: 导入: 把系统的文件的内容,保存到数据库的表里 导入数据的基本格式:mysql> load data infile "文件名" into table ...

  6. Lua和C++交互 学习记录之九:在Lua中以面向对象的方式使用C++注册的类

    主要内容转载自:子龙山人博客(强烈建议去子龙山人博客完全学习一遍) 部分内容查阅自:<Lua 5.3  参考手册>中文版 译者 云风 制作 Kavcc vs2013+lua-5.3.3 在 ...

  7. JavaScript的3种继承方式

    JavaScript的继承方式有多种,这里列举3种,分别是原型继承.类继承以及混合继承. 1.原型继承 优点:既继承了父类的模板,又继承了父类的原型对象: 缺点:不是子类实例传参,而是需要通过父类实例 ...

  8. javascript模块导入导出

    第一次知道javascript有模块的概念通常都是使用<script>标签进行引入,不过只能在html文件上使用 增加的模块就如同php里的include.require可以使用引入的内容 ...

  9. 【转】SVG与HTML、JavaScript的三种调用方式

    原文:https://www.cnblogs.com/guohu/p/5085045.html SVG与HTML.JavaScript的三种调用方式 一.在HTMl中访问SVG的DOM 1 2 3 4 ...

  10. 你真的搞懂ES6模块的导入导出规则了吗

    前言 模块作为ES6规范的核心部分之一,在实际项目开发中经常会看到它的身影,那么我们是否真正了解它的相关规则呢,今天就带大家一起了解一下模块的导入导出规则 导入 ES6模块的导入(即import)大致 ...

随机推荐

  1. sanic和tornado的简单性能测试

    操作系统 : CentOS7.3.1611_x64 Python 版本 : 3.6.8 tornado版本:6.0.2 sanic版本:19.9.0 CPU : Intel(R) Core(TM) i ...

  2. 鹏程杯子2023 pwn

    主要就是修改stdin的最后几位,使他变为write,然后泄露libc,为所欲为即可. 本人是卡在不知道stdin那里可以修改. 然后使用一下jmp qword rbp这个gadget 0x400a9 ...

  3. P5943 [POI2002] 最大的园地 题解

    题目传送门 前置知识 单调栈 简化题意 在一个 \(n \times n\) 的正方形内找到最大的由 \(0\) 组成的子矩形的面积. 解法 令 \(f_{i,j}(1 \le i,j \le n)\ ...

  4. 【Unity3D】Unity与Android交互

    1 前言 ​ 本文主要介绍 Unity 打包发布 Android apk 流程.基于 AndroidJavaObject(或 AndroidJavaClass)实现 Unity 调用 Java 代码. ...

  5. 【OpenGL ES】正方形图片贴到圆形上

    1 前言 ​ 纹理贴图 中介绍了将矩形图片贴到矩形模型上,本文将介绍:在不裁剪图片的情况下,将正方形的图片贴到圆形模型上. ​ 思考:实数区间 [0, 1] 与 [0, 2] 的元素可以建立一一映射关 ...

  6. redis7源码分析:redis 多线程模型解析

    多线程模式中,在main函数中会执行InitServerLast void InitServerLast() { bioInit(); // 关键一步, 这里启动了多条线程,用于执行命令,redis起 ...

  7. 在Windows10中安装解压版MySQL 8.X

    在Windows 10中安装解压版的MySQL 8.X实现步骤: 1.下载MySQL安装包:https://dev.mysql.com/downloads/mysql/ 解压到指定目录,比如:D:\o ...

  8. 深入解析Python并发编程的多线程和异步编程

    本文分享自华为云社区<Python并发编程探秘:多线程与异步编程的深入解析>,作者:柠檬味拥抱. 在Python编程中,多线程是一种常用的并发编程方式,它可以有效地提高程序的执行效率,特别 ...

  9. Vue 上传前获取图片宽度尺寸和大小

    参考资料:https://www.cnblogs.com/wyx-remove-love/p/wyx-20190626-1.html    https://blog.csdn.net/qq_22771 ...

  10. 对于Celery原理的简单理解

    参考博客: https://www.cnblogs.com/forward-wang/p/5970806.html https://blog.csdn.net/cuomer/article/detai ...