require 动态加载_require,exports,module.exports和import,export,export default

我们前端在开发过程中经常会遇到导入导出功能,

在导入时,有时候是require,有时候是import

在导出时,有时候是exports,module.exports,有时候是export,export default

今天我们对这些内容进行简单的介绍

import,export,export default

import,export,export default属于ES6规范

import

import 是在编译过程中执行 也就是说是在代码执行前执行,

比如说,import后面的路径写错了,在运行代码前就会抛错,

在编写代码时,import不是一定要写在js的最前面

import命令具有提升效果,会提升到整个模块的头部,首先执行。(是在编译阶段执行的) import是静态执行的 因为import是静态执行的,不能使用表达式和变量,即在运行时才能拿到结果的语法结构

比如,不能再if和else中使用import

再比如,import后的from的路径,可以是相对路径,可以是绝对路径,但是不能是根据变量得来的路径

//import 路径不可以为变量

var url = './output'

  import {

    a,

    b

  } from url//这么写会报错

//------------------

//import 的引入与否不能和代码逻辑向关联

let status= true

if(status){

     import {

    a,

    b

  } from url//这么写会报错

}

import可以使用as进行重命名

import 的有很多种导入方式,

  import foo from './output'

  import {b as B} from './output'

  import * as OBj from './output'

  import {a} from './output'

  import {b as BB} from './output'

  import c, {d} from './output'

导入的方式和导出有些关联,我们在下面说导出的时候,对以上这些导入方式进行逐一介绍

exoprt和export default

将exoprt和export default放在一起,因为它们关联性很大

简单说:export是导出,export default是默认导出

一个模块可以有多个export,但是只能有一个export default,export default可以和多个export共存

export default 为默认导出,导出的是用{}包裹的一个对象,以键值对的形式存在

导出的方式不同,导入的方式也就不同,

所以建议同一个项目下使用同一的导入导出方式,方便开发

export default解构以后就是export

通过两个直观的demo看下export和export default的区别

先看一段代码(export) 

output.js

const a = 'valueA1'

export {a}

input.js

import {a} from './output.js'//此处的import {a}和export {a},两个a是一一对应关系

console.log(a)//=>valueA1

留意上面的代码其中export {a}导出的a,和import {a}导入的a是同一个a

再看一段代码(export default)

const a = 'valueA1'

export default{a}

input.js

import a from './output.js'//此处的a和export default{a},不是一个a,

console.log(a)//=>{ a: 'valueA1' }

看下export default的栗子中的input.js,我们稍作改动

import abc from './output.js'//此处的a和export default{a},不是一个a,

console.log(abc)//=>{ a: 'valueA1' }

我们做了些改动,但是输出没有变化,import导入的是export default下的对象,叫什么名字都可以,因为只会存在一个export default

exoprt和export default混合使用

exoprt和export default在同一个模块中同时使用,是支持的,虽然我们一般不会这么做

看一个栗子

output.js

const a = 'valueA1'

const b = 'valueB1'

const c = 'valueC1'

const d = 'valueD1'

function foo() {

  console.log(`foo执行,c的值是${c}`);

}

export {a}

export {b}

export default { b,d,foo}

input.js

import obj, {a,b } from './output'

console.log(a); //=>valueA1

console.log(b); //=>valueB1

console.log(obj); //=>{ b: 'valueB1', d: 'valueD1', foo: [Function: foo] }

as 重命名

通过 exoprt和export default导出的在import引入时都支持通过as进行重命名

看个栗子

还是上面的那个output.js

const a = 'valueA1'

const b = 'valueB1'

const c = 'valueC1'

const d = 'valueD1'

function foo() {

  console.log(`foo执行,c的值是${c}`);

}

export {a}

export {b}

export default { b,d,foo}

input.js

import {a as A} from './output'

import {* as A} from './output'//这是不支持的

import * as obj from './output'

console.log(A); //=>valueA1

console.log(obj); //=>{ a: 'valueA1',default: { b: 'valueB1', d: 'valueD1', foo: [Function: foo] },b: 'valueB1' }

as后面的变量是你要在input.js中使用的

重点看这一部分

import {* as A} from './output'//这是不支持的

import * as obj from './output'

console.log(obj); //=>{ a: 'valueA1',default: { b: 'valueB1', d: 'valueD1', foo: [Function: foo] },b: 'valueB1' }

* 代表了所有,包括了export和export default导出的

我们之前说import{}和export{},是一一对应关系,所以在export导出的,在import{}不支持使用*

关于 import,export,export default先介绍到这里,我们继续

require,exports,module.exports(记得后面的s)

这是 AMD规范

require

require是运行时调用,所以require理论上可以运用在代码的任何地方

require支持动态引入

例如,这样是支持的

let flag = true

if (flag) {

  const a = require('./output.js')

  console.log(a); //支持

}

require路径支持变量

let flag = true

let url = './output.js'

if (flag) {

  const a = require(url)

  console.log(a); //支持

}

通过require引入,是一个赋值的过程

exports 与 module.exports

根据AMD规范

每个文件就是一个模块,有自己的作用域。在一个文件里面定义的变量、函数、类,都是私有的,对其他文件不可见。

每个模块内部,module变量代表当前模块。这个变量是一个对象,它的exports属性(即module.exports)是对外的接口。加载某个模块,其实是加载该模块的module.exports属性。

为了方便,Node为每个模块提供一个exports变量,指向module.exports。这等同在每个模块头部,有一行这样的命令。

const exports = module.exports;

所以说

以下两种写法等价

exports.a ='valueA1'

module.exports.a='valueA1'

前面说在每个模块提供一个exports变量,指向module.exports。

所以不能直接给exports赋值,赋值会覆盖

const exports = module.exports;

直接给exports赋值会切断exports和 module.exports的关联关系

看一个栗子

output.js

const a = 'valueA1'

const b = 'valueB1'

const c = 'valueC1'

module.exports = { c}

exports.b = b//当直接给 module.exports时,exports会失效

module.exports.a = a

input.js

  const obj = require('./output.js')

  console.log(obj); //=>{ c: 'valueC1', a: 'valueA1' }

继续看代码 output.js

//部分省略

exports.b = b//这样可以生效

module.exports.a = a

input.js

  const obj = require('./output.js')

  console.log(obj); //=>{ b: 'valueB1', a: 'valueA1' }

再看一段代码 output.js

//部分省略

module.exports = { c}

module.exports.a = a

input.js

  const obj = require('./output.js')

  console.log(obj); //=>{ c: 'valueC1', a: 'valueA1' }

当直接给 module.exports时,exports会失效

交叉使用

在ES6中export default 导出的是一个对象

在AMD中exports和module.exports导出的也都是一个对象

所以如果你手中的项目代码支持两种规范,那么事可以交叉使用的(当然不建议这么去做)

通过export导出的不一定是一个对象

demo1

output.js

//部分省略

module.exports = { c}

module.exports.a = a

inputj.s

import obj from './output'

import {a} from './output'

console.log(a);//=>valueA1

console.log(obj);//=>{ c: 'valueC1', a: 'valueA1' }

demo2

output.js

const a = 'valueA1'

const b = 'valueB1'

const c = 'valueC1'

function foo() {

  console.log(`foo执行,c的值是${c}`);

}

export {a}

export default {b,c,foo}

export {b}

input.js

  const a = require('./output.js')

  console.log(a); //=>{ a: 'valueA1',default: { b: 'valueB1', c: 'valueC1', foo: [Function: foo] }, b: 'valueB1' }

总结

require,exports,module.exports属于AMD规范,import,export,export default属于ES6规范require支持动态导入,动态匹配路径,import对这两者都不支持require是运行时调用,import是编译时调用require是赋值过程,import是解构过程对于export和export default 不同的使用方式,import就要采取不同的引用方式,主要区别在于是否存在{},export导出的,import导入需要{},导入和导出一一对应,export default默认导出的,import导入不需要{}exports是module.exports一种简写形式,不能直接给exports赋值当直接给module.exports赋值时,exports会失效

438aab90317c72f9992a8d50540e4ab0.png

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

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

相关文章

Newbe.ObjectVisitor 0.4.4 发布,模型验证器上线

Newbe.Claptrap 0.4.4 发布,模型验证器上线。更新内容完全基于表达式树的模型验证器本版本,我们带来了基于表达式树实现的模型验证器。并实现了很多内置的验证方法。我们罗列了与 FluentValidation 比较的情况:Build in ValidatorsFluentVali…

算法题目中经典问题(易错点)

算法题目中经典问题.易错点 (一).二维数组的传参问题1.方法一:形参为二维数组并给定第二维长度2.方法二:形参为指向数组的指针并给出数组长度3.二维数组定义为全局变量(二).多组测试控制台数据,输入到文件结束(三).进制转换中的小问题1.使用字符串来存储,每一位(四).结构体…

dotnet core 应用是如何跑起来的 通过AppHost理解运行过程

在 dotnet 的输出路径里面,可以看到有一个有趣的可执行文件,这个可执行文件是如何在框架发布和独立发布的时候,找到 dotnet 程序的运行时的,这个可执行文件里面包含了哪些内容在回答上面的问题之前,请大家尝试打开 C:\…

算法题目——整数划分(HRBUST-2004)

题目链接:HRBUST-2004 递归法: 1.当n1时,此时只有1种解{1}; 2.当m1时,此时也只有1种解{1,1,1, … 3.当n> m时,要分为最大数包含m和不包含m两种情况。 ●包含m:此时就是{mx1,2…}. 其中x1x23.… n-m, 就相当于求和为n-m,最…

dotnet core 应用是如何跑起来的 通过自己写一个 dotnet host 理解运行过程

在上一篇博客是使用官方提供的 AppHost 跑起来整个 dotnet 程序。本文告诉大家在 dotnet 程序运行到托管代码之前,所需要的 Native 部分的逻辑。包括如何寻找 dotnet 运行时,如何加载运行时和框架然后跑起来业务端的 dll 文件的逻辑在上一篇博客告诉大家…

android虚线边框_Android实现代码画虚线边框背景效果

实现如下边框效果:虚线画效果,可以使用Android中的xml来做。下面话不多说,直接上代码:android:id"id/coupon_popup"android:layout_width"320dp"android:layout_height"200dp"android:layout_margi…

算法题目——多米诺骨牌问题(POJ-2663)

题目链接:POJ-2663 设有形状一样的多米诺牌,每张牌恰好覆盖棋盘上相邻的两个方格,即一张多米诺牌是一张 1 行 2 列或者 2 行 1 列的牌。那么,是否能够把 32 张多米诺牌摆放到棋盘上,使得任何两张多米诺牌均不重叠&…

【招聘(上海)】 坚果云 招聘Windows客户端(WPF方向)

岗位职责:1、负责坚果云在Windows 10平台上WPF应用的开发与维护;2、负责基于WPF的Windows平台核心客户端产品开发,维护与测试;3、WPF桌面应用将具备丰富的文件展示和文件管理功能,其中与操作系统交互, 复杂…

三相全桥整流电路_三相桥式全控整流电路

收稿日期:2002-04-12作者简介:陈强(1976—),男,硕士研究生1三相桥式全控整流及单相交流调压实验装置的研制陈强,杨旭,王兆安(西安交通大学电气工程学院,西安710049)摘要:本文结合具体的三相全控整流电路的研制,介绍了以国产集成芯片KJ004和KJ041为中心的触发电路的工作过程及主…

算法题目——Problem A 二进制(北邮机试)

Problem A 二进制 题目描述 32位二进制数 X ,对其进行X+1,X+3操作,并输出。注意不能忽略前导0。 输入 第一行,一个整数 T ,代表测试数据组数。接着 T 行,输入32为二进制数输出对每组测试数据。 输出 两行,第一行为X+1,第二行为X+3. 测试样例 输入 2 00000000000000000000…

merge函数_c语言中的merge函数

展开全部merge()是C标准库的函数,主要实现函数的排序和合并,不仅仅是合并,具体要求参e5a48de588b63231313335323631343130323136353331333431373261照标准库。#include"stdafx.h"#include#include#include#includeusingnamespacest…

算法题目——求众数

在c中有两个关联容器&#xff0c; 第一种是map&#xff0c;内部是按照key排序的&#xff0c;从小到大 第二种是unordered_map&#xff0c;容器内部是无序的&#xff0c;使用hash组织内容的。 #include<iostream> #include<map> #include<algorithm> using n…

2020武汉dotNET俱乐部分享交流会圆满结束

经过长达2个多月的准备&#xff0c;终于在12月5日圆满的举行了武汉首次dotNET俱乐部线下分享交流活动。我们一共精心准备了3个目前比较热门的主题&#xff0c;分别如下&#xff1a;Jason分享的《ABP开发框架的扩展应用》Leo分享的《基于Kubernetes的DevOps平台应用》Eleven分享…

r语言remarkdown展示图_R语言—自动报告Markdown笔记

一句话介绍&#xff1a;Markdown是一种轻量级标记语言&#xff0c;内容是代码与文本的混合&#xff0c;类似HTML,但语法比HTML简单。&、比如&#xff1a;如果你写&#xff1a; 4<5 ,Markdown将会把他转换为&#xff1a; 4<5换行符&#xff1a;在Markdown中依然使用&a…

算法——常用的数据结构/模板/基础知识

常用的数据结构/模板/基础知识(一)c——优先队列(priority_queue)最大堆和最小堆的写法(二)c中的全排列函数next_permutation()(三)迭代器的使用(四)数学知识数列求和(五)求最大公约数和最小公倍数(六)将数值型数据转化为string 类型(一)c——优先队列(priority_queue) 最大堆…

对 精致码农大佬 说的 Task.Run 会存在 内存泄漏 的思考

一&#xff1a;背景 1. 讲故事这段时间项目延期&#xff0c;加班比较厉害&#xff0c;博客就稍微停了停&#xff0c;不过还是得持续的技术输出呀&#xff01;园子里最近挺热闹的&#xff0c;精致码农大佬分享了三篇文章&#xff1a;为什么要小心使用 Task.Run [https://www.c…

算法题目——爬楼梯(动态规划)

题目链接:70.爬楼梯 类似题目:1646.获取生成数组中最大值 本题大家如果没有接触过的话,会感觉比较难,多举几个例子,就可以发现其规律。 爬到第一层楼梯有一种方法,爬到二层楼梯有两种方法。 那么第一层楼梯再跨两步就到第三层 ,第二层楼梯再跨一步就到第三层。 所以到…

jpi多表联查_数据库两表联查、多表联查,多重联查

表连接查询【小编用的是Oracle数据库&#xff0c;Oracle数据库区分表名与字段名的大小写&#xff0c;所以大家进行查询的时候记得注意双引号哟~】有表表名&#xff1a;AAA 字段&#xff1a; id name tag表名&#xff1a;BBB 字段&#xff1a; id ban qq表名&#xff1a;AABB字段…

GraphQL:从头开始

GraphQL 既是一种用于 API 的查询语言也是一个满足你数据查询的运行时。GraphQL 对你的 API 中的数据提供了一套易于理解的完整描述&#xff0c;使得客户端能够准确地获得它需要的数据&#xff0c;而且没有任何冗余&#xff0c;也让 API 更容易地随着时间推移而演进&#xff0c…

iar 看时序_IAR 硬件仿真查看运行时间

最近做STM8的项目&#xff0c;IDE从Keil变成IAR非常不习惯&#xff0c;就像用惯VS用回VC一样。调试软件延时函数&#xff0c;想看一下运行效果&#xff0c;竟然无从下手(Keil有一个查看运行时间的窗口)&#xff0c;网上都是用Simulator软仿真的查看&#xff0c;换成STLINK硬仿真…