剖析require、import、export、exports、module.exports以及export default 的基本用法

简介: 剖析require、import、export、exports、module.exports以及export default 的基本用法

文章目录

1、预备知识

要想对require、import 、export、export default、 exports、module.exports了解的更为清楚, 我们不得不先来谈谈Node.js以及AMD、CMD、UMD等规范。

Node.js

百度百科

Node.js发布于2009年5月,由Ryan Dahl开发,是一个基于Chrome V8引擎的JavaScript运行环境,使用了一个事件驱动、非阻塞式I/O模型,让JavaScript 运行在服务端的开发平台,它让JavaScript成为与PHPPythonPerlRuby等服务端语言平起平坐的脚本语言

Node.js对一些特殊用例进行优化,提供替代的API,使得V8在非浏览器环境下运行得更好,V8引擎执行Javascript的速度非常快,性能非常好,基于Chrome JavaScript运行时建立的平台, 用于方便地搭建响应速度快、易于扩展的网络应用。 [3]

通俗的说法

Node.js就是前端开发人员转后端开发的首选语言,经常搭配Express框架进行快速开发。

模块化系统以及CommonJs

值得一提的是,在Node环境中,采用的是模块化系统(即每个js文件就是一个模块)。


CommonJs 是一种 JavaScript 语言的模块化规范,它通常会在服务端的 Nodejs 上使用。项目是由多个模块组成的,模块和模块之间的调用,需要各个模块有相同规范的 API,这样一来在使用的过程中不会有那么多的学习成本,并且对于单个模块来说是类聚的。

在 CommonJs 的模块化规范中,每一个文件就是一个模块,拥有自己独立的作用域、变量、以及方法等,对其他的模块都不可见。CommonJS规范规定,每个模块内部,module 变量代表当前模块。这个变量是一个对象,它的 exports 属性(module.exports)是对外的接口。加载某个模块,其实是加载该模块的 module.exports 属性。require 方法用于加载模块。

//moudle-a.js
moudle.exports = {
    a: 1
};
//moudle-b.js
var ma = require('./moudle-a');
var b = ma.a + 2;
module.exports ={
    b: b
};

模块化规范给项目带来的好处

在业务复杂,模块众多的大型项目中,开发者都遵循相同的规则来开发各自的模块,他们通过规范来约束模块的定义,大家不需要太多的沟通或者大量的文档来说明自己的模块使用规则,成千上万的模块就这样生产,并能够容易的使用。它的意义不仅是让模块看起来很规范,在合作开发、社区中传播中也起到了重大的作用。

AMD

AMD 叫做异步模块定义规范(Asynchronous Module Definition),它是 CommonJs 模块化规范的超集,但是运行于浏览器之上的。AMD 的特点就和它的名字一样,模块的加载过程是异步的,它大大的利用了浏览器的并发请求能力,让模块的依赖过程的阻塞变得更少了。requireJs 就是 AMD 模块化规范的实现。

AMD 作为一个规范,只需定义其语法 API,而不关心其实现。AMD 规范简单到只有一个 API,即 define 函数:

define(id?, dependencies?, factory);
• 1

具体用法如下:

// moudle-a.js
define('moudleA', function() { 
    return {
        a: 1
    }
});
// moudle-b.js
define(['moudleA'], function(ma) {
    var b = ma.a + 2;
    return {
        b: b
    }
});

它看起来似乎和 CMD 差不多,不过在实现上还是有一定的差异,它们各有优缺点,我们未来会专门对这些模块化规范做对比。

CMD

CMD 叫做通用模块定义规范(Common Module Definiton),它是类似于 CommonJs模块化规范,但是运行于浏览器之上的,关于模块化的好处我们在 上文了解过。它是随着前端业务和架构的复杂度越来越高运用而生的,来自淘宝玉伯的 SeaJS 就是它的实现。

CMD 规范尽量保持简单,并与 CommonJS 的 Modules 规范保持了很大的兼容性。通过 CMD 规范书写的模块,可以很容易在 Node.js 中运行。在 CMD 规范中,一个模块就是一个文件。格式如下:

define(factory);

具体用法如下:

// moudle-a.js
define(function(require, exports, module) {
    module.exports = { 
        a: 1 
    };
});
// moudle-b.js
define(function(require, exports, module) {
    var ma = require('./moudle-a');
    var b = ma.a + 2;
    module.exports = { 
        b: b 
    };
});

CMD 规范拥有简单、异步加载脚本、友好的调试并且兼容 Nodejs,它的确在开发过程中给我们提供了较好的模块管理方式。

UMD

UMD 叫做通用模块定义规范(Universal Module Definition)。也是随着大前端的趋势所诞生,它可以通过运行时或者编译时让同一个代码模块在使用 CommonJs、CMD 甚至是 AMD 的项目中运行。未来同一个 JavaScript 包运行在浏览器端、服务区端甚至是 APP 端都只需要遵守同一个写法就行了。

它没有自己专有的规范,是集结了 CommonJs、CMD、AMD 的规范于一身,我们看看它的具体实现:

((root, factory) => {
    if (typeof define === 'function' && define.amd) {
        //AMD
        define(['jquery'], factory);
    } else if (typeof exports === 'object') {
        //CommonJS
        var $ = requie('jquery');
        module.exports = factory($);
    } else {
        root.testModule = factory(root.jQuery);
    }
})(this, ($) => {
    //todo
});

不难发现,它在定义模块的时候回检测当前使用环境和模块的定义方式,将各种模块化定义方式转化为同样一种写法。它的出现也是前端技术发展的产物,前端在实现跨平台的道路上不断的前进,UMD 规范将浏览器端、服务器端甚至是 APP 端都大统一了,当然它或许不是未来最好的模块化方式,未来在 ES6+、TypeScript、Dart 这些拥有高级语法的语言会代替这些方案。

2、正文

1、require

  • 在Node环境中用于加载模块
  • 例如Node加载fs模块
const fs = require('fs')

2、import

  • ES6的一个语法,可通过Babel转化成ES5的require
// 导入默认模块
import defaultExport from "module-name";
// 导入模块的所有对象,并命名为name
import * as name from "module-name";
// 导入模块中的export对象, 使用了ES6的解构赋值
import { export } from "module-name";
// 导入模块中的export对象并命名为alias, 使用了ES6的解构赋值
import { export as alias } from "module-name";

3、export与export default

export与export default ,是ES6规范,被使用于React或Vue中。

在创建JavaScript模块时,**export** 语句用于从模块中导出实时绑定的函数、对象或原始值,以便其他程序可以通过 import 语句使用它们。被导出的绑定值依然可以在本地进行修改。在使用import进行导入时,这些绑定值只能被导入模块所读取,但在export导出模块中对这些绑定值进行修改,所修改的值也会实时地更新。

4、exports与module.exports

module.exportsexports,是CommonJS的规范,被使用于Node.js中。

其中通过查看exports的源码可以发现:

  • 在Node中,每一个模块内都有一个自己的module对象
  • module中有个exports 空对象
var module = {
    exports:{
    },
}
return module.exports
  • Node为了简化 module.exports = xxx, 在底层定义了var exports = module.exports
  • globals.ts部分代码 即 node部分源码
declare var require: NodeRequire;
declare var module: NodeModule;
// Same as module.exports
declare var exports: any;
  • 导出多个成员(导出对象)
exports.a = 123
exports.b = 'hello'
exports.c = function(){
    console.log('hello')
}
exports.d = {
    name:'Tom'
}
  • exports的基本用法
  • 导出一个成员
module.exports = 'hello'
  • 以下情况会覆盖
module.exports = 'hello'
// 覆盖前面的module.exports
module.exports = 'asd'
  • 也可以通过导出一个对象来导出多个成员
module.exports = {
    a:'hello',
    b:function(){
        console.log('bbbb')
    }
}

等价于

exports.a = 'hello'
exports.b = function(){console.log('bbbb')}

参考链接

相关文章
|
8天前
export 与 import | ES6
export 与 import | ES6
15 0
export 与 import | ES6
|
2月前
|
JavaScript 前端开发
ES6之Module:export、import
ES6之Module:export、import
|
5月前
|
JavaScript
export default和module.exports
export default和module.exports
24 0
|
6月前
|
JavaScript 小程序 前端开发
详解module.exports与exports,export与export default,import 与require
详解module.exports与exports,export与export default,import 与require
33 0
|
9月前
导出与导入(require,import,module.exports,exports,export,export default)
导出与导入(require,import,module.exports,exports,export,export default)
41 0
|
9月前
|
JavaScript C++
Module ‘“xx.vue“‘ has no default export.Vetur(1192)
Module ‘“xx.vue“‘ has no default export.Vetur(1192)
533 0
|
JSON JavaScript 前端开发
Vue export & export default & import 总结
Vue export & export default & import 总结
155 0
require('module') 是什么?
关于 node 中 module 得解释
62 0
|
JavaScript
Vue export和export default的区别
Vue export和export default的区别
40 0
|
JavaScript
export ,export default 和 import 区别 以及用法
export ,export default 和 import 区别 以及用法