var exports = module.exports
当通过exports去改变内存块里内容时,module.exports的值也会改变
当通过module.exports去改变内存块里内容时,exports的值也会改变
当module.exports被改变的时候,exports不会被改变
当exports被改变的时候,module.exports不会被改变
所以,exports属性的出现应该可以直接向exports对象添加方法,从而方便对外输出模块接口。不过当module.exports改变时,exports与module.exports也就断开了链接,所以最好不要采用这种方式,统一采用module.exports方式。
module.exports.a = 100
console.log("log1: " + exports.a)
exports.a = 200;
console.log("log2: " + module.exports.a)
module.exports = "hello"
console.log("log3: " + JSON.stringify(exports))
复制代码
module.exports可以导出所有的类型。对象,函数,字符串、数值等。
语法示例:
var x = 5
var str = "hello"
var addX = function (value) {
return value + x
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
toString() {
return '(' + this.x + ', ' + this.y + ')';
module.exports = {
x: x,
str: str,
addX: addX,
Point: Point
exports = {
x: 10,
复制代码
require
requirer用于加载模块,是node的一个全局方法,使用非常简单
const xxx = require("模块名")
复制代码
读入并执行一个JavaScript文件,返回模块的exports对象。如果没有发现指定模块,会报错。
require方法接受以下几种参数的传递:
原生模块,如http、fs、path等
相对路径的文件模块,如./mod或../mod
绝对路径的文件模块,如 /pathtomodule/mod
第三方模块,如koa等
在模块目录中通常有一个package.json文件,并且将入口文件写入main字段
{ "name" : "some-library",
"main" : "./lib/some-library.js" }
复制代码
require发现参数字符串指向一个目录以后,会自动查看该目录的package.json文件,然后加载main字段指定的入口文件。
如果package.json文件没有main字段,或者根本就没有package.json文件,则会加载该目录下的index.js文件或index.node文件
因为模块导出的实际是module.exports,所以require只能看到通过 module.exports 导出的内容,看不到通过exports导出的内容。它相当于module.exports的传送门,module.exports后面的内容是什么,require的结果就是什么,对象、数字、字符串、函数...再把require的结果赋值给某个变量。
针对上面的 module_export_domo2.js 文件,引入模块示例
const demo2 = require("./module_export_demo2")
console.log(demo2.x)
console.log(demo2.str)
console.log(demo2.addX(15))
let point = new demo2.Point(3, 4)
console.log(point.toString())
复制代码
require 是运行时的,其参数可以是表达式
let value = 2
const demo2 = require("./module_export" + "_demo" + value)
复制代码
require函数加载模块
require函数加载模块顺序按照其在代码中出现的顺序
require函数加载模块是同步的,只有加载完成,才能执行后面的操作
require函数加载的模块是被输出的值的拷贝,不会受到模块内容变化影响
// module_export_demo3.js
var counter = 3
function incCounter() {
counter++
module.exports = {
counter: counter,
incCounter: incCounter,
复制代码
const demo3 = require("./module_export_demo3")
console.log(demo3.counter);
demo3.incCounter();
console.log(demo3.counter);
复制代码
counter输出结果说明module_export_demo3模块内部的变化就影响不到counter了
模块第一次被加载时会执行一次,后续被加载时不会再执行,都是从缓存中获取的
console.log("hello")
module.exports = "wrold"
复制代码
const demo3 = require("./module_export_demo3")
const demo3_1 = require("./module_export_demo3")
const demo3_2 = require("./module_export_demo3")
const demo3_3 = require("./module_export_demo3")
const demo3_4 = require("./module_export_demo3")
const demo3_5 = require("./module_export_demo3")
console.log(demo3)
console.log(demo3_1)
复制代码
hello只会被打印一次说明console.log("hello")语句只执行了一次,module_export_demo3.js只被加载了一次。
ES6模块规范
ES6发布的module并没有直接采用CommonJS,甚至连require都没有采用,也就是说require仍然只是node的一个私有的全局方法,module.exports也只是node私有的一个全局变量属性,跟标准什么关系都没有。
ES6模块规范是,在创建JS模块时,export 语句用于从模块中导出函数、对象或原始值,以便其他程序可以通过 import 语句使用它们。
export 和 export default
ES6模块导出有两种方式:export(命名导出) 和 export default(默认导出)。
在导出多个值时,命名导出非常有用。在导入时,必须使用相应对象的相同名称。但是,可以使用任何名称导入默认导出。
export语法介绍
export let name1, name2, …, nameN;
export let name1 = …, name2 = …, …, nameN;
export function FunctionName(){...}
export class ClassName {...}
export { name1, name2, …, nameN };
export { variable1 as name1, variable2 as name2, …, nameN };
export default expression;
export default function (…) { … }
export default function name1(…) { … }
export { name1 as default, … };
export { name1, name2, …, nameN } from …;
export { import1 as name1, import2 as name2, …, nameN } from …;
export * from …;
export { default } from …;
export与export default均可用于导出常量、函数、文件、模块等
通过export方式导出,在导入时要加{ },export default则不需要
在一个文件中,export可以有多个,export default仅有一个
大部分风格建议,模块中最好在末尾用一个export导出所有的接口
export 1
const value = 1
export { value }
export const value = 1
const value = 1
export default value
export default 1
复制代码
export default是别名的语法糖,这个语法糖的好处在是
import的时候,可以省去花括号{}。
import的时候, 可以起任何变量名表示引入变量
所以如果import的时候,你发现某个变量没有花括号括起来(除了* 号),是因为该变量是通过export default 导出的。
export default function() {}
复制代码
import a from "d.js" // a 是 {defalut as a}的替代写法。
复制代码
所以使用export default命令,为模块指定默认输出,这样就不需要知道所要加载模块的变量名。
let sex = "boy";
export default sex
复制代码
本质上,a.js文件的export default输出一个叫做default的变量,然后系统允许你为它取任意名字。 自然default只能有一个值,所以一个文件内不能有多个export default。
import any from "./a.js"
import any12 from "./a.js"
console.log(any, any12)
复制代码
import
require 和 import是完全不同的两种概念。require是赋值过程,import是解构过程
const xxx = require("模块名")
import { xxx } from "模块名"
import是编译时的, 必须放在文件开头,否则会报错
import后面跟上花括号的形式是最基本的用法,花括号里面的变量与export后面的变量一一对应。
import {a} from ..
支持给变量取别名。因为有的时候不同的两个模块可能有相同的接口,可以给这个变量取一个别名,方便在当前的文件里面使用。
import {a as a_a} from ..
复制代码
import介绍语法
import defaultExport from "module-name";
import * as name from "module-name";
import { export1 } from "module-name";
import { export1 as alias1 } from "module-name";
import { export1 , export2 } from "module-name";
import { foo , bar } from "module-name/path/to/specific/un-exported/file";
import { export1 , export2 as alias2 , [...] } from "module-name";
import defaultExport, { export1 [ , [...] ] } from "module-name";
import defaultExport, * as name from "module-name";
import "module-name";
var promise = import("module-name");
复制代码
Node为何支持export / import
我们经常会看到在node中也会用export / import,这是什么呢?
我们在node中使用babel支持ES6,仅仅是将ES6转码为ES5再执行,import语法会被转码为require。因为目前所有的引擎都还没有实现export / import。
如何让Node.js支持ES6的语法具体参考在node环境中支持ES6代码
import {a} from "./demo.js"
var _demo = require("./demo.js")
复制代码
这也是为什么在使用module.exports模块导出时,在引入模块时使用import仍然起效,因为本质上,import会被转码为require去执行。
CommonJS规范中,建议尽量都用 module.exports 导出,然后用require导入
ES6规则中,大部分风格建议,模块中最好在末尾用一个export导出所有的接口
module.exports / exports: 只有 Node 支持的导出
require: Node 和 ES6 都支持的引入
export / import : 只有ES6 支持的导出引入
javascript.ruanyifeng.com/nodejs/modu…
- 105
-
勇敢的Jerry
ECMAScript 6