首页 > 其他分享 >require()、import、import()有哪些区别?

require()、import、import()有哪些区别?

时间:2023-11-14 22:44:26浏览次数:31  
标签:console log 哪些 require js num 模块 import

require()、import、import()是我们常用的引入模块的三种方式,代码中几乎处处用到。如果对它们存在模糊,就会在工作过程中不断产生困惑,更无法做到对它们的使用挥洒自如。今天我们来一起捋一下,它们之间有哪些区别?

 

一、前世今生

学一个东西,先弄清楚它为什么会出现、它的发展历史、它是做什么的,是很有必要的。看似与技术无关,却很有助于你对技术的理解。

require():

require()是CommonJS引入模块的函数。CommonJS是一种规范,主要用于nodejs,无法用于浏览器端。它是规范,而不是语法。本质上,它是在JS本身不支持模块的情况下,程序员发挥聪明才智,模拟出来的模块系统,在语言层面没有对JS做任何改动。它的原理实际上还是立即执行函数(IIFE)。

import:

JS在设计之初极为简单,没有模块系统,但开发中对模块化的需求却与日俱增。终于,ES6正式在语言标准的层面,引入了模块系统。import就是ES6的模块引入语句,作为ES6本身的语法,只要能写ES6的地方,都能使用它。它最大的特点,是静态引入,在编译时完成模块加载。这带来了加载效率高、静态分析等好处。

require()对比import,类似于VUE之于JS,对比ES6之于ES5的关系。

import():

相比require(),import好处多多,却也丢失了动态引入的优点,即在运行时根据实际需要选择引入模块。怎么办呢?

在ES2020中,引入了import()函数,它和require()一样是动态加载,不同的是,它是异步的,返回一个Promise对象,而require()是同步的。

 

二、缓存方式

(1)先来回答一个面试中常问的问题,一个模块多次引入,会执行几次?

require():

// 2.js
console.log('模块执行开始');
let num = 1;
module.exports = { num };
console.log('模块执行结束');

// testRequire.js
let a = require('./2.js');
let b = require('./2.js');
console.log(typeof a); console.log(a === b); // 执行结果 // 模块执行开始 // 模块执行结束
// object // true

import:

// 1.js
console.log('模块执行开始');
export let num = 1;
console.log('模块执行结束');

// testImport.js
import * as a from './1.js';
import * as b from './1.js';
console.log(typeof a); console.log(a === b); // 执行结果 // 模块开始执行 // 模块执行结束
// object // true

import():

// 1.js
console.log('模块执行开始');
export let num = 1;
console.log('模块执行结束');

// testImportFunction.js
let a = await import('./1.js');
let b = await import('./1.js');
console.log(typeof a); console.log(a === b); // 执行结果 // 模块开始执行 // 模块执行结束
// object // true

由此可见,它们三个,在代码中多次引入同一模块,模块都是只会执行一次。并且,输出结果完全相等(===),也就是指向同一个引用。

我们可以判断,它们都是第一次执行后把输出结果缓存了起来,多次引入不会再次执行,而是直接返回输出结果的引用。

(2)那么,它们对输出结果的缓存方式一样吗?

require():

// 2.js
let num = 1;
let obj = {
	num: 1
};
function add() {
	num += 1;
	obj.num += 1;
}
module.exports = { num, obj, add };

// testRequire.js
let a = require('./2.js');
console.log(a.num); // 1
console.log(a.obj.num); // 1
a.add();
console.log(a.num); // 1
console.log(a.obj.num); // 2

require的缓存方式,是对输出结果进行拷贝,而且是浅拷贝。值类型直接拷贝,引用类型拷贝内存地址。

import:

// 1.js
let num = 1;
let obj = {
	num: 1
};
function add() {
	num += 1;
	obj.num += 1;
}
export { num, obj, add };

// testImport.js
import * as a from './1.js';
console.log(a.num); // 1
console.log(a.obj.num); // 1
a.add();
console.log(a.num); // 2
console.log(a.obj.num); // 2

import并不对输出结果进行拷贝,而是直接指向输出结果的引用。

import():

// 1.js
let num = 1;
let obj = {
	num: 1
};
function add() {
	num += 1;
	obj.num += 1;
}
export { num, obj, add };

// testImportFunction.js
let a = await import('./1.js');
console.log(a.num); // 1
console.log(a.obj.num); // 1
a.add();
console.log(a.num); // 2
console.log(a.obj.num); // 2

import()也是一样的,直接指向输出结果的引用。

 

三、静态?动态?

静态引入:

所谓静态引入,就是在编译时引入,那么就不能使用在运行时才能得到结果的语法结构了,比如不能包在if语句里,引用路径不能使变量和表达式,要求必须是字符串字面量。

import就是静态引入。

动态引入:

动态引入,就是在运行时引入。因此可以根据条件判断来按需引入,引用路径也可以写成变量或表达式。

require()和import()都是动态引入。

 

四、同步?异步?

require():

// 2.js
console.log('模块执行开始');
let num = 1;
for (var i = 0; i < 1000000000; i++) {

}
module.exports = { num };
console.log('模块执行结束');

// testRequire.js
let a = require('./2.js');
console.log('执行其他代码');

// 执行结果
// 模块执行开始
// 若干秒后...
// 模块执行结束
// 执行其他代码

require()引入模块,是同步的,但是因为是在服务端本地引用,同步引入完全没有问题。

import:

// 1.js
console.log('模块执行开始');
let num = 1;
await new Promise(resolve => {
	setTimeout(resolve, 3000);
});
export { num };
console.log('模块执行结束');

// testImport.js
import * as a from './1.js';
console.log('执行其他代码');

// 执行结果
// 模块执行开始
// 3秒后...
// 模块执行结束
// 执行其他代码

这儿让我非常意外,也很困惑。都说import是异步引入的,为什么这儿的结果却显示它是同步的?哪位能解答我的疑惑?

import():

// 1.js
console.log('模块执行开始');
let num = 1;
await new Promise(resolve => {
	setTimeout(resolve, 3000);
});
export { num };
console.log('模块执行结束');

// testImportFunction.js
import('./1.js');
console.log('执行其他代码');

// 执行结果
// 执行其他代码
// 模块执行开始
// 3秒后...
// 模块执行结束

没问题,import()是异步引入,返回的是一个Promise对象。

 

五、相互引用

require():

require()无法引入ES6模块,但可以使用import()函数来引入ES6模块。

import:

// 2.js
let num = 1;
let obj = {
	num: 1
};
module.exports = { num, obj, add };

// testImport.js
import a from './2.js';
console.log(a.num); // 1
console.log(a.obj.num); // 1

import可以引入CommonJS模块,是把module.exports对象整体引入,类似于对exports default的接收,直接用一个变量来接收。

import():

// 2.js
let num = 1;
let obj = {
	num: 1
};
module.exports = { num, obj, add };

// testImportFunction.js
let a = await import('./2.js');
console.log(a.default.num); // 1
console.log(a.default.obj.num); // 1

import()整体接收module.exports这个对象,并把它放在default属性下。

 

就总结这些吧。本人水平非常有限,写作主要是为了把自己学过的东西捋清楚。如有错误,还请指正,感激不尽。

 

标签:console,log,哪些,require,js,num,模块,import
From: https://www.cnblogs.com/luzeyu/p/17832775.html

相关文章

  • 专业软件检测机构进行性能测试有哪些流程?
    软件性能测试是一种评估软件在不同条件下的性能表现的过程。它旨在验证软件在正常和负载情况下的稳定性、响应时间、吞吐量、可扩展性和资源利用率等性能指标。通过性能测试,我们可以发现潜在的性能问题,并为软件性能的提升提供决策依据。一、专业软件测试机构进行性能测试时......
  • 【springboot项目运行报错】亲测有效 Parameter 0 of constructor in xxx.xxx.Control
    Parameter0ofconstructorinme.zhengjie.modules.system.rest.DictDetailControllerrequiredabeanoftype'me.zhengjie.modules.system.service.DictDetailService'thatcouldnotbefound.1.点击界面左侧的maven管理,再点击root下的生命周期,点击clean(也可以直接控制台......
  • 怎么利用http代理IP上网?代理IP代理起到哪些作用?
    代理IP是一种通过使用代理服务器来代替用户直接访问互联网的方式。代理IP可以隐藏用户的真实IP地址,保护用户的隐私和安全。同时,代理IP还可以提高访问速度、突破网络限制、防止安全等作用。以下是利用代理IP上网的步骤:获取代理IP地址:用户可以从代理IP服务商处获取代理IP地址,或者自己......
  • 轻量级前端架构有哪些特性?
    小程序技术自微信2016年提出并大力推动,如今已经成为了中国前端研发的“潮流”,或者说是“趋势”。早期,微信小程序是微信公众平台推出的一种应用形态。微信小程序开放平台允许开发者在微信内直接开发和发布应用,用户无需下载安装,即可在微信中使用。之所以推出小程序技术,是为了解决传统......
  • k8s pod的共享资源有哪些?
    概述1)PID命名空间:Pod中的不同应用程序可以看到其他应用程序的进程ID;2)网络命名空间:Pod中的多个容器能够访问同一个IP和端口范围;3)IPC命名空间:Pod中的多个容器能够使用SystemVIPC或POSIX消息队列进行通信;4)UTS命名空间:Pod中的多个容器共享一个主机名;5)Volumes(共享存储卷):Pod......
  • 视频监控平台SkeyeVSS支持哪些录像形式?
    视频监控平台SkeyeVSS支持哪些录像形式?近年来,随着互联网技术的发展,运用先进的AI、物联网、大数据、云计算等技术手段不断提高化工行业的随着互联网技术的发展。全国各地在视频监控领域进行了大量的建设。但随着摄像头数量的增加,录像设备的多样性,视频监控画面离散、庞杂、关联性差等......
  • 从DPlayer说起,有哪些开源的H5播放器
    引言​ H5指的是HTML5,也就是介绍网页播放器(只是列出而已)。首先我不是什么大佬,并没有完全体验过以下我会介绍的全部播放器;其次,因为我水平比较低,主要介绍拥有中文文档的播放器,不了解开发的朋友当成科普看看就行,平常用不到,了解的可以补充一下还有哪些,毕竟我收集的肯定不全,最好能补......
  • 独立站EDM工具有哪些?Top 5推荐来了
    在当今数字化时代,独立站邮件营销(EDM)成为企业推广的重要手段之一。选择合适的独立站EDM工具对于提高邮件发信效果至关重要。本文将为您介绍一些独立站EDM工具,为您的邮件营销活动提供有力支持。1.蜂邮EDM蜂邮EDMfengemali.com作为独立站EDM工具的佼佼者,以其易用性和丰富的功能而闻名......
  • Golang 无缓冲channel有哪些特点?
    无缓冲channel是Go语言中的一种特殊类型的channel,其主要特点是在发送和接收数据时要求发送方和接收方必须同时准备好,否则会造成阻塞。具体来说,当一个无缓冲channel的发送操作没有准备好时,会阻塞发送方的执行;同样地,当一个无缓冲channel的接收操作没有准备好时,会阻塞接收方的执行。无......
  • VS2017 fail: An XML declaration with an encoding is required for all non-UTF8 do
    VS2017打开一个别人的项目,报错无法打开,提示:AnXMLdeclarationwithanencodingisrequiredforallnon-UTF8documents研究一番,没有找到直接原因。换个思路,是不是IDE版本问题?检查一下项目文件,IDE版本是:VisualStudioVersion=17.5.33414.496这个是VS2022的版本。于是下载安装V......