美文网首页
require和import的区别

require和import的区别

作者: scarqin | 来源:发表于2020-04-12 14:57 被阅读0次

当前端应用越来越复杂时,我们想要将代码分割成不同的模块,便于复用、按需加载等。

require 和 import 分别是不同模块化规范下引入模块的语句,下文将介绍这两种方式的不同之处。

1. 出现的时间、地点不同

年份 出处
require/exports 2009 CommonJS
import/export 2015 ECMAScript2015(ES6)

2. 不同端(客户端/服务器)的使用限制

require/exports import/export
Node.js 所有版本 Node 9.0+(启动需加上 flag --experimental-modules)
Node 13.2+(直接启动) 如何使用?
Chrome 不支持 61+
Firefox 不支持 60+
Safari 不支持 10.1+
Edge 不支持 16+

CommonJS 模块化方案 require/exports 是为服务器端开发设计的。服务器模块系统同步读取模块文件内容,编译执行后得到模块接口。(Node.jsCommonJS 规范的实现)。

在浏览器端,因为其异步加载脚本文件的特性,CommonJS 规范无法正常加载。所以出现了 RequireJSSeaJS 等(兼容 CommonJS )为浏览器设计的模块化方案。

两种方案各有各的限制,需要注意以下几点:

  • 原生浏览器不支持 require/imports,可使用支持 CommonJS 模块规范的 Browsersifywebpack 等打包工具,它们会将 require/imports 转换成能在浏览器使用的代码。
  • import/export 在浏览器中无法直接使用,我们需要在引入模块的 <script\> 元素上添加type="module属性。
  • 即使 Node.js 13.2+ 已经支持 import/export,官方不建议在正式环境使用,目前可以使用 babelES6 的模块系统编译成 CommonJS 规范(注意:语法一样,但具体实现还是require/exports)。

3. require/exports 是运行时动态加载,import/export 是静态编译

CommonJS 加载的是一个对象(即 module.exports 属性),该对象只有在脚本运行完才会生成。而 ES6 模块不是对象,它的对外接口只是一种静态定义,在代码静态解析阶段就会生成。- 阮一峰

4. require/exports 输出的是一个值的拷贝,import/export 模块输出的是值的引用

require/exports 输出的是值的拷贝。也就是说,一旦输出一个值,模块内部的变化就影响不到这个值。

import/export 模块输出的是值的引用。JS 引擎对脚本静态分析的时候,遇到模块加载命令import,就会生成一个只读引用。等到脚本真正执行时,再根据这个只读引用,到被加载的那个模块里面去取值。

若文件引用的模块值改变,require 引入的模块值不会改变,而 import 引入的模块值会改变。

5. 用法不一致

(1). require/exports 的用法

const fs = require('fs')
exports.fs = fs
module.exports = fs

exports 是对 module.exports 的引用,相当于

exports = module.exports = {};

在不改变 exports 指向的情况下,使用 exportsmodule.exports 没有区别;如果将 exports 指向了其他对象,exports 改变不会改变模块输出值。示例如下:

//utils.js
let a = 100;

exports.a = 200;
console.log(module.exports) //{a : 200}
exports = {a:300}; //exports 指向其他内存区

//test.js

var a = require('./utils');
console.log(a) // 打印为 {a : 200} 

(2). import/export 的写法

import fs from 'fs'

import {readFile} from 'fs' //从 fs 导入 readFile 模块
import {default as fs} from 'fs' //从 fs 中导入使用 export default 导出的模块
import * as fileSystem from 'fs' //从 fs 所有导出模块,引用对象名为 fileSystem
import {readFile as read} from 'fs' //从 fs 导入 readFile 模块,引用对象名为 read
import('/modules/my-module.js') //动态导入
  .then((module) => {
    // Do something with the module.
});

export default fs
export const fs
export function readFile
export {readFile, read}
export * from 'fs'

建议1:建议明确列出我们要引用的内容。,使用 * 虽然很方便,但是不利于现代的构建工具检测未被使用的函数,影响代码优化。

建议2: 请不要滥用动态导入 import()(只有在必要情况下采用)。静态框架能更好的初始化依赖,而且更有利于静态分析工具和 tree shaking 发挥作用

同时需要注意

  1. 引入 export default 导出的模块不用加 {},引入非 export default 导出的模块需要加 {}。
import fileSystem, {readFile} from 'fs' 
  1. 一个文件只能导出一个 default 模块。

  2. 在验证代码的时候遇到如下报错

access to script from origin 'null' has been blocked by CORS policy

前面提到过,浏览器引入模块的 <script> 元素要添加 type="module 属性,但 module 不支持 file:// 文件协议,只支持 HTTP 协议,所以本地需要使用 http-server 等本地网络服务器打开网页文件。

(3). import/export 不能对引入模块重新赋值/定义

当我尝试给 import 的模块重新赋值时

  import {e1} from './webUtils.js';
  e1=234;

浏览器显示

Uncaught TypeError: Assignment to constant variable.

当我重新定义引用的模块

 import {e1} from './webUtils.js';
 var e1=1;

浏览器显示

(index):17 Uncaught SyntaxError: Identifier 'e1' has already been declared

(4). ES6 模块可以在 import 引用语句前使用模块,CommonJS 则需要先引用后使用

ES6 模块

//webUtils.js
export var e='export';
  console.log(e) //export
  import {e} from './webUtils.js';
  console.log(e) //export

CommonJS

//utils.js
exports.e = 'export';
console.log(a) 
a = require('./utils');
console.log(a) 

程序报错

ReferenceError: a is not defined

(5). import/export 只能在模块顶层使用,不能在函数、判断语句等代码块之中引用;require/exports 可以。

import fs from  './webUtils.js';
   function a(){
    import {e1} from './webUtils.js';
    console.log(e1)
   }
   a();
   console.log(fs())

程序报错

Uncaught SyntaxError: Unexpected token '{'
前面提到过 import/export 在代码静态解析阶段就会生成,不会去分析代码块里面的 import/export,所以程序报语法错误,而不是运行时错误。

这里需要注意,动态导入 import() 任何地方使用,因为他是运行时加载

6. 是否采用严格模式

严格模式是采用具有限制性JavaScript变体的一种方式

import/export 导出的模块默认调用严格模式。

var fun=()=>{
    mistypedVaraible = 17; //报错,mistypedVaraible is not defined
};
export default fun;

require/exports 默认不使用严格模式,可以自定义是否使用严格模式。
例如

exports.fun = ()=>{
 mistypedVaraible = 17; //没有调用严格模式,不会报错
}; 

7. 参考资料

相关文章

  • require,import ,export default,m

    module.exports和exports区别 import和require的区别 import和require...

  • 2、require 和 import 的区别?

    【转载出处】 require 和 import 的区别? 谈谈import和require的区别 1⃣️、遵循的规...

  • require和import区别

    使用形式不一样 import 还有一个重要的区别import是解析时候加载的,require是运行时加载,requ...

  • import和require区别

    在学习过程发现项目代码中存在两种引入方式,便各方查了两种的区别(一下内容为自我学习笔记,如有不当还请指教): 1、...

  • import 和 require区别

    ES6之前出现了JS模块加载的法案,最主要是CommonJS和AMD规范。CommonJS前者主要应用于服务器,实...

  • require和import区别

    遵循的模块化规范不一样 模块化规范:即为 JavaScript 提供一种模块编写、模块依赖和模块运行的方案。谁让最...

  • import 和 require区别

    import和require分别是不同模块化规范下引入模块的语句。 1.时间 年份出处require/exprot...

  • require和import区别

    node编程中最重要的思想就是模块化,import和require都是被模块化所使用。 遵循规范–require ...

  • import和require的区别

  • import和require的区别

    node编程中最重要的思想就是模块化,import和require都是被模块化所使用。 遵循规范 require...

网友评论

      本文标题:require和import的区别

      本文链接:https://www.haomeiwen.com/subject/wcavmhtx.html