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

前言

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

导入导出方式⚔️⚔️

我们都知道最常见的几种导出方式无非是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. 2023年多校联训NOIP层测试3+「SFCOI-3」Sadness Fan Club Round 3

    2023年多校联训NOIP层测试3 T1 数列变换 \(10pts\) 考虑暴力,发现 \(f\) 数列进行一次变换 \(A\) ,再进行一次变换 \(B\) 后,恢复成了原数列: \(f\) 数列进 ...

  2. NC201613 Jelly

    题目链接 题目 题目描述 Nancy喜欢吃果冻! Nancy钻进了一个 \(n \times n \times n\) 的果冻里,她想从(1,1,1)一路上.下.左.右.前.后六个方向吃到(n,n,n ...

  3. 轻松玩转makefile | 变量与模式

    前言 本文通过简单的几个示例,以及对同一个Makefile进行几个版本的迭代,帮助快速的理解变量和模式规则的使用. 1.回顾 在上一篇文章中,我们使用Makefile编译fun.c和main.c这两个 ...

  4. 解锁Mysql中的JSON数据类型,怎一个爽字了得

    引言 在实际业务开发中,随着业务的变化,数据的复杂性和多样性不断增加.传统的关系型数据库模型在这种情况下会显得受限,因为它们需要预先定义严格的数据模式,并且通常只能存储具有相同结构的数据.而面对非结构 ...

  5. 使用CNN实现MNIST数据集分类

    1 MNIST数据集和CNN网络配置 关于MNIST数据集的说明及配置见使用TensorFlow实现MNIST数据集分类 CNN网络参数配置如下: 原始数据:输入为[28,28],输出为[1,10] ...

  6. 【OpenGL ES】绘制三角形

    1 前言 1.1 设置顶点属性 ​ 顶点有位置.颜色等属性,可以通过 glVertexAttribPointer 设置顶点的属性. void glVertexAttribPointer( int in ...

  7. Java Socket编程系列(一)开发一次性会话的Server和Client

    关于什么是Socket: A socket is one end-point of a two-way communication link between two programs running ...

  8. Java并发编程实例--19.在一个锁中使用多个条件

    一个锁可能关联了一个或多个条件.这些条件可以在Condition接口中声名. 使用这些条件的目的是去控制一个锁并且可以检查一个条件是true或false,如果为false,则暂停直到 另一个线程来唤醒 ...

  9. 如何用Apipost校验响应结果

    数据校验的意义 我们可以通过 json-schema 预先定义接口的数据返回格式,当接口完成后,我们可以通过匹配 实际响应结果 和 预先定义的接口格式 ,来发现接口问题.如下图: 数据校验的设置 我们 ...

  10. 【Android 逆向】r0zapataNative.apk 破解

    1. apk 安装到手机,需要输入内容,随便输入,提示fail... 2. apk 导入到jadx中查看一下 MainActivity.java String textData = "b2F ...