[读书笔记] 了不起的Node.js

本文深入探讨Node.js的关键特性,包括JavaScript概览、继承、阻塞与非阻塞IO、模块系统、错误处理和非阻塞IO原理,通过实例展示如何在Node.js环境中高效编程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

CHAPTER2 JavaScript概览

继承


使用
 Ferret.prototype = new Animal(); 

来继承

重写:

Ferret.prototype.eat = function(food){
  Animal.prototype.eat.call(this, food);
  //ferret特有逻辑写在这里
}


这个方法的不足之处就是,如果Animal的初始化函数里面有什么操作就麻烦了,解决方案是

A: 在构造器中添加判断条件

function Animal(a){
  if(a === false) return;
  //初始化
}
B: 写一个新的空构造函数

function Animal(){
  //consstructor stuff
}

function f(){};
f.prototype = Animal.prototype;
Ferret.prototype=new f;

防止迭代属性的时候迭代到父类属性的方法

for(var i in a){
  if(a.hasOwnProperty(i)){}
}

V8

在V8里面获取所有自有键的快速方法

var a= {a:'b',c:'d'};
Object.keys(a); // ['a', 'c']

数组

检测某对象是否是数组

Array.isArray(new Array) //true
Array.isArray([]) //true
Array.isArray(null) //false
Array.isArray(arguments) //false

V8

遍历数组

// 会打印出 1, 2, 3
[1,2,3].forEach(function(v){
  console.log(v);
});

过滤数组使用 filter

改变数组用map

[5, 10, 15].map(function(v){
  return v * 2;
}); // 会返回 [10,20,30]

js的trim

' hello '.trim(); // 'hello'

JSON编码解码:JSON.stringify 和 JSON.parse

BIND

.bind 改变this引用

function a(){
  this.hello='world';
};

var b = a.bind({hello: 'world'});
b();

__PROTO__继承,使得继承简化了

function Animal(){}
function Ferret(){}
Ferret.prototype.__proto__=Animal.prototype;

__defineGetter__

Date.protptype.__defineGetter__('ago',function(){
.....
}

CHAPTER3 阻塞与非阻塞IO

变量是公共的

nodejs共享状态的并发,也就是说一个线程会影响到另一个线程的变量,就好像所有函数外的变量都是static的感觉一样,比如
var books=[
'aaa','bbb'];
function serveBooks(){
var html='.....';
books=[];
return html;
}
运行结果为:第一次将完整的图书列表返回,第二次则返回一个空的列表

非阻塞

node并发使用事件轮询,注册一个事件,随后不停的询问内核这些事件是否已经分发。(也就是说你定的时间不是绝对准确的,后面说道怎么个不准确法)。文件描述符是抽象的句柄。本质上来说,当node接受到从浏览器发来的http请求时,底层的tcp连接会分配一个文件描述符。随后,如果客户端向服务器发送数据,node就会受到该文件描述符上的通知,然后触发javascript的回调函数。

单线程

node是单线程的,也就是说事件轮询跟别的事情一样是在一个线程里面,之前提到有可能你定的时间是不准确的,现在演示一个不准确的例子

var start = Date.now();

setTimeout(function(){
console.log(Date.now() - start);
for(var i=0;i<1000000000;i++){}
},1000);

setTimeout(function()){
console.log(Date.now()-start);
},2000);
输出

1000
3738

原因就是事件轮询被js代码阻塞了。

为什么单线程+非阻塞=高并发

因为一般的语言会经常被阻塞在数据库操作,文件操作等动作上,所以才会消耗性能,造成并发量小,nodejs的方式是:“当你获取数据库响应时记得通知我”之后,node就可以继续处理其他事情了。单线程使用的堆栈看起来是同一个时间只能处理一个请求的操作,但是由于在很快的状态下,你看起来像是并发一样。
注:我个人的理解的为什么node比别的语言并发高,因为cpu本身的原理就是处理并发用的是时间片来模拟,我们都知道其实如果有3件事情,你让电脑一次只干一件事情,总时间是最快的,如果让电脑同时干,每件事情的时间会延长到超过3倍,也就是说node遵循计算机的本质,让计算机做最擅长的事情:一次只干一件事情,这样在一个时间段,比如1s内,看起来并发量就提高了

错误处理

书中使用 process.on('uncaughtException',funcion(){}); 的方式,但是我们知道其实最好是使用domain + forever的方式。

堆栈追踪

格外注意你并不知道(也无法知道)抛出的异常的回调函数是从哪个函数注册进去的。

CHAPTER4 Node中的JavaScript

global对象

浏览器中全局对象是window,setTimeout其实就是window.setTimeout  , document其实就是 window.ducument。 而在node 中是这样的:
  1. global:和window一样任何global对象上的属性都可以被全局访问到
  2. process:所有全局执行上下文中的内容都在process对象中。在浏览器中只有一个window对象,在node中也只有一个process对象。举例来说,在浏览器中窗口的名字是window.name,在node中进程的名字是 process.title

实用的全局对象

setImmediate相当于 process.nextTick。nextTick可以将函数的执行时间规划到下一个事件中
console.log(1);
process.nextTick(function(){
console.log(3);
})
console.log(2);

打印出来是 123

模块系统

传统的js模块是自己来定义全局变量,这样没有规范,容易污染。 Node把这个行为规范了起来: require, module, exports

暴露API

做一个module_a.js
exports.name='john';
exports.data='something';
var privateV = 5;
exports.getPrivate=function(){
return privateV;
};

测试一下:
在module_a.js边上建一个index.js 写上
var a =require('./module_a');
console.log(a.name);
console.log(a.data);
console.log(a.getPrivate());

输出
john
something
5
exports 其实就是对 module.exports 的引用。其在默认情况下是一个对象。甚至可以直接重写exports对象
person.js
module.exports=Person;
function Person(name){
   this.name=name;
}

Person.prototype.talk=function(){
console.log('my name is',this.name);
};

index.js
var Person = require('./person');
var john = new Person('john');
john.talk();









评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值