包
在模块的基础上进一步组织JavaScript代码
用途: 可以让开发者通过npm直接下载,与cocoapods作用相同,与bower的用途相似
存放网站
我们做的包,需要先在npm网站上,上传一下,配置东西:package.json,然后npm install -- npm -- git这个过程才能完成,否则npm install失败
与iOS的包上传cocoapods一样,先在github中创建,然后clone下载,然后新建podspec文件,然后上传github,然后pod truck将podspec文件推送到cocoapods,就行
"道理都一样:1.得有个代码存放地 2.自己的代码包得有个spec描述文件 3.这个描述文件得在npm、cocoapods中存在"
参考链接:https://www.jianshu.com/p/f146fa5358d5?mType=Group
bower
bower与npm导入包的功能在一定程度上相似
但是侧重点不同:
简单的说,npm是进行后端开发中,使用的模块安装工具,
而bower,是前端的模块安装工具。
比如,在安装express,socket.io时,当然使用的是npm,那么比如bootstrap,jquery等前端框架,需要使用bower
bower是国外的,直接install,是去国外服务器下载(速度太慢),淘宝镜像的作用,就是复制了一份,放在了自己的服务器上,我们直接访问淘宝的镜像地址,就可以install
bower可以帮我们自动下载第三方的依赖库(第三方中有个json文件,里面记录了第三方的一些基本信息: 名字 版本 网址 依赖库等等)
依赖库下载以后,这个第三方不删除,这个依赖库是不能通过命令行删除的,提示,有第三方正在依赖它
参考链接:https://yq.aliyun.com/ziliao/40449
包的组成
- 包结构
- 包描述文件package.json
配置文件为啥用json格式?
方便解析读取,格式简单清晰
npm install -g fast-init
fast-init 是一个基于node的命令行工具,可以快速生成一个包的文件标准结构
作用: 集成快捷键,可以一键生成指定的文件
类似代码块,这个可以叫文件块
命令行应用名字 -h
可以查看该应用工具的所有指令,还有解释
package.json
包的描述文件,一定程度上相当于iOS项目第三方库中的podspec文件
package.json文件内部就是一个JSON对象,该对象的每一个成员就是当前项目的一项设置,
比如name就是项目名称,version就是项目的版本号
在模块的加载机制中,有一个main属性是非常重要的,它很大意义上决定了包要导出的模块位置
参考文献 package.json全字段解析 http://blog.csdn.net/woxueliuyun/article/details/39294375
模块化
一个js文件在node里面我们就理解为一个模块
在一个模块内变量、函数、对象都属于这个模块,对外是封闭的。
module.exports用来曝露属性和方法的,因为模块有封装性,需要打破封装性曝露方法和属性来
require()方法来实现模块化(具体会在下面Global模块详述)
模块三兄弟:require、module、exports
模块化:
seajs
requirejs
这两个实现模块化的第三方,到了nodejs中,都已经原生实现了,api也基本相同,还是require()
REPL(Read-eval-print-loop) 交互式运行环境
Node.js给我们提供一个交互式运行环境——REPL,在这个环境中我们可以做一些简单的应用程序的测试或调试。进入命令行窗口,输入”node”命令并按下回车键,即可进入REPL运行环境。
方便测试
JavaScript代码的运行环境,repl和chrome的控制台很像
- 通过在控制台中输入
node
敲回车就可以计入 REPL 运行环境 - 通过在REPL运行环境中 连续按两次
Ctrl+C
或者输入.exit就可以退出 REPL 运行环境
基本操作:
- 变量、函数、对象
- 直接运行函数
- 使用下划线,表示上一个命令的返回结果
全局对象global
global表示Node所在的全局环境,类似于浏览器的window对象
在html中,一个网页,一个ifream一个window
nodejs中,一个项目全局,也就一个global
在前者中
var a = 123 / a =123 都是加到window中的
在nodejs中
var定义的是当前js文件的变量
a=123/global.a=123都是加给global的
我们可以在REPL环境中直接查看global对象
总结:
global就表示Node中的全局命名空间,任何全局变量、函数或对象都是global的一个属性
在一个模块中定义的变量、函数或方法只在该模块中可用,但可以通过exports对象将其传递到模块外部
global常见的一些属性与函数
__dirname和__filename
exports和module
process
Class:Buffer
setInterval()和clearInterval()
setTimeout()和clearTimeout()
console
require()
__dirname 和 __filename
__dirnamee 用来找到当前文件夹的路径
__filename 用来去到当前文件的路径
不知道代码要才哪使用的时候,用于灵活的写代码取路径的时候。
它们属于模块作用域,可以直接使用
它们两个用来获取路径的,一般用于操作文件路径的时候,才会用到,一般在读取文件的时候,最好使用绝对路径的方式,通过这俩家伙拼接
module(每个模块,可用看做就是每个js文件)
Node内部提供一个Module构造函数,所有模块都是Module的实例
每个模块内部,都有一个module对象,代表当前模块。
module.id 带有绝对路径的模块文件名
module.filename 模块的文件名,带有绝对路径
module.loaded 表示模块是否已经完成加载
module.parent 返回一个对象,表示调用该模块的模块。
module.children 返回一个数组,表示该模块要用到的其他模块。
module.exports 模块对外输出的值
Module的exports属性
module.exports属性表示当前模块对外输出的接口,其它文件加载该模块,实际上就是读取module.exports属性
点儿导出单个函数、对象或者值的时候非常有用,本质上就是少了一个.(点)
exports
为了方便,Node又为每个模块提供一个exports变量,指向module.exports
相当于在每个模块头部,有这样一行命令:
var exports = module.exports;
结果就是:
在对外输出模块接口时,可以向exports对象添加方法
注意:不能直接给exports或者module.exports直接赋值,因为这样等于切断了exports和module.exports的联系,export就无效了,用属性的形式去赋值的时候二者都有效
module.exports=123;已经使用过一次了,exports就不生效了
module.exports.a=12;这样使用,exports是还可以使用的
process
process 是一个全局可用对象,用来和我们现在启动中的node进行交互的
process.version取版本号
在控制台做标准输出
process.stdout.write(`123123`);
process.pid:当前进程的进程号。
process.version:Node的版本,比如v0.10.18。
process.platform:当前系统平台,比如Linux。
process.env:指向当前shell的环境变量,比如process.env.HOME。
process.stdout:指向标准输出。
process.stdin:指向标准输入。
process.stderr:指向标准错误。
nodejs中的console
断言 是用来测试用的
断言就是假定一个条件,如果条件成立则不输出任何内容,如果条件不成立则报错还要输出想要输出的内容。
console.assert(条件,条件不成立输出的内容);
var foo=3;
console.assert(foo==3,"失败");
time() timeEnd()成对出现,计算在两个方法中间的代码的运行时间,传入的参数要一致
console.time('test');
console.timeEnd('test');
require()
在Node.js中,require命令用于加载模块文件
基本功能:
读取并执行一个JavaScript文件
然后返回该模块的exports对象
如果没有发现指定模块,会报错
require的实现原理
把代码从文件中读出来,用匿名函数的方式头尾包装,返回modules.exports对象,曝露出想要曝露出来的属性、方法、对象。
加载规则:
1. 参数字符串以 “/”开头:表示从系统根目录开始寻找该模块文件
2. 参数字符串以“./”开头:表示从当前目录出发
3. 参数字符串以“../”开头:表示从上一级目录出发
4. 参数字符串不以以上三种开头,说明要加载的不是一个文件,而是一个包模块。此时则先在核心模块(nodejs原生提供)当中找,然后再寻找NPM模块(即第三方模块包,或自己写的模块包)。在寻找NPM模块包时,会从当前目录出发,向上搜索各级当中的node_modules文件夹当中的文件,但若有两个同名文件,则遵循就近原则。
1、加载核心模块(nodejs原生提供)的时候,不需要传入路径,因为Node.js已经将核心模块的文件代码编译到了二进制的可执行文件中了,在加载的过程中,原生的核心模块的优先级是是最高的
2、之前在使用require的方式来加载一个文件时,如果该文件在当前目录当中,则参数字符串当中必须以./开头,不能直接写文件名。若在参数字符串当中直接写文件名,则代表载入的是一个模块包,模块包必须放在一个特定名字的文件夹当中,即node_modules。
3、在加载一个自己编写的模块的时候,最好使用__dirname 和 你要加载的模块的文件名拼接
4、若直接写包名
先在包内的node_modules目录下查找,再去父级目录下的node_modules目录下查找,
依次向上查找,直到根目录。
5、require 优先从缓存加载
common.js规范----->加载后,会将对象缓存下来,再次需要加载时,是去缓存中取module.exports
使用require来加载文件的时候,参数字符串可以省略后缀名
.js、.json、.node
.js会当做JavaScript脚本文件解析
.json会以JSON格式解析:Node.js通过fs读文件的形式读取出来的,然后通过JSON.parse()转换成一个对象
.node会以编译后的二进制文件解析(后缀为node的文件是c/c++写的一些扩展模块)
若参数字符串为一个目录(文件夹)的路径,则自动先查找该文件夹下的package.json文件,然后再再加载该文件当中main字段所指定的入口文件。(若package.json文件当中没有main字段,或者根本没有package.json文件,则再默认查找该文件夹下的index.js文件作为模块来载入。)
Node.js会通过同步阻塞的方式看这个路径是否存在
依次尝试,直到找到为止,
如果找不到,报错
参考文献 http://www.infoq.com/cn/articles/nodejs-module-mechanism/