博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
理解import、require、export、module.export
阅读量:6432 次
发布时间:2019-06-23

本文共 3637 字,大约阅读时间需要 12 分钟。

理解import、require、export、module.export

ES6的模块设计

模块设计的思想是尽量静态化,使得编译的时候就可以确定模块的一来关系,以及输入和输出的变量。

CommonJS和AMD都只能在运行时确定这些东西,commonJS模块就是对象,输入时需要查找对象属性

// CommonJS模块let { stat, exists, readFile } = require('fs');// 等同于let _fs = require('fs');let stat = _fs.stat;let exists = _fs.exists;let readfile = _fs.readfile;

nodeJS 中模块化使用的就是CommonJS的规范,实质就是整体加载fs模块,生成fs_对象,在对象上读取属性和方法,

这种加载方式是“运行时加载”

ES6 模块

ES6 模块不是对象,而是通过export命令显式指定输出的代码,再通过import命令输入。
// ES6模块import { stat, exists, readFile } from 'fs';

上面代码的实质是从fs模块加载 3 个方法,其他方法不加载。这种加载称为“编译时加载”或者静态加载,即 ES6 可以在编译时就完成模块加载,效率要比 CommonJS 模块的加载方式高。

export命令

一个模块就是一个独立的文件。该文件内部的所有变量,外部无法获取。如果你希望外部能够读取模块内部的某个变量,就必须使用export关键字输出该变量。

// profile.jsexport var firstName = 'Michael';export var lastName = 'Jackson';export var year = 1958;// profile.jsvar firstName = 'Michael';var lastName = 'Jackson';var year = 1958;export {firstName, lastName, year};

export的语法,对外导出接口,在接口名与模块内部变量之间,建立了一一对应的关系。

// 写法一export var m = 1;// 写法二var m = 1;export {m};// 写法三var n = 1;export {n as m};

import命令

注意,import命令具有提升效果,会提升到整个模块的头部,首先执行。

目前阶段,通过 Babel 转码,CommonJS 模块的require命令和 ES6 模块的import命令,可以写在同一个模块里面,但是最好不要这样做。因为import在静态解析阶段执行,所以它是一个模块之中最早执行的。下面的代码可能不会得到预期结果。

require('core-js/modules/es6.symbol');require('core-js/modules/es6.promise');import React from 'React';

export default 命令

export default命令用于指定模块的默认输出。显然,一个模块只能有一个默认输出,因此export default命令只能使用一次。所以,import命令后面才不用加大括号,因为只可能唯一对应export default命令。

本质上,export default就是输出一个叫做default的变量或方法,然后系统允许你为它取任意名字。所以,下面的写法是有效的。

// modules.jsfunction add(x, y) {  return x * y;}export {add as default};// 等同于// export default add;// app.jsimport { default as foo } from 'modules';// 等同于// import foo from 'modules';// 正确export var a = 1;// 正确var a = 1;export default a;// 错误export default var a = 1;

CommonJS规范

每个文件就是一个模块,有自己的作用域。在一个文件里面定义的变量、函数、类,都是私有的,对其他文件不可见。

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;// 使用var example = require('./example.js');console.log(example.x); // 5console.log(example.addX(1)); // 6

CommonJS模块的特点

  1. 所有代码都运行在模块作用域,不会污染全局作用域。
  2. 模块可以多次加载,但是只会在第一次加载时运行一次,然后运行结果就被缓存了,以后再加载,就直接读取缓存结果。要想让模块再次运行,必须清除缓存。
  3. 模块加载的顺序,按照其在代码中出现的顺序。
export var foo = 'bar';setTimeout(() => foo = 'baz', 500);

ES6 模块化上面代码输出变量foo,值为bar,500 毫秒之后变成baz。

这一点与 CommonJS 规范完全不同。CommonJS 模块输出的是值的缓存,不存在动态更新

module对象

Node内部提供一个Module构建函数。所有模块都是Module的实例

module.id 模块的识别符,通常是带有绝对路径的模块文件名。

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

module.exports属性

module.exports属性表示当前模块对外输出的接口,其他文件加载该模块,实际上就是读取module.exports变量。

为了方便,Node为每个模块提供一个exports变量,指向module.exports。这等同在每个模块头部,有一行这样的命令。

var exports = module.exports;

造成的结果是,在对外输出模块接口时,可以向exports对象添加方法。

exports.area = function (r) {  return Math.PI * r * r;};exports.circumference = function (r) {  return 2 * Math.PI * r;};

注意,不能直接将exports变量指向一个值,因为这样等于切断了exports与module.exports的联系。

exports.hello = function() {  return 'hello';};module.exports = 'Hello world';

面代码中,hello函数是无法对外输出的,因为module.exports被重新赋值了。

这意味着,如果一个模块的对外接口,就是一个单一的值,不能使用exports输出,只能使用module.exports输出。

目录的加载规则

和node中模块加载规则一致

通常,我们会把相关的文件会放在一个目录里面,便于组织。这时,最好为该目录设置一个入口文件,让require方法可以通过这个入口文件,加载整个目录。

在目录中放置一个package.json文件,并且将入口文件写入main字段。下面是一个例子。

// package.json{ "name" : "some-library",  "main" : "./lib/some-library.js" }

require发现参数字符串指向一个目录以后,会自动查看该目录的package.json文件,然后加载main字段指定的入口文件。如果package.json文件没有main字段,或者根本就没有package.json文件,则会加载该目录下的index.js文件或index.node文件。

参考

转载地址:http://rexga.baihongyu.com/

你可能感兴趣的文章
执行命令取出linux中eth0的IP地址
查看>>
CRUD全栈式编程架构之控制器的设计
查看>>
python常用内建模块(五)
查看>>
你为什么有那么多时间写博客?
查看>>
Excel 中使用VBA
查看>>
$.ajax同步请求会阻塞js进程
查看>>
Postman 网络调试工具
查看>>
Python教程6
查看>>
zabbix实现自动发现功能添加磁盘监控
查看>>
mysql8.0.14 安装
查看>>
1039. 到底买不买(20)
查看>>
android笔试题一
查看>>
【JavaEE企业应用实战学习记录】getConnListener
查看>>
了解轮询、长轮询、长连接、websocket
查看>>
bzoj2427[HAOI2010]软件安装
查看>>
WPF个人助手更新
查看>>
NLPIR技术助力中文智能数据挖掘
查看>>
python操作redis--------------数据库增删改查
查看>>
Android中仿IOS提示框的实现
查看>>
php初学第一课
查看>>