前言

说到import和require,大家平时开发中一定不少见,尤其是需要前端工程化的项目现在都已经离不开node了,在node环境下这两者都是大量存在的,大体上来说他们都是为了实现JS代码的模块化,那为什么会出现两种方案呢,又有什么不同呢?

模块化的不同解决方案

追根溯源,JS这门脚本语言设计伊始就是没有模块化的,所以早期的全局变量容易造成命名冲突。但随着web项目越来越大,JS的代码量也与日俱增,于是社区就自发约定了几种模块化的方案:requirejs遵循AMD,seajs遵循CMD,node的module遵循CommonJS规范,虽然写法上有所不同,都是为了能够间接实现模块化的基础上保持较为一致的代码风格。

随着ES2015的发布,官方标准定义了一种模块化的方案,那就是import、export。可是,标准毕竟是标准,各大浏览器和node终端要实现标准还是有一段距离的,目前来说都2018年了主流浏览器都还没实现,还得依赖转换工具(例如babel)转为ES5的代码之后浏览器才能解析。所以这也就解释了为什么我们的工程化代码中nodeJS遵循的CommonJS规范和ES6的模块化方案并存的现象。

两者的区别

  • import是ES6标准中的模块化解决方案,require是node中遵循CommonJS规范的模块化解决方案
  • 后者支持动态引入,也就是require(${path}/xx.js),前者目前不支持,但是已有提案
  • 前者是关键词,后者不是
  • 前者是编译时加载,必须放在模块顶部,在性能上会比后者好一些,后者是运行时加载,理论上来说放在哪里都可以
  • 前者采用的是实时绑定方式,即导入和导出的值都指向同一个内存地址,所以导入值会随着导出值变化。而后者在导出时是指拷贝,就算导出的值变化了,导入的值也不会变化,如果想要更新值就要重新导入
  • 前者会编译成require/exports来执行

用法上的区别

import导入模块

  • 导入模块根据模块导出时的写法有不同写法,具体可以参考这里,如果模块是普通导出:

// test.js
var firstName = 'Michael';
var lastName = 'Jackson';
var year = 1958;
export {firstName, lastName, year};
// demo.js
import { firstName } from './test.js'
console.log(firstName); // 'Michael'
import * as test from './test.js'
console.log(test); //Module{} 所有内容
import { firstName as key, lastName as value } from './test.js'
console.log(key + '--' + value); // Michael--Jackson
  • 带有默认值时,也是我们日常开发中常用的方式:
// test.js
var firstName = 'Michael';
var lastName = 'Jackson';
var year = 1958;
export default { firstName, lastName, year };
// demo.js
import test from './test.js'
console.log(test); // {firstName: "Michael", lastName: "Jackson", year: 1958}

实际上这个default就是一个语法糖,只不过defaul是一个关键字,在这里等同于

import { default as test } from './test.js'

特别注意的是,export命令规定的是对外的接口,必须与模块内部的变量建立一一对应关系。可以理解为export导出的是一种引用关系而不是一个具体的值,它们的实质是,在接口名与模块内部变量之间,建立了一一对应的关系,例如下面这样就会报错:

export 1;
var m = 1;
export m;

但是改为用花括号包起来变成对象之后就成了输出引用关系就可以正常导出了:

var m = 1;
export { m }

require导入模块

  • require导入模块就没那么复杂了,导出时是什么样,导入时就还是什么样:
// test.js
var firstName = 'Michael';
var lastName = 'Jackson';
var year = 1958;
module.exports = { firstName, lastName, year };
// demo.js
const test = require('./test.js');
console.log(test); // {firstName: "Michael", lastName: "Jackson", year: 1958}
  • 还有一种不常用的用法,直接导出:
// test.js
var year = 1958;
exports.year = year;
// demo.js
const test = require('./test.js');
console.log(test); // {year: 1958}
  • 需要注意的是,module.exports导出之后,后面的代码就对导出的模块无效了,例如上例中
// test.js
module.exports = { firstName, lastName, year };
exports.name = '222';
// demo.js
const test = require('./test.js');
console.log(test); // {firstName: "Michael", lastName: "Jackson", year: 1958}
  • 特别说明一下,由于require是可以在任意地方引入的,所以,我们在开发中用~引入图片的方式实际上等效于require:
<img src="~assets/img/icon/red_logo.png" class="logo" alt="">
//等效于
<img :src="require('assets/img/icon/red_logo.png')" class="logo" alt="">

总结

import和require就是两种不同的JS模块化实现方式而已,由于之前npm生态的很多包都是基础CommonJS规范写的,所以相当一段时间之内必然是import和require这两种模块引入方式共存的。

总体来说时代总是发展的,ES6作为语言规范是迟早会被各大主流浏览器支持的,不然也就称不上主流浏览器了。所以为了长远考虑,我们还是尽量使用ES6的import来引入模块,等以后浏览器支持了我们也就可以少改一些代码了。

参考

注1:

JS报错:Cannot use import statement outside a module

在使用import和export的时候,type类型错误会导致无法使用模块化功能:

<script type="text/javascript">
  import test from './test/js';
  console.log(test);
</script>

需要将type中text/javascript改为module,模块化的功能方能生效:

<script type="module">
import test from './test.js';
console.log(test);
</script>

注2:

JS报错:require is not defined

报错原因:
浏览器端不能识别require关键字,require是node.js环境下的,在node_modules文件夹里面的模块下面常见require

解决方法:
通过工具browserify或者是webpack把js文件编译一下,转成浏览器端可识别的。

//安装browserify ,我这里是全局安装

npm install -g browserify

// 编译

browserify ./source/module.js -o ./dist/dist.js

即可在dist目录下看到打包后的dist.js文件。 
browserify 后面的第一个参数表示要打包的前端程序的入口,-o或者>表示打包后的输出文件。browserify会根据入口文件中的require或者import(ES6,需要安装babel)自动完成依赖分析,并将依赖文件打包为一个单文件。
————————————————
版权声明:本文为CSDN博主「giao00000」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/wml00000/article/details/84181227

原文出处:

西风瘦码,ES6学习笔记(二)—— 通过ES6 Module看import和require区别,https://www.cnblogs.com/wancheng7/p/10169470.html

通过ES6 Module看import和require区别的更多相关文章

  1. ES6学习笔记(二)—— 通过ES6 Module看import和require区别

    前言 说到import和require,大家平时开发中一定不少见,尤其是需要前端工程化的项目现在都已经离不开node了,在node环境下这两者都是大量存在的,大体上来说他们都是为了实现JS代码的模块化 ...

  2. module.exports,exports,export和export default,import与require区别与联系【原创】

    还在为module.exports.exports.export和export default,import和require区别与联系发愁吗,这一篇基本就够了! 一.首先搞清楚一个基本问题: modu ...

  3. module.exports,exports,export和export default,import与require区别与联系

    还在为module.exports.exports.export和export default,import和require区别与联系发愁吗,这一篇基本就够了! 一.首先搞清楚一个基本问题: modu ...

  4. es6+require混合开发,兼容es6 module,import,export

    近一年,一直很忙,做了不少的项目,不过都不是太满意,毕竟是别人的作品,不好意思写出来.最近打算开发一个es6的项目,项目中用到require,本文主要讲解es6的module规范怎么与require的 ...

  5. es6+require混合开发,兼容es6 module,import,export之 加载css及公用date-main

    大家好!上篇文章已经介绍了搭建文件夹,以及加载js文件.现在讲一下加载css ,以及对baseUrl的理解 1.对项目结构的认知 一个项目的结构是根据项目的架构来决定的,当然也可以做到更智能,但是意义 ...

  6. JS中的import和require区别

    1.import xx from yy的方式是静态编译,即编译时加载,要写在文件的最上头,但是import()函数可以实现动态加载,写在任何地方 2.require是动态加载,即运行时加载,理论上可以 ...

  7. export,export default,module.exports,import,require之间的区别和关联

    module.exports Node 应用由模块组成,采用 CommonJS 模块规范.根据这个规范,每个文件就是一个模块,有自己的作用域.在这些文件里面定义的变量.函数.类,都是私有的,对外不可见 ...

  8. require/exports 与 import/export 的区别?

    文章作者:寸志链接:https://www.zhihu.com/question/56820346/answer/150724784来源:知乎 遵循的模块化规范不一样 模块化规范:即为 JavaScr ...

  9. CommonJS与ES6 Module的使用与区别

    CommonJS与ES6 Module的使用与区别 1. CommonJS 1.1 导出 1.2 导入 2. ES6 Module 2.1 导出 2.2 导入 3. CommonJS 与 ES6 Mo ...

随机推荐

  1. C lang:Pointer and Array

    Xx_Introduction Point and Array germane. Xx_Code #include<stdio.h> #define SIZE 4 int main(voi ...

  2. 从0系统学Android--3.6 RecyclerView

    从0系统学Android--更强大的滚动控件---RecyclerView 本系列文章目录:更多精品文章分类 本系列持续更新中.... 参考<第一行代码> 首先说明一点昨天发了一篇关于 L ...

  3. Git介绍与简易搭建

    Git介绍 Git(读音为/gɪt/.)是一个开源的分布式版本控制系统,可以有效.高速的处理从很小到非常大的项目版本管理. Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发 ...

  4. right join 和left join 的区别

    SQL 数据库 right join 和left join 的区别   left join(左联接) 返回包括左表中的所有记录和右表中联结字段相等的记录 right join(右联接) 返回包括右表中 ...

  5. hibernate-positional-parameter-does-not-exist-1-in-query

    经过bug的排查,问题出在,scsj字段的赋值上; 通过字符串在数据库端生成即可:

  6. 创建可执行的JAR包并运行

    将一个应用程序制作成可执行的JAR包,通过JAR包来发布应用程序.创建可执行JAR包的关键在于:让java -jar命令知道JAR包中哪个类是主类,java -jar命令可以通过运行该主类来运行程序. ...

  7. vue_04day 路由初始

    目录 vue_04 项目初始: vue 文件构造: vue项目目录结构: 项目入口(main.js): vue项目启动生命周期: 根组件(vue.js): router.js: 创建的页面: 全局样式 ...

  8. C#添加错误日志信息

    错误日志是软件用来记录运行时出错信息的文本文件.编程人员和维护人员等可以利用错误日志对系统进行调试和维护. 系统日志 系统日志包含了由Windows系统组件记录的事件.例如,在启动期间装入驱动程序或其 ...

  9. 利用Python进行数据分析-Pandas(第二部分)

    上一个章节中我们主要是介绍了pandas两种数据类型的具体属性,这个章节主要介绍操作Series和DataFrame中的数据的基本手段. 一.基本功能 1.重新索引 pandas对象的一个重要方法是r ...

  10. 【Java基础】JDBC简明教程

    目录 1. 常用类 2. JDBC编程步骤 3. 事务处理 4. 数据库连接池 5. JDBC列子代码 6. 使用Apache的JDBC工具类 虽然在平时的开发过程中我们不会直接使JDBC的API来操 ...