Node.js-模块和包
2017-01-09 11:24
351 查看
这篇文章是Node.js第二篇,之所以要来写这些,是因为想把看过的书都记录下来,第一篇文章在这里:
从头开始讲Node.js——异步与事件驱动
看的书名叫做《Node.js开发指南》
从元旦之后就给自己立了一个flag,每个星期看完以本书,最近比较闲,主要是花在这部书上的精力也还蛮多的吧,现在已经翻了1/4了,嗯,一个星期已经过去一半了,不知道能不能看完呀。闲话少说,来说重点吧。
这一篇主要是讲模块和包
主要分四节:
什么是模块
如何创建并加载模块
如何创建包
如何使用包管理器
简而言之,也就是说一个文件就是一个模块。
node.js遵循commonJS的规范,使用require加载和export导出。
什么是commonJS规范,我之前也有讨论过:Javascript模块化编程——使用AMD,CommonJS,ES Harmony
另外模块的导出,我也转过一篇很好的文章,因为我们有些时候会导出整个node.js文件,有些时候只需要一个对象。Node.js中exports和module.exports有什么不同?
这里跟着书上的代码再过一遍吧。
module.js
getModule.js
这个确实跟创建一个对象,再声明一个对象没什么区别啊。但是在node.js这种写后台语言的环境下这么做或许好一些吧。
上面这段代码感觉跟下面这段代码完全没区别,其实就是换了一种CommonJS规范的写法而已,我觉得。
这种接口封装方式比许多语言要简洁得多,同时也不失优雅,未引入违反语义的特性,符合传统的编程逻辑。在这个基础上,我们可以构建大型的应用程序,npm 提供的上万个模块都是通过这种简单的方式搭建起来的。
但是在后续用到npm里面肯定非常好吧。
但是基于对象的创建就不一样了。
**区别:通过对象创建的myModule2相当于创建了一个新的module实例,因此myModule2的修改不会影响myModule。
但是通过require加载的,每次只加载一个,无论声明多少次require,他们指向的都是同一个对象。**
这里也就解释了我前面的疑惑。
那么在另一个模块中引用该模块就需要 var newHello = new Hello.Hello;这样写来看上去非常不好看
因此把上面的exports.Hello = Hello;改成 module.exports = Hello; 就完美了
注意,模块接口的唯一变化是使用 module.exports = Hello 代替了 exports.Hello= Hello 。在外部引用该模块时,其接口对象就是要输出的 Hello 对象本身,而不是原先的 exports。
事实上,exports 本身仅仅是一个普通的空对象,即 {} ,它专门用来声明接口,本质上是通过它为模块闭包的内部建立了一个有限的访问接口。因为它没有任何特殊的地方,所以可以用其他东西来代替,譬如我们上面例子中的 Hello 对象。
警告:
不可以通过对 exports 直接赋值代替对 module.exports 赋值。 exports 实际上只是一个和 module.exports 指向同一个对象的变量, 它本身会在模块执行结束后释放,但 module 不会,因此只能通过指定 module.exports 来改变访问接口。
模块与文件是一一对应的。文件不仅可以是 JavaScript 代码或二进制代码,还可以是一个文件夹。最简单的包,就是一个作为文件夹的模块。下面我们来看一个例子,建立一个叫做 somepackage 的文件夹,在其中创建 index.js ,内容如下:
//somepackage/index.js
然后在 somepackage 之外建立 getpackage.js ,内容如下:
//getpackage.js
我们使用这种方法可以把文件夹封装为一个模块,即所谓的包。包通常是一些模块的集合,在模块的基础上提供了更高层的抽象,相当于提供了一些固定接口的函数库。通过定制package.json,我们可以创建更复杂、更完善、更符合规范的包用于发布。
通过使用 npm init 可以根据交互式问答产生一个符合标准的 package.json,例如创建一个名为 byvoidmodule 的目录,然后在这个目录中运行npm init :
这样就在 byvoidmodule 目录中生成一个符合 npm 规范的 package.json 文件。创建一个 index.js 作为包的接口,一个简单的包就制作完成了。 在发布前,我们还需要获得一个账号用于今后维护自己的包,使用 npm adduser 根据提示输入用户名、密码、箱,等待账号创建完成。完成后可以使用 npm whoami 测验是
否已经取得了账号。
接下来,在 package.json 所在目录下运行 npm publish ,稍等片刻就可以完成发布了。打开浏览器,访问 http://search.npmjs.org/ 就可以找到自己刚刚发布的包了。现在我们可以在世界的任意一台计算机上使用 npm install byvoidmodule 命令来安装它。
如果你的包将来有更新,只需要在 package.json 文件中修改 version 字段,然后重新使用 npm publish 命令就行了。如果你对已发布的包不满意(比如我们发布的这个毫无意义的包),可以使用 npm unpublish 命令来取消发布。
从头开始讲Node.js——异步与事件驱动
看的书名叫做《Node.js开发指南》
从元旦之后就给自己立了一个flag,每个星期看完以本书,最近比较闲,主要是花在这部书上的精力也还蛮多的吧,现在已经翻了1/4了,嗯,一个星期已经过去一半了,不知道能不能看完呀。闲话少说,来说重点吧。
这一篇主要是讲模块和包
主要分四节:
什么是模块
如何创建并加载模块
如何创建包
如何使用包管理器
什么是模块
模块是 Node.js 应用程序的基本组成部分,文件和模块是一一对应的。换言之,一个 Node.js 文件就是一个模块,这个文件可能是 JavaScript 代码、JSON 或者编译过的 C/C++ 扩展。简而言之,也就是说一个文件就是一个模块。
如何创建并加载模块
前面说了一个node.js文件就是一个模块,那么如何创建它,或者说加载这个模块呢?node.js遵循commonJS的规范,使用require加载和export导出。
什么是commonJS规范,我之前也有讨论过:Javascript模块化编程——使用AMD,CommonJS,ES Harmony
另外模块的导出,我也转过一篇很好的文章,因为我们有些时候会导出整个node.js文件,有些时候只需要一个对象。Node.js中exports和module.exports有什么不同?
这里跟着书上的代码再过一遍吧。
module.js
var name; exports.setName = function(thyName) { name = thyName; } exports.sayHello = function() { console.log('Hello' + name); }
getModule.js
var myModule = require('./module.js'); myModule.setName('daisy_Hawen'); myModule.sayHello()
这个确实跟创建一个对象,再声明一个对象没什么区别啊。但是在node.js这种写后台语言的环境下这么做或许好一些吧。
上面这段代码感觉跟下面这段代码完全没区别,其实就是换了一种CommonJS规范的写法而已,我觉得。
var module = (function() { var name, setName = function(thyName) { name = thyName }, sayHello = function() { console.log('Hello' + name); } return { setName: function(thyName) { setName(thyName) }, sayHello: function() { sayHello() } } }) var myModule = new module() myModule.setName('Hawen'); myModule.sayHello();
这种接口封装方式比许多语言要简洁得多,同时也不失优雅,未引入违反语义的特性,符合传统的编程逻辑。在这个基础上,我们可以构建大型的应用程序,npm 提供的上万个模块都是通过这种简单的方式搭建起来的。
但是在后续用到npm里面肯定非常好吧。
单次加载
上面这个例子有点类似于创建一个对象,但实际上和对象又有本质的区别,因为 require 不会重复加载模块,也就是说无论调用多少次 require,获得的模块都是同一个。我们在 getmodule.js 的基础上稍作修改:var myModule1 = require('./module.js'); myModule1.setName('daisy_Hawen'); var myModule2 = require('./module.js'); myModule2.setName('ahahah'); myModule2.sayHello() //helloahahah myModule1.sayHello();//helloahahah
但是基于对象的创建就不一样了。
var module = (function() { var name, setName = function(thyName) { name = thyName }, sayHello = function() { console.log('Hello' + name); } return { setName: function(thyName) { setName(thyName) }, sayHello: function() { sayHello() } } }) var myModule = new module() myModule.setName('Hawen'); var myModule2 = new module() myModule2.setName('ahahah'); myModule.sayHello();//helloaHawen myModule2.sayHello();//helloahahah
**区别:通过对象创建的myModule2相当于创建了一个新的module实例,因此myModule2的修改不会影响myModule。
但是通过require加载的,每次只加载一个,无论声明多少次require,他们指向的都是同一个对象。**
这里也就解释了我前面的疑惑。
覆盖exports
假如我们是将一个对象封装在模块中的话,例如:function Hello() { var name; this.setName = function(thyName) { name = thyName; }; this.sayHello = function() { console.log("Hello" + name); } } exports.Hello = Hello;
那么在另一个模块中引用该模块就需要 var newHello = new Hello.Hello;这样写来看上去非常不好看
var Hello = require('./sinleobject.js') var newHello = new Hello.Hello; newHello.setName('hawen'); newHello.sayHello();
因此把上面的exports.Hello = Hello;改成 module.exports = Hello; 就完美了
var Hello = require('./sinleobject.js') var newHello = new Hello; newHello.setName('hawen'); newHello.sayHello();
注意,模块接口的唯一变化是使用 module.exports = Hello 代替了 exports.Hello= Hello 。在外部引用该模块时,其接口对象就是要输出的 Hello 对象本身,而不是原先的 exports。
事实上,exports 本身仅仅是一个普通的空对象,即 {} ,它专门用来声明接口,本质上是通过它为模块闭包的内部建立了一个有限的访问接口。因为它没有任何特殊的地方,所以可以用其他东西来代替,譬如我们上面例子中的 Hello 对象。
警告:
不可以通过对 exports 直接赋值代替对 module.exports 赋值。 exports 实际上只是一个和 module.exports 指向同一个对象的变量, 它本身会在模块执行结束后释放,但 module 不会,因此只能通过指定 module.exports 来改变访问接口。
创建包
‘这一节我觉得真的没什么好说的,就直接copy书上的话过来了’模块与文件是一一对应的。文件不仅可以是 JavaScript 代码或二进制代码,还可以是一个文件夹。最简单的包,就是一个作为文件夹的模块。下面我们来看一个例子,建立一个叫做 somepackage 的文件夹,在其中创建 index.js ,内容如下:
//somepackage/index.js
exports.hello = function() { console.log('hello'); }
然后在 somepackage 之外建立 getpackage.js ,内容如下:
//getpackage.js
var somePackage = require('./somepackage'); somePackage.hello();
我们使用这种方法可以把文件夹封装为一个模块,即所谓的包。包通常是一些模块的集合,在模块的基础上提供了更高层的抽象,相当于提供了一些固定接口的函数库。通过定制package.json,我们可以创建更复杂、更完善、更符合规范的包用于发布。
包的发布
npm 可以非常方便地发布一个包,比 pip 、gem 、pear 要简单得多。在发布之前,首先需要让我们的包符合 npm 的规范,npm 有一套以 CommonJS 为基础包规范,但与 CommonJS并不完全一致,其主要差别在于必填字段的不同。通过使用 npm init 可以根据交互式问答产生一个符合标准的 package.json,例如创建一个名为 byvoidmodule 的目录,然后在这个目录中运行npm init :
这样就在 byvoidmodule 目录中生成一个符合 npm 规范的 package.json 文件。创建一个 index.js 作为包的接口,一个简单的包就制作完成了。 在发布前,我们还需要获得一个账号用于今后维护自己的包,使用 npm adduser 根据提示输入用户名、密码、箱,等待账号创建完成。完成后可以使用 npm whoami 测验是
否已经取得了账号。
接下来,在 package.json 所在目录下运行 npm publish ,稍等片刻就可以完成发布了。打开浏览器,访问 http://search.npmjs.org/ 就可以找到自己刚刚发布的包了。现在我们可以在世界的任意一台计算机上使用 npm install byvoidmodule 命令来安装它。
如果你的包将来有更新,只需要在 package.json 文件中修改 version 字段,然后重新使用 npm publish 命令就行了。如果你对已发布的包不满意(比如我们发布的这个毫无意义的包),可以使用 npm unpublish 命令来取消发布。
Node.js的调试
相关文章推荐
- node.js文件的复制,创建文件夹等相关操作
- rac one node 安装和切换(11gR2)
- Swagger UI教程 API 文档神器 搭配Node使用
- [leetcode]382. Linked List Random Node
- 微信小程序完整精品demo:移动小商城:基于node,包含前后台
- 搭建以太坊开发环境的曲折之路
- node 安装
- 几个命令行命令的总结(node, babel-cli, babel-node)
- 19. Remove Nth Node From End of List
- nodejs 的 express-session 模块之 cookie.secure 选项使用注意事项
- 8.Nodejs入门-----web Socket和Socket.IO框架
- 7.Nodejs入门-----Mongoose
- 6.Nodejs入门-----写服务
- 5.Nodejs入门-----Cookie和Session
- 2.Nodejs入门-----模块
- nodejs stream 手册
- 1.Nodejs入门-----简介
- Node调试工具JSHint
- namenode无法启动
- DataNode无法启动