require 和 import,都是为了JS模块化使用。不知道有没有小伙伴和我一样,最开始有点分不清楚import和require的区别,今天就给大家梳理一下他们之间的区别。由于有时候多人协同开发时,会出现一个项目中同时使用了import和require引入的情况。在正常的情况下,一个项目中最好使对引入方式做一个规范。
ES6标准发布后,module成为标准,标准的使用是以export指令导出接口,以import引入模块;但是在node模块中,我们采用的是CommonJS规范,使用require引入模块,使用module.exports导出接口。
require/exports 出生在野生规范当中,什么叫做野生规范?即这些规范是 JavaScript 社区中的开发者自己草拟的规则,得到了大家的承认或者广泛的应用。比如 CommonJS、AMD、CMD 等等。import/export 则是名门正派。
CommonJS 作为 Node.js 的规范,一直沿用至今。(就是因为CommonJS填补了JS没有模块的功能空缺,它的目标是让JS不止在浏览器中运行,可以在各个地方都能运行。)由于CommonJS 和 ES6 之间的差异,所以Node.js 无法直接兼容 ES6。因此我们在现阶段掌握require/exports是必要的。
ES6在语言规格的层面上,实现了模块功能,而且实现得相当简单,完全可以取代现有的CommonJS和AMD规范,成为浏览器和服务器通用的模块解决方案。
require是Commonjs的规范,node应用是由模块组成的,遵从Commonjs的规范即exports是模块公开的接口,require用于从外部获取一个模块接口,举一个例子:
x.js与y.js是同级文件。
在x.js文件中写入代码:
1 | function demo(args) { |
y.js文件中写入代码:
1 | let { demo } = require("./x.js"); |
通过在终端运行:node y.js可以运行出:I am x_demo!!!
require的使用:在导出的文件中定义module.exports,导出的对象类型不予限定(可为任意类型)。在导入的文件中使用require()引入即可使用。本质上,是将要导出的对象,赋值给module这个对象的exports属性,在其他文件中通过require这个方法来访问exports这个属性。
import是ES6为JS模块化提出的新的语法,import(导入)要与export(导出)结合使用,举一个例子。
index.html文件与x.js与y.js是同级文件。
在index.html文件中写入代码:
1 |
|
在x.js文件中写入代码:
1 | export function demo(args) { |
y.js文件中写入代码:
1 | import def, { demo, age, name } from './x.js'; // def代表引入的export default的内容 |
注意:如果不放在服务器下面会有一个报错信息,如下图所示:
此时的解决办法就是将它放在服务器下面就可以解决相应的问题。我们可以下一个服务器,Windows系统的可以下一个wamp,Mac系统的可以下一个mamp。
as简单的说就是取一个别名。export中可以用,import中也可以用。下面我们看一个例子。
a.js文件与b.js文件与c.js文件是同级文件:
a.js文件代码如下:
1 | var a = function() {}; |
b.js文件代码如下:
1 | import {fun as a} from './a'; |
上面这段代码,export的时候,对外提供的接口是fun,它是a.js内部a这个函数的别名,但是在模块外面,不认识a,只认识fun。
import中的as就很简单,就是你在使用模块里面的方法的时候,给这个方法取一个别名,好在当前的文件里面使用。之所以是这样,是因为有的时候不同的两个模块可能通过相同的接口,比如有一个c.js也通过了fun这个接口。
c.js文件代码如下:
1 | export function fun() {}; |
如果在b.js中同时使用a和c这两个模块,就必须想办法解决接口重名的问题,as就解决了。
在export的时候,可能会用到default,说简单一些它其实是别名的语法糖。
在x.js文件中写入代码:
1 | export default function() {} |
在import的时候,可以这样使用:
1 | import a from './x'; |
注意:这个语法糖的好处就是import的时候,可以省去花括号{}。简单的说,如果import的时候,你发现某个变量没有花括号括起来(没有*号),那么你在脑海中应该把它还原成有花括号的as语法。就如上面代码所示。
就是代表所有,只用在import中。
*注意:符号尽可能少用,它实际上是使用所有export的接口,但是很有可能你的当前模块并不会用到所有接口,可能仅仅是一个,所以最好的建议是使用花括号,用一个加一个。*
1 | // 导入写法 |
1 | const dai = require("dai"); |
require的使用场合:
require的使用非常简单,它相当于module.exports的传送门,module.exports后面的内容是什么,require的结果就是什么,对象、数字、字符串、函数……再把require的结果赋值给某个变量,相当于把require和module.exports进行平行空间的位置重叠。
require理论上可以运用在代码的任何地方,甚至不需要赋值给某个变量之后再使用,而且你在使用时,完全可以忽略模块化这个概念来使用require,仅仅把它当做一个node内置的全局函数,它的参数甚至可以是表达式:。举一个例子,代码如下所示:
1 | require('./a')(); // a模块是一个函数,立即执行a模块函数 |
import使用场合:
import是编译时的,它必须放在文件开头,而且使用格式也是确定的,它不会将整个模块运行后赋值给某个变量,而是只选择import的接口进行编译,这样在性能上比require好很多。
如果还有不懂或者想要深入学习的同学,可以去网上搜索相关的内容进行一个补充。