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

前言

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

导入导出方式⚔️⚔️

我们都知道最常见的几种导出方式无非是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. Go语言的100个错误使用场景(40-47)|字符串&函数&方法

    目录 前言 5. 字符串 5.5 无用的字符串转换(#40) 5.6 获取子字符串操作和内存泄漏(#41) 6. 函数和方法 6.1 不知道选择哪种类型的方法接受者(#42) 6.2 从来不使用命名的 ...

  2. 惠普HP519打印机缺色处理记录

    打印蓝色缺失, 黑色出墨不均匀 开盖检查, 发现蓝色墨水管路中间有断线, 拆开打印头后, 用随机器配的桔红色吸墨器吸墨. 之后重新开机还是缺色. 检查彩色打印头, 用浅浅的一层热水泡下方喷嘴, 黄色红 ...

  3. Java定时器(Timer)

    1.介绍 Timer和TimerTask是用于在后台线程中调度任务的java util类.简单地说,TimerTask是要执行的任务,Timer是调度器. 2.调度一次性任务 2.1 指定延迟后执行 ...

  4. win32 - 写入安全日志(AuthzRegisterSecurityEventSource和AuthzReportSecurityEvent)

    微软文档介绍说, 安全日志在其他两个重要方面与其他日志不同.首先,在默认配置中,它受到强大的访问控制列表(ACL)和特权检查的保护,这将可以读取其内容的个人的范围限制为本地系统,管理员和安全特权的持有 ...

  5. 硬件开发笔记(十二):RK3568底板电路电源模块和RTC模块原理图分析

    前言   做硬件做系统做驱动,很难从核心板做起,所以我们先依赖核心板,分析底板周围的电路,然后使用AD绘制原理图和设计PCB,打样我司测试底板,完成硬件测试,再继续系统适配,驱动移植,从而一步一步完善 ...

  6. 开源软件CVE_Search的配置与使用(详细)

    目录 项目介绍 环境配置 初始化cve_search 使用cve_search 简介 CVE: https://baike.baidu.com/item/CVE/9483464?fr=aladdin ...

  7. 【LeetCode贪心#10】划分字母区间(有涉及hash数组的使用)

    划分字母区间 力扣题目链接(opens new window) 字符串 S 由小写字母组成.我们要把这个字符串划分为尽可能多的片段,同一字母最多出现在一个片段中.返回一个表示每个字符串片段的长度的列表 ...

  8. JS中Date和时间戳转换

    <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="C ...

  9. Emqx高可用架构

    目录 优化前架构 主要问题 haproxy问题 优化后架构 优化功能点 emq版本升级 linux系统调优 haproxy调优 测试工具 依赖安装 配置erl环境变量 安装压测软件 测试指令与结果展示 ...

  10. TypeScript项目开发运行(即时编译、运行,所见所得)

    1.项目*.ts自动编译 $ tsc . --watch 2.项目本地web服务运行 $ npm install --save-dev webpack-dev-server npm install - ...