之前始终以传统后端的思维来写nodejs的代码,发现运行后果与我的同步思维形式不太一样,所以须要全面将nodejs学习一下。此学习笔记适宜后端同学学习nodejs的时候观看,前端大佬能够多多斧正。
环境变量
console.log(setTimeout);console.log(setInterval);console.log(setImmediate);console.log(__filename); // 以后文件的全名console.log(__dirname); //console.log(process); // 过程信息,全局变量
process就是以后运行环境变量的集合体。例如process.argv就是获取用户输出的参数
数学库
与Java一样,叫Math
Math.random(); // 返回0~1的浮点数
模块标准之exports和module.exports的关系
须要解决的问题:
脚本变多时,须要手动治理加载程序
不同脚本之间逻辑调用,须要通过全局变量的形式去交换,例如:JQUERY。将输入放到全局变量中,而后由其余局部进行应用
没有html怎么办?
nodejs中应用CommonJs模块标准,加载另一个js,用require函数来获取即可。
// demo.jsconsole.log("-----------");let lib = require('./lib');console.log('---------',lib);// lib.jsconsole.log('==========');exports.hello = '++++++++++';exports.word = '///////////////';exports.add = function () { console.log('1111111111111')};
能够看见,模块中定义模块输入的形式:默认会注入一个叫export的变量,在该变量上挂参数就相当于给以后被require对象外面附一个值。还能够挂函数,对象等,实践上就是在输入对象中加对象。所以在exports中咱们能够挂各种类型的构造
同时,对于exports来说,里面能够扭转模块外面的内容,是同一个援用。
// demo.jsconsole.log("-----------");let lib = require('./lib');lib.addd = '*******************';console.log('---------',lib);// lib.jsconsole.log('==========');exports.hello = '++++++++++';exports.word = '///////////////';exports.add = function () { console.log('1111111111111')};setTimeout(()=>{ console.log(exports)},2000);
运行后果如下,能够看见批改了里面被require的对象,外面的exports对象也被批改了
特定地,如果心愿被require进去的不是一个对象,而是一个办法,或者变量啥的,能够应用module.exports,然而会笼罩掉之前怼exports变量的批改。
// demo.jsconsole.log("-----------");let lib = require('./lib');console.log('---------',lib);// lib.jsconsole.log('==========');exports.hello = '++++++++++';exports.word = '///////////////';exports.add = function () { console.log('1111111111111')};module.exports = function dsa() { return '123'};
最终打印的后果为
能够看到后果中exports变量的值并没有被输入进去,失去这样的后果有两种可能性,第一是module.exports将exports对象给笼罩掉了,第二种是module.exports和exports在文件被require的时候其实是两个不同的货色,指向两个不同的内存,当模块被require的时候,如果module.exports没有被指定,那么就require进去的是exports对象,如果module.exports被指定了,那么就应用module,exports。我比拟偏向于前面这种解释,上面来证实我的观点。
// demo.jsconsole.log("-----------");let lib = require('./lib');lib.addd = '*******************';console.log('---------',lib);// lib.jsconsole.log('==========');exports.hello = '++++++++++';exports.word = '///////////////';exports.add = function () { console.log('1111111111111')};setTimeout(()=>{ console.log(exports)},2000);module.exports = function dsa() { return '123'};setTimeout(()=>{ console.log(module.exports)},2000);
运行后果为:
能够看到,在demo.js中给援用的lib新增了addd属性,最终是作用到了module.exports上,同时,exports打印的后果与module.exports并不一样,阐明,module.exports和exports不是一个对象,只是在一个模块被援用时,module.exports的优先级要高于exports。
获取控制台输出(规范输入输出)
process.stdin.on('data', (e) => { const x = e.toString().trim(); console.log(x);} );
包管理工具
每个语言都有包管理工具,不过nodejs有个坑,就是npm有时候版本和nodejs不匹配,这个时候就会抛出一些莫名其妙的谬误。碰到这种状况,就只能去npm官网解决问题局部寻找后果了。
npm init
要应用npm,须要自身就是一个npm目录,所以须要应用 npm init 来申明为npm 包
package.json
dependencies:放在外面,npm install时会被主动下载,申明以后npm包所有的依赖
装置卸载
npm install xxxnpm uninstall xxx
国内镜像
npm是国外的镜像,能够应用淘宝的npm镜像,能够去NPM镜像查看相干的办法
值得注意的是,用cnpm的时候要加上--save指令,否则dependencies中不会加进去
npm search xxx
很多同学不晓得本人适宜用什么包,比方我想连贯redis,该应用什么包呢?就能够应用 npm search redis来寻找了,雷同的,docker search redis/composer search redis 等等都是这么玩的。
nodejs架构
基于V8运行环境
事件驱动:非阻塞式的IO模型
内置模块
nodejs官方网站文档页面 nodejs官方网站文档中文页面
底层能力是怎么实现的
以os为例,在源码的lib文件中:internalBinding('os') 在 src/node_os.cc中再调用v8的能力
Event模块实现观察者模式,进而使得两个对象进行传输
EventEmitter,process继承与它,所以能够往上抛事件,也就是典型的观察者模式。底层的能力封装起来放到一个模块中,里面的模块拿到这个代码,通过事件的监听器,就能比拟不便的,晓得子模块外面产生的变动。
观察者模式,能够用来解决两个对象的交换问题。
其实这个办法也能够实现两个函数的先后执行,从而将代码过程化,我看到这个还是比拟兴奋的,这样我就能够解决原本具备先后执行程序的代码,因为nodejs的异步个性导致无奈实现的,能够利用这个模式实现
const EventEmitter = require('events').EventEmitter;class X extends EventEmitter{ constructor(){ super(); setInterval(()=>{ this.emit('newlesson',{ price:Math.random()*100 }); },3000) }}const x = new X();x.addListener('newlesson',(res)=>{ console.log('buy!',res);});
炒鸡辣鸡原创文章,转载请注明起源