之前始终以传统后端的思维来写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);});

炒鸡辣鸡原创文章,转载请注明起源