2、环境和调试
1、commonJS规范、global全局对象、process(当前执行的进程,挂载于global下面)
2.1、commonJS
1、commonJS是Node.js模块规范,下面讲个例子
(1)先写个console.js文件里面致谢一句话
console.log('this is Node.js')
(2)然后在命令行进行调试,输入命令:node --inspect-brk console.js
(3)打开chrome浏览器,输入网址:chrome://inspect 进入
(4)下面有个Target,我们点击inspect进入
(5)在里面会有这样一段代码:
(function(exports, require, module, __filename, __dirname) {
console.log('this is Node.js')
}
);
那这个就是我们刚才在console.js文件中的写的代码的完整版(也就是实际执行的代码),首先exports代表模块的输出,require表示要依赖别的模块需要的function,module表示模块本身,_filename代表文件路径,_dirname代表文件夹路径。
2、每个文件是一个模块,有自己的作用域
3、在模块内部module变量代表模块本身
4、module.exports属性代表模块对外接口
5、现在我们就可以自己去定义模块了,就记住三件事情:首先定义一个模块就要创建一个文件,然后使用module.exports来放一些我们想输出的一些东西。
6、在实例之前我们先理一下require规则
(1)/表示绝对路径,./表示相对于当前文件的
(2)支持js,json,node拓展名,不写依次尝试。
(3)不写路径则认为是build-in模块或者各级node_modules内额第三方模块
7、定义一个模块,对外提供的输出是textVar和testFn
console.log('This is a module')//最好写在一个function中
const testVar=100;
function test(){
console.log(testVar)
}
module.exports.testVar=testVar; //前面的testVar是提供个外面能看到的,后面的testVar是本模块里面真实的东西
molule.exports.testFn=test;
然后我们去引入这个模块
const mod=require('./console.js')
console.log(mod.testVar)
mod.testFn();
我们理所应当的以为结果是输出 100 100,但是结果是 This is a module 100 100。这种现象就是加载一个模块这个模块每句话都会被执行。
8、require特性
(1)module被加载时候执行,加载后缓存。
这句话前半句很好理解,根据我们上面的例子可以理解,那么加载后缓存是什么意思,就是该模块被第一次引用时会执行,并且缓存到内存中,第二次被引用就不会再执行这个模块,而是直接去内存中拿这个模块,不会重复加载。那给我们的提示就是像这种将console.log('This is a module')最好写在一个function中,这样虽然执行但是不会显示出来。
(2)一旦出现某个模块被循环加载,就只输出已经执行的部分,还未执行的部分不会输出,那这样的特性给我们的提示就是避免它,不要写像下面这样的某个模块被循环加载的代码,5句话都可能把人搞晕
这句话是什么意思,我们写个例子,在modA.js中写这样的代码
module.exports.test='A'; //1 5
const modB=require('./modB.js')//2
console.log(ModA':modB.test)
module.exports.test='AA'
然后在modB.js中写这样的代码
module.exports.test='B'; //3
const modA=require('./modA.js') //4
console.log(ModB':modA.test) //6 输出A
module.exports.test='BB' //7 输出BB
我们在主程序中去require两者
const modA=require('./modA.js')
const modB=require ('./modB.js') //这句话没有结果也是A BB,因为上一句中已经将modB.js执行一遍了,这句话是去缓存中拿的结果
执行主程序的结果是 ‘A’ 'BB',原因可以看看上面我在代码后面注释的程序流程顺序。
2.2 引用系统内置模块和第三方模块
1、引用系统内置模块(比如说引用fs模块),编写文件console.js
const fs=require('fs')
const result=fs.readFile('./console.js',(err,data)=>{
if(err){
console.log(err);
}else{
console.log(data) //console.log(data.toString())就是我们写的源码,不是二进制字符了
}
});
console.log(result)//由于异步的存在,主程序是立即返回的,立即返回result是没有值的,所以结果第一行出现了undefined
出人意料的打印出undefined和Buffer连接的一堆二进制字符。
2、引用第三方组件(比如说引用chalk)
首先要下载第三方包,npm install chalk --save,然后写一段简单的代码
const chalk=require('chalk')
console.log(chalk.red('This is a cha'))
能够输出红色字体,还有下划线阴影,可以上官网查API
3、特别要注意我们的下载第三方组件都会放在一个node_modules中,这里是将所有包的依赖磨平放在里面,什么意思,就是A包依赖了 B,C,D包,E包依赖了C,D,G包,其中C,D包并不会重复下载和依赖,而是和被依赖的A,E同时都放在node_modules里,即A,B,C,D,E,G。
2.3 exports与module.exports的区别
在本篇文章的最前面我们提到过这样一段代码
(function(exports, require, module, __filename, __dirname) {
console.log('this is Node.js')
}
);
在function的参数列表中有exports,在module中也有个exports,那么exports和module.exports有什么区别?
exports默认的情况是module.exports的快捷方式,但是exports改变了指向,那么exports和普通的变量就没啥区别了,举例:
exports.text=100;
//这种情况exports就相当于module.exports,外面的文件是可以访问到text的
exports={
text:100
}
//这种情况exports就是普通的对象,外面是访问不到的
2.4 global全局对象
1、在node中我们把希望能全局访问的属性,变量或者方法挂在global上,那么global自己也有方法,像CommonJS,Buffer,process,console,timer。这些都能全局直接用。
global.text=2200
这种就将text暴露在全局中,外面的文件都能用,也不用引入text定义所在文件
2.5 process
2.5.1参数相关
1、参数相关,{argv,argv0.execArgv,exerPath}Node.js在启动的时候有启动相关的参数,经常通过启动脚本来传递参数到程序,那么怎么读取呢?
const {argv,argv0,execArgv,execPath}=process;
argv.forEach(element => {
console.log(element)
});
对于包含参数的argv来讲,是个数组,循环打印出来看看结果,下图所示有两项,第一项是node的命令所在位置,也就是node的安装路径,第二个当前执行文件的路径。
当然这个命令还能传递一些额外的参数,方便我们在启动程序的时候额外输入一些参数
2、argv0就是argv数组中的第一个元素,也就是Node命令的路径
3、execArgv是什么,比如我们现在的代码是依旧是下面这样
const {argv,argv0,execArgv,execPath}=process;
argv.forEach(element => {
console.log(element)
});
console.log(argv0)
console.log(execArgv)
现在我们的命令变了,在最后的结果会显示一系列在文件名前的参数,并以数组的形式显示
4,exerPath实际也是argv的第一个元素
2.5.2环境相关
1、env表示了环境配置的参数,console.log(process.env)可以看到打印出来很多环境参数
2、cwd表示当前命令执行的路径
3、前面在将global的时候,setImmediate也是全局的,它和setTimeout和process。nextTick的快慢为:nextTick>setTimeout>setImmediate,大于号的意思是快于的意思。
2.6调试
1、inspector,node自己的调试方式:node --inspect-brk js文件名,打开浏览器进入 chrome://inspect