node.js中的module模块

模块模式

我们把每一个 .js 文件都视为一个 模块模块内部有自己的作用域,不会影响到全局。并且,我们约定一些关键词来进行依赖声明和 API 暴露。在js中有几种用于实现模块的方法和规范:

  • 对象字面量表示法
  • Module模式

以下是一些模块化规范,括号内为对应的脚本加载器

  • CMD(SeaJS)
  • AMD(RequireJS)
  • CommonJS(NodeJS)
  • ES6 Module (ECMAScript 2015)

比较有名模块化规范的是 CMD、AMD、CommonJS 和 ES6 Module,它们都是为了实现在浏览器端模块化开发的目的。前面两个规范分别来自 SeaJS 及 RequireJS,这两个规范现在基本已经很少人用了;CommonJS 由于是被 NodeJS 所采用的,所以很多人用;而 ES6 Module 自然是来自去年正式发布的 ECMAScript 2015 所采用的了,以后会逐渐成为最主要的模块化规范。

对象字面量

在对象字面量表示法中,一个对象被描述为一组包含在大括号中、以逗号分隔的名值对。

对象字面量不需要使用new操作符进行实例化。使用对象字面量有助于封装和组织代码,即将所有属性和方法封装在一个变量中。

var myModule = {
    //属性
    myProperty:"someValue",
    //一些用于配置的属性
    myConfig:{
        language:"English",
        useCaching:true
    },
    //基本方法
    Method:function(){
        console.log("test")
    },
    //用于输出配置的方法
    Method2:function(){
        console.log(this.myConfig.language);
    },
    //用于设置配置的方法
    Method3:function(newConfig){
        this.myConfig = newConfig;
        console.log(this.myConfig)
    }
}
myModule.Method();//test
myModule.Method2(); //true
myModule.Method3({
    language:"Chinese",
    useCaching:false
});//Object {language: "Chinese", useCaching: false}

Module模块模式

1、概念:用于进一步模拟类的概念,通过这种方式,能够使一个单独的对象拥有公有/私有变量和方法,从而构成自己的一个私有作用域,减少命名冲突的可能性。这样会解决两个问题:

     1)冲突:不同js文件中除非将所有的变量和函数用命名空间单独包起来,不然每一个js文件中定义的变量和函数都是全局的。可能存在命名等一系列的冲突;

     2)依赖:不同的js文件在加载时存在一定的先后顺序,这种先后取决于它们之间的依赖关系,有可能存在相互均存在依赖关系,无法决定加载顺序的情况

2、模块实例的require方法

我们都知道,当使用exports或者module.exports抛出一个模块,通过给require()方法传入模块标识符参数,然后node根据一定的规则引入该模块之后,我们就能使用模块中定义的方法和属性了。

node的模块引入规则:

1)注意引入的路径地址,如果模块的路径填写的是相对路径,那么加载的就是文件模块,如果填写的不是以相对路径开始的,那么就是文件夹模块。

2)所有需要引入的node模块应该统一都放到node_modules文件下,在同级文件目录下还会有一个pack.json文件(说明配置文件),里面会记载着一些配置信息,版本号等。

3)在package.json文件通过main选项可以指定模块的入口文件(主文件),那么通过require加载模块的时候,加载的就是该main指定的文件,node通过 require( ) 来加载模块。

3、module.exports    

module对象具有一个exports属性,该属性就是用来对外暴露变量、方法或整个模块的。当其他的文件require进来该模块的时候,实际上就是读取了该模块module对象的exports属性。

4、 exports对象

 exports和module.exports都是引用类型的变量,而且这两个对象指向同一块内存地址。在node中,二者一开始都是指向一个空对象的,exports对象是通过形参的方式传入的,直接赋值形参会改变形参的引用,但是并不能改变作用域外的值。代码如下:

var module = {
    exports: {}
}
var exports = module.exports
function change(exports) {
    //为形参添加属性,是会同步到外部的module.exports对象的
    exports.name = "lisi"
    //在这里修改了exports的引用,并不会影响到module.exports
    exports = {
        age:10
    }
    console.log(exports) //{ age:10}
}
change(exports)
console.log(module.exports) //{exports: {name: "lisi"}}

5、exports和module.exports区别总结:

1.exports只是module.exports的引用。

2.exports的生存周期是当前模块的执行时间,而module.exports生存周期则是当前程序的执行时间

3.require()返回的是 module.exports 而不是 exports

4.module.exports 初始值为一个空对象 {}

5.通过上面代码可以很清楚知道,开始实际上module.exports和exports是指向同一个对象,而this开始又是指向module.exports,所以开始都是空对象。之后开始对module.exports赋值,这里要注意了,我们使用的module,实际上是传进来的参数,是外面定义那个module对象的地址,现在我们对module.exports赋值,如此一来,module里面这个exports的地址指向已经变了,指向了另一块内存,而由于是值传递,this和exports保存的仍然是之前的内存地址,所以他们仍然为{}

你可能感兴趣的:(node)