node要点总结

node开发要点

1、常用前端技术:
    html5
    css3
    jQuery
2、js高级话题:
    面向对象
    闭包
    作用域
    设计模式
3、其他后端技术:
    mongodb
    redis
    apache
    nignix
    mysql
4、node内置核心库:
    全局对象
    时事件
    流
    网络
    子程序
5、常用知名第三方库:
    async
    express
    koa
6、node高级话题:
    异步
    部署
    性能调优
    异常调试

node事件循环机制

* javaScript高级话题(面向对象、作用域、闭包、设计模式)

面向对象

1、常用js类定义的方法?

构造函数原型法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
		function Person () {
this.name = 'pinocchio';
}
Person.prototype.sayName = function () {
alert(this.name);
; }
var person = new Person ();
person.sayName();
//对象创建:
var Person = {
name: 'pinocchio',
sayName: function () {
alert(this.name);
}
};
var person = Object.create(Person);
person.sayName();

2、js类继承的方法?

原型链法(Person是Animal的子集,即子类):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
	function Animal () {
this.name = 'animal';
}
Animal.prototype.sayName = function () {
alter(this.name);
}
function Person () {}
Person.prototype = Animal.prototype; //人继承动物
Person.prototype = constructor = 'Person'; //更新构造函数为人
属性复制法(单纯复制,两者无继承关系):
function Animal () {
this.name = 'animal';
}
Animal.prototype.sayName = function () {
alter(this.name);
};
function Person () {}
//复制动物所有属性到人
for (prop in Animal.prototype) {
Person.prototype[prop] = Animal.prototype[prototype];
}
//更新构造函数为人
Person.prototype.constructor = 'Person';
构造器应用法:
function Animal () {
this.name = 'animal';
}
Animal.prototype.sayName = function () {
alter(this.name);
};
function Person () {
//apply,call,bind方法都行,有细微区别
Animal.call(this);
}

3、js类多重继承的方法怎么实现?

通过类继承里面的属性复制法来实现,可以继承所有父类的prototype属性

作用域

4、js里作用域是什么样?

函数作用域,

1
2
3
4
5
6
7
8
9
var globalVar = 'global var';

function test() {
alert(globalVar); // undefined, 因为globalVar在本函数内被重定义了,导致全局失效,这里使用函数内的变量值,可是此时还没定义
var globalVar = 'overrided var'; // globalVar在本函数内被重定义

alert(globalVar); // overrided var
}
alert(globalVar); // global var,使用全局变量

5、js中this指的是什么?

this指的是对象本身

6、apply,call,bind有什么区别?

apply 、 call 、bind 三者都是用来改变函数的this对象的指向的;
三者第一个参数都是this要指向的对象,也就是想指定的上下文;
三者都可以利用后续参数传参;
apply,call是直接执行函数调用,bind是绑定,执行需要再次调用.apply和call的区别是apply接受数组作为参数,而call是接受逗号分隔的无限多个参数列表
        
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function Person () {}
Person.prototype.sayName() {
alert(this.name);
}
//普通对象,不是Person实例
var obj = {
name: 'pinocchio'
};
//apply
Person.prototype.sayName.apply(obj, [param1, param2, param3]);
//call
Person.prototype.sayName.call(obj, param1, param2, param3);
//bind,先绑定,再执行
var sn = Person.prototype.sayName.bind(obj);
sn([param1, param2, param3]);
sn(param1, param2, param3);

7、caller,callee和arguments分别是什么?

1
2
3
4
5
6
7
8
9
10
11
12
caller,callee之间的关系就像是employer和employee之间的关系,就是调用与被调用的关系,二者返回的都是函数对象引用.arguments是函数的所有参数列表,它是一个类数组的变量.
function parent(param1, param2, param3) {
child(param1, param2, param3);
}

function child() {
console.log(arguments); // { '0': 'mqin1', '1': 'mqin2', '2': 'mqin3' }
console.log(arguments.callee); // [Function: child]
console.log(child.caller); // [Function: parent]
}

parent('mqin1', 'mqin2', 'mqin3');

闭包

8、什么是闭包?闭包有什么用处?

通俗的说,闭包就是作用域范围,因为js是函数作用域,所以函数就是闭包.全局函数的作用域范围就是全局,所以无须讨论.更多的应用其实是在内嵌函数,这就会涉及到内嵌作用域,或者叫作用域链。
这就会带来另外一个问题,什么时候引用结束?如果不结束,就会一直占用内存,引起内存泄漏.不用的时候就引用设为空。    

9、defineProperty, hasOwnProperty, propertyIsEnumerable都是做什么用的?

Object.defineProperty(obj, prop, descriptor)用来给对象定义属性,有value,writable,configurable,enumerable,set/get等.hasOwnProerty用于检查某一属性是不是存在于对象本身,继承来的

父亲的属性不算.propertyIsEnumerable用来检测某一属性是否可遍历,也就是能不能用for..in循环来取到.

设计模式

10、js常用设计模式的实现思路,单例,工厂,代理,装饰,观察者模式等

1) 单例: 任意对象都是单例,无须特别处理

var obj = {name: 'michaelqin', age: 30};

2) 工厂: 就是同样形式参数返回不同的实例

1
2
3
4
5
6
7
8
9
10
11
12
13
function Person() { this.name = 'Person1'; }
function Animal() { this.name = 'Animal1'; }

function Factory() {}
Factory.prototype.getInstance = function(className) {
return eval('new ' + className + '()');
}

var factory = new Factory();
var obj1 = factory.getInstance('Person');
var obj2 = factory.getInstance('Animal');
console.log(obj1.name); // Person1
console.log(obj2.name); // Animal1

3) 代理: 就是新建个类调用老类的接口,包一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function Person() { }
Person.prototype.sayName = function() { console.log('michaelqin'); }
Person.prototype.sayAge = function() { console.log(30); }

function PersonProxy() {
this.person = new Person();
var that = this;
this.callMethod = function(functionName) {
console.log('before proxy:', functionName);
that.person[functionName](); // 代理
console.log('after proxy:', functionName);
}
}

var pp = new PersonProxy();
pp.callMethod('sayName'); // 代理调用Person的方法sayName()
pp.callMethod('sayAge'); // 代理调用Person的方法sayAge()

4) 观察者: 就是事件模式,比如按钮的onclick这样的应用.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
function Publisher() {
this.listeners = [];
}
Publisher.prototype = {
'addListener': function(listener) {
this.listeners.push(listener);
},

'removeListener': function(listener) {
delete this.listeners[listener];
},

'notify': function(obj) {
for(var i = 0; i < this.listeners.length; i++) {
var listener = this.listeners[i];
if (typeof listener !== 'undefined') {
listener.process(obj);
}
}
}
}; // 发布者

function Subscriber() {

}
Subscriber.prototype = {
'process': function(obj) {
console.log(obj);
}
}; // 订阅者


var publisher = new Publisher();
publisher.addListener(new Subscriber());
publisher.addListener(new Subscriber());
publisher.notify({name: 'michaelqin', ageo: 30}); // 发布一个对象到所有订阅者
publisher.notify('2 subscribers will both perform process'); // 发布一个字符串到所有订阅者

11、列举数组相关的常用方法

push/pop, shift/unshift, split/join, slice/splice/concat, sort/reverse, map/reduce, forEach, filter

12、列举字符串相关的常用方法

indexOf/lastIndexOf/charAt, split/match/test, slice/substring/substr, toLowerCase/toUpperCase

node核心内置库类(事件, 流, 文件, 网络)

node概览:

1、node架构

主要分为三层,应用app >> V8及node内置架构 >> 操作系统. V8是node运行的环境,可以理解为node虚拟机.

node内置架构又可分为三层: 核心模块(javascript实现) >> c++绑定 >> libuv + CAes + http.

2、node的核心模块

EventEmitter, Stream, FS, Net, 全局对象

node全局对象:

1、node有哪些全局对象?

process、 console、 Buffer

2、process有哪些方法?

process.stdin, process.stdout, process.stderr, process.on, process.env, process.argv, process.arch, process.platform, process.exit

3、console有哪些常用方法?

console.log/console.info, console.error/console.warning, console.time/console.timeEnd, console.trace, console.table

4、node有哪些定时功能?

setTimeout/clearTimeout, setInterval/clearInterval, setImmediate/clearImmediate, process.nextTick

5、node中的事件循环是什么样子的?

process.nextTick >> setImmidate >> setTimeout/SetInterval

6、node中的Buffer如何应用?

Buffer是用来处理二进制数据的,比如图片,mp3,数据库文件等.Buffer支持各种编码解码,二进制字符串互转

EventEmitter:

1、什么是EventEmitter?

EventEmitter是node中一个实现观察者模式的类,主要功能是监听和发射消息,用于处理多模块交互问题.

2、如何实现一个EventEmitter?

主要分三步:定义一个子类, 调用构造函数, 继承EventEmitter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var util = require('util'),	
EventEmitter = require('event').EventEmitter;
//构造函数
function MyEmitter () {
EventEmitter.call(this);
}
//继承
util.inherits(MyEmitter, EventEmitter);

var em = new MyEmitter();
//接受事件
em.on('hello', function(data) {
console.log('收到事件hello的数据:', data);
});
em.emit('hello', 'EventEmitter传递消息真方便');

3、EventEmitter有哪些典型应用?

模块之间传递消息
回调函数内外传递消息
处理流数据
观察者模式发射触发机制

4、怎么捕获EventEmitter的错误事件?

监听error事件即可,若有多个EventEmitter,可用domain来统一处理。

1
2
3
4
5
6
7
8
9
10
11
12
var domain = require('domain');
var myDomain = domain.create();
//接受事件并打印
myDomain.on('error', function(err){
console.log('domain接受到的事件', err);
});
myDomain.run(function() {
var emitter1 = new MyEmitter();
emitter1.emit('error', '错误事件来自emitter1');
var emitter2 = new MyEmitter();
emitter2.emit('error', '错误事件来自emitter2');
});

5、EventEmitter中的newListenser事件有什么用处?

newListener可以用来做事件机制的反射,特殊应用,事件管理等.当任何on事件添加到EventEmitter时,就会触发newListener事件,基于这种模式,我们可以做很多自定义处理.

1
2
3
4
5
6
7
8
9
var emitter3 = new MyEmitter();
emitter3.on('newListener', function(name, listener) {
console.log("新事件的名字:", name);
console.log("新事件的代码:", listener);
setTimeout(function(){ console.log("我是自定义延时处理机制"); }, 1000);
});
emitter3.on('hello', function(){
console.log('hello node');
});

Stream

stream是基于事件EventEmitter的数据管理模式.由各种不同的抽象接口组成,主要包括可写,可读,可读写,可转换等几种类型.

1、Stream有什么好处?

非阻塞式数据处理提升效率,片段处理节省内存,管道处理方便扩展

2、Stream有哪些典型应用?

文件处理、网络交换、数据转换、音视频处理

3、怎么捕获Stream的错误事件?

监听error事件、方法同EventEmitter

4、哪些常用Stream,分别什么时候用?

Readable为可被读流,在座位数据源时使用;
Writeable为可被读流,在作为输出元时使用;
Duplex为读写流,作为输入源接受被写入,同时又作为输入源被后面的流读出;
Transform机制和Duplex一样,都是双向流,区别时Transfrom只需要实现一个函数_transfrom(chunk, encoding, callback);
而Duplex需要分别实现_read(size)函数和_write(chunk, encoding, callback)函数.    

5、实现一个Writable Stream?

三步走:1)构造函数call Writable 2) 继承Writable 3) 实现_write(chunk, encoding, callback)函数

```
var Writeable = require('stream').Writable;
var util = require('util');
//构造函数
function MyWriteable(options) {
    Writeable.call(this, options);
}
//继承Writeable
util.inherits(MyWriteable, Writable);
MyWritable.prototype._write = function(chunk, encoding, callback) {
    // 此处可对写入的数据进行处理
    console.log("被写入的数据是:", chunk.toString()); 
    callback();
};
// stdin作为输入源,MyWritable作为输出源   
process.stdin.pipe(new MyWritable()); 
```            

node高级话题(异步, 部署, 性能调优, 异步调试)

1、node中的异步与同步怎么理解?

node是单线程的,异步是通过一次次的事件循环来实现的。
同步则是阻塞式的io,在高并发环境下会有很大的性能问题,所以同步一般只在基础框架的启动时使用,如:加载配置文件、初始化程序

2、哪些方法可以进行异步流程控制?

1)多层嵌套回调
2)单独为回调写函数,函数里再回调
3)第三方框架:async、q、promise

3、怎么绑定node程序到80端口?

1)sudo
2)Apache/nginx代理
3)操作系统的firewall iptables端口绑定
4)第三方库up

4、有哪些方法可以让node程序遇到错误后自动重启?

1) runit 
2) forever 
3) nohup npm start &
4)up -watch -port 80 server.js

5、怎么充分利用多个cpu?

1个cpu运行一个node程序

6、怎样调节node执行单元的内存大小?

用--max-old-space-size 和 --max-new-space-size 来设置 v8 使用内存的上限

7、有哪些常用方法可以防止程序崩溃?

1) try-catch-finally 
2) EventEmitter/Stream error事件处理 
3) domain统一控制 
4) jshint静态检查 
5) jasmine/mocha进行单元测试

8、怎样调试node程序?

1) 监听错误事件req.on('error', function(){}), 适用EventEmitter存在的情况; 
2) Promise.then.catch(error),适用Promise存在的情况 
3) try-catch,适用async-await和js运行时异常,比如undefined object
-------------本文结束感谢您的阅读-------------
显示 Gitment 评论