前言

说到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. Dynamics 365 Customer Engagement V9.X新引入的自动编号属性介绍

    我是微软Dynamics 365 & Power Platform方面的工程师罗勇,也是2015年7月到2018年6月连续三年Dynamics CRM/Business Solutions方面 ...

  2. IS Kali: installed chiess messy code problem

    apt-get install ttf-wqy-microhei ttf-wqy-zenhei xfonts-wqy init 6

  3. 理解ES6的新数据类型:Symbol

    ES6之前的数组类型 在ES6之前JS只有6种数据类型,分别是:Undefined.Null.布尔值(Boolean).字符串(String).数值(Number).对象(Object). ES6引入 ...

  4. Go语言系列:(2)go get 命令介绍

    Go语言的代码被托管于 Github.com 网站,该网站是基于 Git 代码管理工具的,很多有名的项目都在该网站托管代码.其他类似的托管网站还有 code.google.com.bitbucket. ...

  5. 二维数组中的查找(剑指offer_4)

    给定一个二维数组,其每一行从左到右递增排序,从上到下也是递增排序.给定一个数,判断这个数是否在该二维数组中. Consider the following matrix: [ [1, 4, 7, 11 ...

  6. angularjs link compile与controller的区别详解,了解angular生命周期

     壹 ❀ 引 我在 angularjs 一篇文章看懂自定义指令directive 一文中简单提及了自定义指令中的link链接函数与compile编译函数,并说到两者具有互斥特性,即同时存在link与c ...

  7. 隐藏Nginx软件版本号信息

    为了提高我们web服务器的安全性,我们应当尽可能的隐藏服务器的信息以防止他人通过这些信息找到漏洞侵入我们的服务器,对于Nginx而言,我们安装好Nginx后最好隐藏Nginx的版本号,以防止通过该版本 ...

  8. 【CF908D】New Year and Arbitrary Arrangement

    Problem Description 给定三个数 \(k,pa,pb\) ,每次有 \(\frac{pa}{pa+pb}\) 的概率往后面添加一个 a,有 \(\frac{pb}{pa+pb}\) ...

  9. 痞子衡嵌入式:飞思卡尔i.MX RT系列MCU量产神器RT-Flash常见问题

    对于MCUBootUtility,RT-Flash工具,有任何使用上的问题,可以在本博客下留言,也可以扫码加入QQ交流群.

  10. javaWeb核心技术第十二篇之分页和条件

    分页:limit ?,? 参数1 : startIndex 开始索引. 参数2 : pageSize 每页显示的个数 n 表示第几页 给定一个特殊的单词 pageNumber select * fro ...