module.export和exports两者区别及使用方法

参考链接:简书博客简书博客CommonJS规范

功能介绍

module.exports

Node应用由模块组成,采用CommonJS模块规范。根据这个规范,每个文件就是一个模块,有自己的作用域。在这些文件里面定义的变量、函数、类,都是私有的,对外不可见,因此规避掉了作用域污染。
根据CommonJS规定,每个模块内部,module变量代表当前模块,这个变量是一个对象,它的exports属性(即module.exports)是对外的接口。加载某个模块,其实就是加载该模块的exports属性。
举例:通过module.exports输出变量 age 和 sayHelloTo 函数。

./MyModule.js
    var age = 7; 
    var sayHelloTo= function (name) { 
        return "hello " + name;
    }; 
    module.exports.age = age; 
    module.exports.sayHelloTo=sayHelloTo;

参考链接:module.exports的使用方法

require:用于加载模块

var temp = require('./MyModule.js');  //这里也可以使用 import myModule from './MyModule.js'
console.log(temp.age); // 7 
console.log(temp.sayHelloTo("Steve")); // hello Steve

额外说明:对于自定义的模块,需要使用相对路径,否则会提示找不到模块/组件(默认情况下,非相对路径的引用,会从node_modules文件夹中查找)

exports 与 module.exports

为了方便,node为每个模块提供了一个exports变量,指向module.exports。这等同于在每个模块头部,有这么一行代码:

var exports = module.exports;

因此,我们可以直接在exports对象上添加方法(等同于在 module.exports 添加一样)

./MyModule.js
    var age = 7; 
    var sayHelloTo= function (name) { 
        return "hello " + name;
    }; 
    exports.age = age;  //等效于:  module.exports.age = age;
    exports.sayHelloTo=sayHelloTo;  //等效于: module.exports.sayHelloTo=sayHelloTo;

PS:不能直接将exports指向一个值,这会切断 exports 与 module.exports 的联系(但是可以用module.exports来指向一个值)

./MyModule.js
    var age = 7; 
    var sayHelloTo= function (name) { 
        return "hello " + name;
    }; 
    exports = age;  //不要这么干。这么做会切断exports与module.exports的联系

module.export和exports两者区别

你可以用它创建你的模块。例如:(假设这是rocker.js文件)

exports.name = function() {
    console.log('my name is cp');
}

在另一个文件中引用rocker.js

var rocker = require('./rocker.js');
rocker.name(); // my name is cp

先来看一个例子

var a = {name: 1};
var b = a;

console.log(a);
console.log(b);

b.name = 2;
console.log(a);
console.log(b);

var b = {name: 3};
console.log(a);
console.log(b);

// 运行输出结果为:
// { name: 1 }
// { name: 1 }
// { name: 2 }
// { name: 2 }
// { name: 2 }
// { name: 3 }

a 是一个对象,b 是对 a 的引用,即 a 和 b 指向同一块内存,所以前两个输出一样。当对 b 作修改时,即 a 和 b 指向同一块内存地址的内容发生了改变,所以 a 也会体现出来,所以第三四个输出一样。当 b 被覆盖时,b 指向了一块新的内存,a 还是指向原来的内存,所以最后两个输出不一样。
module.exports和exports到底是什么?

其实,Module.exports才是真正的接口,exports只不过是它的一个辅助工具。 最终返回给调用的是Module.exports而不是exports。

所有的exports收集到的属性和方法,都赋值给了Module.exports。当然,这有个前提,就是Module.exports本身不具备任何属性和方法。如果,Module.exports已经具备一些属性和方法,那么exports收集来的信息将被忽略。
修改rocker.js如下:

module.exports = 'ROCK IT!';
exports.name = function() {
    console.log('my name is cp');
}

再次引用执行rocker.js

var rocker = require('./rocker.js');
rocker.name();

出现报错:rocker.name is not a function

rocker模块忽略了exports收集的name方法,返回了一个字符串“ROCK IT!”。由此可知,你的模块并不一定非得返回“实例化对象”。你的模块可以是任何合法的javascript对象–boolean, number, date, JSON, string, function, array等等。
你的模块可以是任何你设置给它的东西。如果你没有显式的给module.exports设置任何属性和方法,那么你的模块就是exports设置给module.exports的属性。

结论:

  • module.exports 初始值为一个空对象 {}
  • exports 是指向的 module.exports 的引用
  • require() 返回的是 module.exports 而不是 exports

使用方法

用两个例子来解析
例子1:
下面例子中,你的模块是一个类:

module.exports = function(name, age) {
    this.name = name;
    this.age = age;
    thisl.about = function() {
        console.log(this.name + 'is' + this.age + 'years old');
    };
};

你可以这样引用它:

var Rocker = require('./rocker.js');
var r = new Rocker('Ozzy', 62);
r.about(); // Ozzy is 62 years old

例子2:
下面例子中,你的模块是一个数组:

module.exports = ['Lemmy Kilmister', 'Ozzy Osbourne', 'Ronnie James Dio', 'Steven Tyler', 'Mick Jagger'];

你可以这样引用它:

var rocker = require('./rocker.js');
console.log('Rockin in heaven: ' + rocker[2]); // Rocking in heaven: Ronnie James Dio

什么时候用exports?什么时候用module.exports?

从以上两个例子,我们可以总结出:

  • 如果你想你的模块是一个特定的类型就用Module.exports。
  • 如果你想的模块是一个典型的“实例化对象”就用exports。

给module.exports添加属性类似于给exports添加属性,例如:

module.export.name = function() {
    console.log('my name is cp');
}

同样,exports是这样的

exports.name = function() {
    console.log('my name is cp');
}

注意: 这两种结果并不相同。前面已经提到module.exports是真正的接口,exports只不过是它的辅助工具。推荐使用exports导出,除非你打算从原来的“实例化对象”改变成一个类型。

在ES6中,使用export default 和 export 向外暴露成员

用 export 导出的模块,需要用 import 来进行导入,而不能用 require。
node中导入模块:var 名称 = require(‘模块标识符’)

node中向外暴露成员的形式:module.exports = {}

在ES6中,也通过规范的形式,规定了ES6中如何导入和导出模块

ES6中导入模块,使用

  • import 模块名称 from ‘模块标识符’
  • import ‘表示路径’

import *** from *** 是ES6中导入模块的方式
例如:

// test.js
export default {
    name: 'zs',
    age: 20
}

或是

// test.js
var info = {
    name: 'zs',
    age: 20
}
export default info

在main.js中接收,test.js使用export default 向外暴露的成员

import person from './test.js'
console.log(person);


注意:

1、export default 向外暴露的成员,可以使用任意变量来接收

2、在一个模块中,export default 只允许向外暴露一次

3、在一个模块中,可以同时使用export default 和export 向外暴露成员

4、使用export向外暴露的成员,只能使用{ }的形式来接收,这种形式,叫做【按需导出】

5、export可以向外暴露多个成员,同时,如果某些成员,在import导入时,不需要,可以不在{ }中定义

6、使用export导出的成员,必须严格按照导出时候的名称,来使用{ }按需接收

7、使用export导出的成员,如果想换个变量名称接收,可以使用as来起别名

猜你喜欢

转载自blog.csdn.net/weixin_44339850/article/details/99887127