Node.js面试题,侧重后端应用与对Node核心的理解
node-interview-questions
Node是搞后端的,不应该被被归为前端,更不应该用前端的观点去理解,去面试node开发人员。所以这份面试题大全,更侧重后端应用与对Node核心的理解。
node开发技能图解
文章图片
node_skillset.jpg node 事件循环机制
文章图片
event_loop.jpg 起源
- node正风生火起,很多介绍却停留在入门阶段,无法投入生产
- node相关的高质量面试题更是少之又少,很难全面考查应聘者的node能力
- 许多文章在讲第三方类库,可是这些库质量差距较大,一旦遇到问题怎么办
- 必需的,全面了解node核心才能成为一名合格的node开发人员
- 前后端兼顾,更侧重后端
- 理论实战兼顾,侧重考察对实战中应用较多的理论的理解
- 参考答案简单明了,一针见血,不为追求严谨而浪费口舌,绕弯子
- 尽量用代码讲清理论的应用与区别,以接地气
- 终极目标是让大家对node有一个快速完整的认识
- ES6新特性
- javascript高级话题(面向对象,作用域,闭包,设计模式等)
- node核心内置类库(事件,流,文件,网络等)
- node高级话题(异步,部署,性能调优,异常调试等)
- 常用知名第三方类库(Async, Express等)
- 其它相关后端常用技术(MongoDB, Redis, Apache, Nginx等)
- 常用前端技术(Html5, CSS3, JQuery等)
-
- ES6有哪些新特性?
-
- 你对ES6的个人看法?
推荐ES6入门好书: 阮一峰 ECMAScript 6入门
javascript高级话题(面向对象,作用域,闭包,设计模式等)
-
- 常用js类定义的方法有哪些?
代码演示
- 构造函数方法定义类
function Person(){
this.name = 'michaelqin';
}
Person.prototype.sayName = function(){
alert(this.name);
}var person = new Person();
person.sayName();
- 对象创建方法定义类
var Person = {
name: 'michaelqin',
sayName: function(){ alert(this.name);
}
};
var person = Object.create(Person);
person.sayName();
-
- js类继承的方法有哪些
代码演示
- 原型链法
function Animal() {
this.name = 'animal';
}
Animal.prototype.sayName = function(){
alert(this.name);
};
function Person() {}
Person.prototype = Animal.prototype;
// 人继承自动物
Person.prototype.constructor = 'Person';
// 更新构造函数为人
- 属性复制法
function Animal() {
this.name = 'animal';
}
Animal.prototype.sayName = function() {
alert(this.name);
};
function Person() {}for(prop in Animal.prototype) {
Person.prototype[prop] = Animal.prototype[prop];
} // 复制动物的所有属性到人量边
Person.prototype.constructor = 'Person';
// 更新构造函数为人
- 构造器应用法
function Animal() {
this.name = 'animal';
}
Animal.prototype.sayName = function() {
alert(this.name);
};
function Person() {
Animal.call(this);
// apply, call, bind方法都可以.细微区别,后面会提到.
}
-
- js类多重继承的实现方法是怎么样的?
-
- js里的作用域是什么样子的?
代码演示
var globalVar = 'global var';
function test() {
alert(globalVar);
// undefined, 因为globalVar在本函数内被重定义了,导致全局失效,这里使用函数内的变量值,可是此时还没定义
var globalVar = 'overrided var';
// globalVar在本函数内被重定义
alert(globalVar);
// overrided var
}
alert(globalVar);
// global var,使用全局变量
-
- js里边的this指的是什么?
代码演示
function Person() {
}
Person.prototype.sayName() { alert(this.name);
}var person1 = new Person();
person1.name = 'michaelqin';
person1.sayName();
// michaelqin
-
- apply, call和bind有什么区别?
代码演示
function Person() {
}
Person.prototype.sayName() { alert(this.name);
}var obj = {name: 'michaelqin'};
// 注意这是一个普通对象,它不是Person的实例
1) apply
Person.prototype.sayName.apply(obj, [param1, param2, param3]);
2) call
Person.prototype.sayName.call(obj, param1, param2, param3);
3) bind
var sn = Person.prototype.sayName.bind(obj);
sn([param1, param2, param3]);
// bind需要先绑定,再执行
sn(param1, param2, param3);
// bind需要先绑定,再执行
-
- caller, callee和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');
-
- 什么是闭包,闭包有哪些用处?
-
- defineProperty, hasOwnProperty, propertyIsEnumerable都是做什么用的?
-
- js常用设计模式的实现思路,单例,工厂,代理,装饰,观察者模式等
1) 单例: 任意对象都是单例,无须特别处理
var obj = {name: 'michaelqin', age: 30};
2) 工厂: 就是同样形式参数返回不同的实例
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);
// Animal13) 代理: 就是新建个类调用老类的接口,包一下
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这样的应用.
function Publisher() {
this.listeners = [];
}
Publisher.prototype = {
'addListener': function(listener) {
this.listeners.push(listener);
},'removeListener': function(listener) {
delete this.listeners[this.listeners.indexOf(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');
// 发布一个字符串到所有订阅者
-
- 列举数组相关的常用方法
-
- 列举字符串相关的常用方法
node核心内置类库(事件,流,文件,网络等) node概览
-
- 为什么要用node?
-
- node的构架是什么样子的?
文章图片
-
- node有哪些核心模块?
node全局对象
-
- node有哪些全局对象?
-
- process有哪些常用方法?
-
- console有哪些常用方法?
-
- node有哪些定时功能?
-
- node中的事件循环是什么样子的?
总体上执行顺序是:process.nextTick >> setImmidate >> setTimeout/SetInterval
看官网吧:
https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/
- node中的事件循环是什么样子的?
-
- node中的Buffer如何应用?
EventEmitter
-
- 什么是EventEmitter?
-
- 如何实现一个EventEmitter?
代码演示
var util = require('util');
var EventEmitter = require('events').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传递消息真方便!');
-
- EventEmitter有哪些典型应用?
-
- 怎么捕获EventEmitter的错误事件?
代码演示
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');
emitter2 = new MyEmitter();
emitter2.emit('error', '错误事件来自emitter2');
});
-
- EventEmitter中的newListenser事件有什么用处?
代码演示
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?
-
- Stream有什么好处?
-
- Stream有哪些典型应用?
-
- 怎么捕获Stream的错误事件?
-
- 有哪些常用Stream,分别什么时候使用?
-
- 实现一个Writable Stream?
代码演示
var Writable = require('stream').Writable;
var util = require('util');
function MyWritable(options) {
Writable.call(this, options);
} // 构造函数
util.inherits(MyWritable, Writable);
// 继承自Writable
MyWritable.prototype._write = function(chunk, encoding, callback) {
console.log("被写入的数据是:", chunk.toString());
// 此处可对写入的数据进行处理
callback();
};
process.stdin.pipe(new MyWritable());
// stdin作为输入源,MyWritable作为输出源
文件系统
-
- 内置的fs模块架构是什么样子的?
-
- 读写一个文件有多少种方法?
-
- 怎么读取json配置文件?
-
- fs.watch和fs.watchFile有什么区别,怎么应用?
网络
-
- node的网络模块架构是什么样子的?
-
- node是怎样支持https,tls的?
-
- 实现一个简单的http服务器?
代码演示
var http = require('http');
// 加载http模块http.createServer(function(req, res) {
res.writeHead(200, {'Content-Type': 'text/html'});
// 200代表状态成功, 文档类型是给浏览器识别用的
res.write(' 我是标题啊! 这么原生,初级的服务器,下辈子能用着吗?!');
// 返回给客户端的html数据
res.end();
// 结束输出流
}).listen(3000);
// 绑定3ooo, 查看效果请访问 http://localhost:3000
child-process
-
- 为什么需要child-process?
-
- exec,execFile,spawn和fork都是做什么用的?
-
- 实现一个简单的命令行交互程序?
代码演示
var cp = require('child_process');
var child = cp.spawn('echo', ['你好', "钩子"]);
// 执行命令
child.stdout.pipe(process.stdout);
// child.stdout是输入流,process.stdout是输出流
// 这句的意思是将子进程的输出作为当前程序的输入流,然后重定向到当前程序的标准输出,即控制台
-
- 两个node程序之间怎样交互?
代码演示
1) fork-parent.js
var cp = require('child_process');
var child = cp.fork('./fork-child.js');
child.on('message', function(msg){
console.log('老爸从儿子接受到数据:', msg);
});
child.send('我是你爸爸,送关怀来了!');
2) fork-child.js
process.on('message', function(msg){
console.log("儿子从老爸接收到的数据:", msg);
process.send("我不要关怀,我要银民币!");
});
-
- 怎样让一个js文件变得像linux命令一样可执行?
-
- child-process和process的stdin,stdout,stderror是一样的吗?
node高级话题(异步,部署,性能调优,异常调试等)
-
- node中的异步和同步怎么理解
-
- 有哪些方法可以进行异步流程的控制?
-
- 怎样绑定node程序到80端口?
-
- 有哪些方法可以让node程序遇到错误后自动重启?
-
- 怎样充分利用多个CPU?
-
- 怎样调节node执行单元的内存大小?
-
- 程序总是崩溃,怎样找出问题在哪里?
-
- 有哪些常用方法可以防止程序崩溃?
-
- 怎样调试node程序?
-
- 如何捕获NodeJS中的错误,有几种方法?
参考答案: 1) 监听错误事件req.on('error', function(){}), 适用EventEmitter存在的情况; 2) Promise.then.catch(error),适用Promise存在的情况 3) try-catch,适用async-await和js运行时异常,比如undefined object
- 如何捕获NodeJS中的错误,有几种方法?
-
- async都有哪些常用方法,分别是怎么用?
- async.parallel并行执行完多个函数后,调用结束函数
async.parallel([
function(){ ... },
function(){ ... }
], callback);
- async.series串行执行完多个函数后,调用结束函数
async.series([
function(){ ... },
function(){ ... }
]);
- async.waterfall依次执行多个函数,后一个函数以前面函数的结果作为输入参数
async.waterfall([
function(callback) {
callback(null, 'one', 'two');
},
function(arg1, arg2, callback) {
// arg1 now equals 'one' and arg2 now equals 'two'
callback(null, 'three');
},
function(arg1, callback) {
// arg1 now equals 'three'
callback(null, 'done');
}
], function (err, result) {
// result now equals 'done'
});
- async.map异步执行多个数组,返回结果数组
async.map(['file1','file2','file3'], fs.stat, function(err, results){
// results is now an array of stats for each file
});
- async.filter异步过滤多个数组,返回结果数组
async.filter(['file1','file2','file3'], fs.exists, function(results){
// results now equals an array of the existing files
});
-
- express项目的目录大致是什么样子的
-
- express常用函数
-
- express中如何获取路由的参数
-
- express response有哪些常用方法
res.download() 弹出文件下载
res.end() 结束response
res.json() 返回json
res.jsonp() 返回jsonp
res.redirect() 重定向请求
res.render() 渲染模板
res.send() 返回多种形式数据
res.sendFile 返回文件
res.sendStatus() 返回状态
其它相关后端常用技术(MongoDB, Redis, Apache, Nginx等)
-
- mongodb有哪些常用优化措施
-
- mongoose是什么?有支持哪些特性?
-
- redis支持哪些功能
-
- redis最简单的应用
var redis = require("redis"),
client = redis.createClient();
client.set("foo_rand000000000000", "some fantastic value");
client.get("foo_rand000000000000", function (err, reply) {
console.log(reply.toString());
});
client.end();
-
- apache,nginx有什么区别?
常用前端技术(Html5, CSS3, JQuery等)
-
- Html5有哪些比较实用新功能
-
- CSS3/JQuery有哪些学常见选择器
-
- JQuery有哪些经典应用
node.js 设计模式
- HeadFirstDesignPatternInJavascript
- HeadFirstDesignPattern是一本非常经典的设计模式入门书籍。可是Javascript由于语言本身的限制,比较难以应用。随着新浏览器和Node.js开始普遍支持ES5, ES6,尤其是对类的支持。设计模式已经变得触手可及,对于大型Node.js项目更是非常必要。 HeadFirstDesignPatternInJavascript正是js版本的设计模式实现。
转载自jimuyouyou的GitHub开源项目,在最后附上项目名,以及地址。
推荐阅读
- PMSJ寻平面设计师之现代(Hyundai)
- 杜月笙的口才
- Node.js中readline模块实现终端输入
- Linux下面如何查看tomcat已经使用多少线程
- 皮夹克
- 解读《摩根集团》(1)
- 绘本与写作
- 蓝桥杯试题
- 麦田社群
- 面对苦难——如何化解