import和require的区别

关于 importrequire 的不一样,其实能够理解成 CommonJs 和 ES Module 的区别。这二者都是前端模块化的规范。前端

咱们在 node 里使用的是 CommonJs,在前端页面的时候,用的是 ES Module,这二者的区别,仍是很容易混淆的,因此整理一下 CommonJs 和 ES Moudule 的相关知识点,把这里好好的整理一下。node

1、CommonJses6

1.1 概述json

Nodejs 是 CommonJS 规范的主要实践者,在 CommonJs 里每一个文件就是一个模块,有本身的做用域。在一个文件里面定义的变量、函数、类,都是私有的,对其余文件不可见。CommonJs 提供了四个重要的环境变量为模块化的实现提供支持:moduleexportsrequireglobal。CommonJS 规定,每一个模块内部,module 变量表明当前模块。这个变量是一个对象,它的 exports 属性(即 module.exports )是对外的接口。加载某个模块,实际上是加载该模块的 module.exports 属性。数组

var x = 5;
var addX = function (value) {
 return value + x;
};

module.exports.x = x;
module.exports.addX = addX;

而使用 require 方法来引入并加载模块缓存

var example = require('./example.js');

console.log(example.x); // 5
console.log(example.addX(1)); // 6

1.2 CommonJS模块的特色模块化

  • 全部代码都运行在模块做用域,不会污染全局做用域。
  • CommonJS 用同步的方式加载模块。
  • 模块能够屡次加载,可是只会在第一次加载时运行一次,而后运行结果就被缓存了,之后再加载,就直接读取缓存结果。要想让模块再次运行,必须清除缓存。
  • 模块加载的顺序,按照其在代码中出现的顺序。

关于变量:函数

一、module 对象是 node 里的 Module 构造函数的实例,表明当前模块。具备如下属性:ui

  • module.id 模块的识别符,一般是带有绝对路径的模块文件名。
  • module.filename 模块的文件名,带有绝对路径。
  • module.loaded 返回一个布尔值,表示模块是否已经完成加载。
  • module.parent 返回一个对象,表示调用该模块的模块。
  • module.children 返回一个数组,表示该模块要用到的其余模块。
  • module.exports 表示模块对外输出的值。

二、exportsthis

NodeJs 为每一个模块提供一个 exports 变量,指向 module.exports在使用的时候,能够直接给 exports 添加属性,就会指向 module.exports。可是不能给 exports 直接赋值一个变量,这样会切断 exportsmodule.exports 之间的联系。

若是有 exportsmodule.exportsexports 就会失效,只会输出 module.exports 的,由于 module.exports 被从新赋值了。

三、global

这是一个全局变量声明方式,就能够全局用这个 warning 变量了。

global.warning = true;

四、require

require 命令用于加载模块文件。

require 命令的基本功能是,读入并执行一个 JavaScript 文件,而后返回该模块的 exports 对象
加载规则:

  • 若是参数字符串以“/”开头,则表示加载的是一个位于绝对路径的模块文件。
  • 若是参数字符串以“./”开头,则表示加载的是一个位于相对路径(跟当前执行脚本的位置相比)的模块文件。
  • 若是参数字符串不以“./“或”/“开头,则表示加载的是一个默认提供的核心模块(位于Node的系统安装目录中),或者一个位于各级node_modules目录的已安装模块(全局安装或局部安装)。
  • 若是参数字符串不以“./“或”/“开头,并且是一个路径,好比 require('example-module/path/to/file'),则将先找到 example-module 的位置,而后再以它为参数,找到后续路径。
  • 若是指定的模块文件没有发现,Node会尝试为文件名添加.js、.json、.node后,再去搜索。.js件会以文本格式的JavaScript脚本文件解析,.json文件会以JSON格式的文本文件解析,.node文件会以编译后的二进制文件解析。
  • 若是想获得 require 命令加载的确切文件名,使用 require.resolve() 方法。

require函数及其辅助方法主要以下。

  • require(): 加载外部模块
  • require.resolve():将模块名解析到一个绝对路径
  • require.main:指向主模块
  • require.cache:指向全部缓存的模块
  • require.extensions:根据文件的后缀名,调用不一样的执行函数

关于缓存:

在屡次加载某个相同的模块时,若是前面的模块已经操做了,后面调用时,拿到就再也不是最初时的数据了,就是通过前面操做事后的数据了。

全部缓存的模块保存在 require.cache 之中,若是想删除模块的缓存,能够像下面这样写。

// 删除指定模块的缓存
delete require.cache\[moduleName\];

// 删除全部模块的缓存
Object.keys(require.cache).forEach(function(key) {
 delete require.cache\[key\];
})

注意:缓存是根据绝对路径识别模块的,若是一样的模块名,可是保存在不一样的路径,require 命令仍是会从新加载该模块。

1.3 模块的加载机制

CommonJS 模块的加载机制是,输入的是被输出的值的拷贝。也就是说,一旦输出一个值,模块内部的变化就影响不到这个值。

2、ES Module

2.1 概述

ES6 模块的设计思想是尽可能的静态化,使得编译时就能肯定模块的依赖关系,以及输入和输出的变量。因此ES6 模块不是对象,而是经过 export 命令显式指定输出的代码,再经过 import 命令输入。这种加载称为“编译时加载”或者静态加载,即 ES6 能够在编译时就完成模块加载,效率要比 CommonJS 模块的加载方式高。固然,这也致使了无法引用 ES6 模块自己,由于它不是对象。

2.2 ES Module的特色:

ES6 的模块功能主要由两个命令构成:exportimportexport 命令用于规定模块的对外接口。import 命令用于输入 其余模块提供的功能。

  • ES6 模块必须用 export 导出
  • export 必须与模块内部的变量创建一一对应关系

一、export命令

  • 一个模块就是一个独立的文件。该文件内部的全部变量,外部没法获取。若是你但愿外部可以读取模块内部的某个变量,就必须使用 export 关键字输出该变量。
  • export 命令规定的是对外的接口,必须与模块内部的变量创建一一对应关系。

二、import命令

  • import 命令输入的变量都是只读的
  • import 命令具备提高效果
  • import 是静态执行,因此不能使用表达式和变量
  • import 语句是 Singleton 模式,若是屡次重复执行同一句 import 语句,那么只会执行一次,而不会执行屡次。

三、export default 命令

  • export default 就是输出一个叫作 default 的变量或方法
  • export default 因此它后面不能跟变量声明语句

3、CommonJs 和 ES Module的区别

  • ES6 模块输出的是值的引用,CommonJS 模块输出的是一个值的拷贝
  • ES6 模块是编译时输出接口,CommonJS 模块是运行时加载。
  • ES6 模块不是对象,它的对外接口只是一种静态定义,在代码静态解析阶段就会生成。而 CommonJS 加载的是一个对象(即 module.exports 属性),该对象只有在脚本运行完才会生成。
es6 {

 export : ‘能够输出多个,输出方式为 {}’ ,

 export default : ‘ 只能输出一个 ,能够与 export 同时输出,可是不建议这么作’,

 解析阶段肯定对外输出的接口,解析阶段生成接口,

 模块不是对象,加载的不是对象,

 能够单独加载其中的某个接口(方法),

 静态分析,动态引用,输出的是值的引用,值改变,引用也改变,即原来模块中的值改变则该加载的值也改变,

 this 指向 undefined

}

  

commonJS {

 module.exports = … : ‘只能输出一个,且后面的会覆盖上面的’ ,

 exports. … : ‘ 能够输出多个’,

 运行阶段肯定接口,运行时才会加载模块,

 模块就是对象,加载的是该对象,

 加载的是整个模块,即将全部的接口所有加载进来,

 输出的是值的拷贝,即原来模块中的值改变不会影响已经加载的该值,

 this 指向当前模块

}
相关文章
相关标签/搜索