ES6学习笔记(二)—— 通过ES6 Module看import和require区别
前言
说到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来引入模块,等以后浏览器支持了我们也就可以少改一些代码了。
参考
ES6学习笔记(二)—— 通过ES6 Module看import和require区别的更多相关文章
- 通过ES6 Module看import和require区别
前言 说到import和require,大家平时开发中一定不少见,尤其是需要前端工程化的项目现在都已经离不开node了,在node环境下这两者都是大量存在的,大体上来说他们都是为了实现JS代码的模块化 ...
- ES6学习笔记<二>arrow functions 箭头函数、template string、destructuring
接着上一篇的说. arrow functions 箭头函数 => 更便捷的函数声明 document.getElementById("click_1").onclick = ...
- ES6学习笔记(二)——字符串扩展
相信很多人也和我一样,不喜欢这样循规蹈矩的逐条去学习语法,很枯燥乏味.主要是这样学完一遍之后,没过一段时间就忘到九霄云外了.不如实际用到的时候研究它记得牢靠,所以我就整理成笔记,加深记忆的同时便于复习 ...
- ES6学习笔记二
字符串遍历 var str = 'hello'; for(let s of str){console.log(s += ' ')} //h e l l o 字符串查找:添加了include(str,i ...
- es6学习笔记二:生成器 Generators
今天这篇文章让我感到非常的兴奋,接下来我们将一起领略ES6中最具魔力的特性. 为什么说是“最具魔力的”?对于初学者来说,此特性与JS之前已有的特性截然不同,可能会觉得有点晦涩难懂.但是,从某种意义上来 ...
- ES6学习笔记二:各种扩展
转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/7242967.html 一:字符串扩展 1:字符串遍历器 for (let char of str) { // ...
- ES6学习笔记(二)
Set 和 Map 数据结构 1.set 基本用法 ES6提供了新的数据结构Set,它类似于数组,但是成员的值都是唯一的,没有重复的值 Set本身是一个构造函数,用来生成Set数据结构 const s ...
- ES6学习笔记<五> Module的操作——import、export、as
import export 这两个家伙对应的就是es6自己的 module功能. 我们之前写的Javascript一直都没有模块化的体系,无法将一个庞大的js工程拆分成一个个功能相对独立但相互依赖的小 ...
- ES6学习笔记<三> 生成器函数与yield
为什么要把这个内容拿出来单独做一篇学习笔记? 生成器函数比较重要,相对不是很容易理解,单独做一篇笔记详细聊一聊生成器函数. 标题为什么是生成器函数与yield? 生成器函数类似其他服务器端语音中的接口 ...
随机推荐
- java框架之MyBatis(2)-进阶&整合Spring&逆向工程
进阶内容 准备 jdbc.url=jdbc:mysql://192.168.208.192:3306/test?characterEncoding=utf-8 jdbc.driver=com.mysq ...
- 自动化安装-【kickstart】
批量自动安装软件介绍 kickstart 是一种无人值守的安装方式,工作原理是在安装过程中记录人工干预填写的各种参数,并生成以个名为ks.cfg(自动应答文件)的文件,如果在自动安装过程中出现要填写参 ...
- 【Gradle】-NO.101.Gradle.1.gradle.1.001-【Gradle Configuration】-(
Style:Gradle Series:Gradle Since:2018-09-20 End:2018-09-20 Total Hours:1 Degree Of Diffculty:5 Degre ...
- 把ResNet-L152模型的ckpt文件转化为pb文件
import tensorflow as tf from tensorflow.python.tools import freeze_graph #os.environ['CUDA_VISIBLE_D ...
- VMWare安装CentOS 6.5图解
1.本安装示例所使用的虚拟机:vmware workstation 12 2.从VMWare创建虚拟机开始,打开VMWare. 操作系统:CentOS 6.5 64位 IP地址:192.168.1.2 ...
- 转载的web server实例
asp.net—web server模拟网上购物 2014-05-08 我来说两句 来源:asp.net—web server模拟网上购物 收藏 我要投稿 在学vb的时候学到了a ...
- ASM磁盘组剔盘、加盘实施过程
Task:从一个ASM磁盘组中剔除一块盘,加入到另一个ASM磁盘组. 环境:AIX6.1 + Oracle RAC 11.2.0.3 前期准备: 1.查看DG磁盘组空间情况: --查看DG磁盘组空间情 ...
- Kaggle比赛:从何着手?
介绍 参加Kaggle比赛,我必须有哪些技能呢? 你有没有面对过这样的问题?最少在我大二的时候,我有过.过去我仅仅想象Kaggle比赛的困难度,我就感觉害怕.这种恐惧跟我怕水的感觉相似.怕水,让我无法 ...
- 使用shiro框架,解决跳转页面出现404的问题
shiro框架是一个安全框架,在进行登录的时候,如果没有配置路径,它会跳到shiro的默认配置的路径“/”下面,所以总是会出现404的错误,因为它的路径是保存在session中 所以需要我们把sess ...
- 网页布局要注意的事项,以及CSS3需要特别注意的地方。
overflow: hidden; white-space: nowrap; text-overflow: ellipsis;隐藏超出部分,出省略号 一定要先布局!布局!布局!要先设置好色块,将位置确 ...