欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

nodejs require exports module

程序员文章站 2022-07-14 20:30:01
...

环境

  • node = v7.9.0
  • os = macOS Mojave v10.14

准备

目录

-test

  • test-require.js
  • a.js
  • b.js
  • app.js

一、require

test-require.js

module.exports = function(){
   console.log('test require has run')
}

a.js

module.exports = function () {
    require('./test-require')
    console.log('a run')
}

b.js

module.exports = function () {
    require('./test-require')
    console.log('b run')
}

1.require用法

向app.js中加入以下代码,分别打开注释运行node app.js


var a = require('./a')
// var a = require('./a.js')
// var a = require('/Users/jyjin/workspace/gitProject/interview/a')
// var a = require('/Users/jyjin/workspace/gitProject/interview/a.js')
// var a = require('a')      // 错误
// var a = require('a.js')   // 错误

var b = require('./b.js')
a()
b()
console.log('app start...')
console.log('app start...')

结论

a.合法引用

require(’./a’) // 相对路径
require(’./a.js’)
require(’/Users/jyjin/workspace/gitProject/interview/a’) // 绝对路径
require(’/Users/jyjin/workspace/gitProject/interview/a.js’)

node app.js
a run
b run
app start...

b.错误引用

require(‘a.js’)
require(‘a’)

Error: Cannot find module 'a.js'
    at Function.Module._resolveFilename (module.js:470:15)
    at Function.Module._load (module.js:418:25)
    at Module.require (module.js:498:17)
    at require (internal/module.js:20:19)
    at Object.<anonymous> (/Users/jyjin/workspace/gitProject/interview/app.js:1:63)
    at Module._compile (module.js:571:32)
    at Object.Module._extensions..js (module.js:580:10)
    at Module.load (module.js:488:32)
    at tryModuleLoad (module.js:447:12)
    at Function.Module._load (module.js:439:3)
Error: Cannot find module 'a'
    at Function.Module._resolveFilename (module.js:470:15)
    at Function.Module._load (module.js:418:25)
    at Module.require (module.js:498:17)
    at require (internal/module.js:20:19)
    at Object.<anonymous> (/Users/jyjin/workspace/gitProject/interview/app.js:1:63)
    at Module._compile (module.js:571:32)
    at Object.Module._extensions..js (module.js:580:10)
    at Module.load (module.js:488:32)
    at tryModuleLoad (module.js:447:12)
    at Function.Module._load (module.js:439:3)

2.require加载模式

修改test-require.js, 如下

console.log(‘require initilized …’) // <- 添加此句代码
module.exports = function () {
console.log(‘test require has run’)
}

运行node app.js, 结果如下

node app.js
require initilized ...
a run
b run
app start...

结论

多次重复require某个模块时,require只会加载一次

二、exports与module.exports

1.exports用法

通常我们最熟悉的用法,exports可以导出多个模块,module.exports只可以导出单个模块(require例子中所有的模块可以看出)

现新建test-exports.js

var count = 0
var increment = 5
var setIncrement = function (_increment) {
if (!_increment)
console.error(‘parameter _increment is required!’)
increment = _increment
}
var printCount = function () {
count += increment
console.log('count in exports: ', count)
}
exports.setIncrement = setIncrement
exports.printCount = printCount

修改app.js如下

var {setIncrement, printCount} = require(’./test-exports’)
setIncrement(10)
printCount();
printCount();
printCount();
setIncrement(2)
printCount()
printCount()
printCount()
console.log(‘app start…’)
运行结果

node app.js
count in exports:  10
count in exports:  20
count in exports:  30
count in exports:  32
count in exports:  34
count in exports:  36

通过运行结果可以看出:exports可以作为模块接口导出多个模块

向test-exports中加入以下代码

var isEq = (exports == module.exports)
console.log('isEq : ', isEq)
console.log('exports: ', exports)
console.log('module.exports: ', module.exports)
运行观察exports和module.exports

运行node app.js观察结果

node app.js
isEq   :  true
exports:  { setIncrement: [Function: setIncrement],
  printCount: [Function: printCount] }
module.exports:  { setIncrement: [Function: setIncrement],
  printCount: [Function: printCount] }
count in exports:  10
count in exports:  20
count in exports:  30
count in exports:  32
count in exports:  34
count in exports:  36
app start...

可见
exports导出是一个对象,因此test-exports的导出语句可以优化为

exports.setIncrement = setIncrement
exports.printCount = printCount
// 等价于下面代码:
exports = {setIncrement, printCount}

并且在没有设置module.exports的情况下,module.exports和exports相同。实际上,exports最终只是module.exports一个地址引用

结论

  • exports可以作为模块接口导出多个模块
  • exports作为模块导出的接口,导出的是一个对象
  • exports是module.exports的一个引用(此例子还不能证明引用,在下文举例证明),即在没有设置module.exports只设置了exports的情况下module.exports=exports**

2.exports是module.exports的一个引用

修改test-exports如下

var count = 0
var increment = 5
var printCount = function () {
count += increment
console.log('count in exports: ', count)
}
exports.printCount = printCount
module.exports = function () {
increment = 2
count += increment
this.printCount = function () {
console.log('count in module.exports: ', count)
}
}
var isEq = (exports == module.exports)
console.log('isEq : ', isEq)
console.log('exports: ', exports)
console.log('module.exports: ', module.exports)

分别为exports和module.exports挂一个printCount方法,且实现不同,看谁覆盖谁

1.假设exports有效

修改app.js如下

var te = require(’./test-exports’)
te.printCount()

运行node app.js结果

node app.js
isEq   :  false
exports:  { printCount: [Function: printCount] }
module.exports:  function () {
    increment = 2
    count += increment
    this.printCount = function () {
        console.log('count in module.exports: ', count)
    }
}
/Users/jyjin/workspace/gitProject/interview/app.js:26
te.printCount()
   ^

TypeError: te.printCount is not a function
    at Object.<anonymous> (/Users/jyjin/workspace/gitProject/interview/app.js:26:4)
    at Module._compile (module.js:571:32)
    at Object.Module._extensions..js (module.js:580:10)
    at Module.load (module.js:488:32)
    at tryModuleLoad (module.js:447:12)
    at Function.Module._load (module.js:439:3)
    at Module.runMain (module.js:605:10)
    at run (bootstrap_node.js:423:7)
    at startup (bootstrap_node.js:147:9)
    at bootstrap_node.js:538:3

显然
此时exports和module.exports不相同,并且没有办法通过te.printCount()调用printCount方法,也就是说exports没有生效。

假设exports生效不成立

那module.exports有没有生效?

2.假设module.exports有效

再修改app.js如下

var t = new te()
t.printCount();

注意:

  • 成员方法调用需要new进行实例化

运行node app.js结果

node app.js
isEq   :  false
exports:  { printCount: [Function: printCount] }
module.exports:  function () {
    increment = 2
    count += increment
    this.printCount = function () {
        console.log('count in module.exports: ', count)
    }
}
count in module.exports:  2
app start...

运行成功!

结论

当exports与module.exports不相同时,模块的导出以module.exports为准
结合exports使用的例子,可以看出exports仅仅是module.exports的一个地址引用