本文主要源自https://github.com/jimuyouyou/node-interview-questions#jsAdvanced腊瑟,用作歸納整理,歡迎各位指正交流馅精。
Nodejs面試題大全?
Node是搞后端的蛾狗,不應(yīng)該被被歸為前端骨稿,更不應(yīng)該用前端的觀點去理解,去面試node開發(fā)人員扮叨。所以這份面試題大全缤弦,更側(cè)重后端應(yīng)用與對Node核心的理解。
github地址:https://github.com/jimuyouyou/node-interview-questions
注: 這是本人歷時一星期完成的小作品彻磁,github里面對一些關(guān)鍵代碼還有js源文件.直接node filename.js就可查看效果.
? ? ?第一個版本碍沐,寫的匆忙狸捅,能力有限,歡迎拍磚補充累提!后面持續(xù)更新會及時發(fā)布到github上.
node開發(fā)技能圖解
起源
node正風(fēng)生火起尘喝,很多介紹卻停留在入門階段,無法投入生產(chǎn)
node相關(guān)的高質(zhì)量面試題更是少之又少斋陪,很難全面考查應(yīng)聘者的node能力
許多文章在講第三方類庫朽褪,可是這些庫質(zhì)量差距較大,一旦遇到問題怎么辦
必需的无虚,全面了解node核心才能成為一名合格的node開發(fā)人員
目標與原則
前后端兼顧缔赠,更側(cè)重后端
理論實戰(zhàn)兼顧,側(cè)重考察對實戰(zhàn)中應(yīng)用較多的理論的理解
參考答案簡單明了友题,一針見血嗤堰,不為追求嚴謹而浪費口舌,繞彎子
盡量用代碼講清理論的應(yīng)用與區(qū)別度宦,以接地氣
終極目標是讓大家對node有一個快速完整的認識
內(nèi)容大綱
javascript高級話題(面向?qū)ο筇呦唬饔糜颍]包戈抄,設(shè)計模式等)
node核心內(nèi)置類庫(事件离唬,流,文件呛凶,網(wǎng)絡(luò)等)
node高級話題(異步男娄,部署行贪,性能調(diào)優(yōu)漾稀,異常調(diào)試等)
其它相關(guān)后端常用技術(shù)(MongoDB, Redis, Apache, Nginx等)
常用前端技術(shù)(Html5, CSS3, JQuery等)
javascript高級話題(面向?qū)ο螅饔糜蚪ㄌ保]包崭捍,設(shè)計模式等)
1. 常用js類定義的方法有哪些?
參考答案:主要有構(gòu)造函數(shù)原型和對象創(chuàng)建兩種方法啰脚。原型法是通用老方法殷蛇,對象創(chuàng)建是ES5推薦使用的方法.目前來看,原型法更普遍.
代碼演示
1) 構(gòu)造函數(shù)方法定義類
? ? function Person(){
? ? ? ? this.name = 'michaelqin';
? ? }
? ? Person.prototype.sayName = function(){
? ? ? ? alert(this.name);
? ? }
? ? var person = new Person();
? ? person.sayName();
2) 對象創(chuàng)建方法定義類
? ? var Person = {
? ? ? ? name: 'michaelqin',
? ? ? ? sayName: function(){ alert(this.name); }
? ? };
? ? var person = Object.create(Person);
? ? person.sayName();
2. js類繼承的方法有哪些
參考答案:原型鏈法橄浓,屬性復(fù)制法和構(gòu)造器應(yīng)用法. 另外粒梦,由于每個對象可以是一個類,這些方法也可以用于對象類的繼承.
代碼演示
1) 原型鏈法
? ? function Animal() {
? ? ? ? this.name = 'animal';
? ? }
? ? Animal.prototype.sayName = {
? ? ? ? alert(this.name);
? ? };
? ? function Person() {}
? ? Person.prototype = Animal.prototype; //人繼承自動物
? ? Person.prototype.constructor = 'Person'; //更新構(gòu)造函數(shù)為人
2) 屬性自制法
? ? function Animal() {
? ? ? ? this.name = 'animal';
? ? }
? ? Animal.prototype.sayName = {
? ? ? ? alert(this.name);
? ? };
? ? function Person() {}
? ? for(prop in Animal.prototype) {
? ? ? ? Person.prototype[prop] = Animal.prototype[prop];
? ? } //復(fù)制動物的所有屬性到人量邊
? ? Person.prototype.constructor = 'Person'; //更新構(gòu)造函數(shù)為人
3) 構(gòu)造器應(yīng)用法
? ? function Animal() {
? ? ? ? this.name = 'animal';
? ? }
? ? Animal.prototype.sayName = {
? ? ? ? alert(this.name);
? ? };
? ? function Person() {
? ? ? ? Animal.call(this); // apply, call, bind方法都可以.細微區(qū)別荸实,后面會提到.
? ? }
3. js類多重繼承的實現(xiàn)方法是怎么樣的?
參考答案:就是類繼承里邊的屬性復(fù)制法來實現(xiàn).因為當所有父類的prototype屬性被復(fù)制后匀们,子類自然擁有類似行為和屬性.
4. js里的作用域是什么樣子的?
參考答案:大多數(shù)語言里邊都是塊作作用域准给,以{}進行限定泄朴,js里邊不是.js里邊叫函數(shù)作用域重抖,就是一個變量在全函數(shù)里有效.比如有個變量p1在函數(shù)最后一行定義,第一行也有效祖灰,但是值是undefined.
代碼演示
? ? var globalVar = 'global var';
? ? function test() {
? ? ? ? alert(globalVar); // undefined,因為globalVar在本函數(shù)內(nèi)被重定義了钟沛,導(dǎo)致全局失效,這里使用函數(shù)內(nèi)的變量值局扶,可是此時還沒定義
? ? ? ? var globalVar = 'overrided var'; // globalVar在本函數(shù)內(nèi)被重定義
? ? ? ? alert(globalVar); // overrided var
? ? }
? ? alert(globalVar); // global var恨统,使用全局變量
5. js里邊的this指的是什么?
參考答案: this指的是對象本身,而不是構(gòu)造函數(shù).
代碼演示
? ? function Person() {
? ? }
? ? Person.prototype.sayName() { alert(this.name); }
? ? var person1 = new Person();
? ? person1.name = 'michaelqin';
? ? person1.sayName(); // michaelqin
6. apply, call和bind有什么區(qū)別?
參考答案:三者都可以把一個函數(shù)應(yīng)用到其他對象上三妈,注意不是自身對象.a(chǎn)pply,call是直接執(zhí)行函數(shù)調(diào)用延欠,bind是綁定,執(zhí)行需要再次調(diào)用.a(chǎn)pply和call的區(qū)別是apply接受數(shù)組作為參數(shù)沈跨,而call是接受逗號分隔的無限多個參數(shù)列表由捎,
代碼演示
? ? 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需要先綁定饿凛,再執(zhí)行?
? ? sn(param1, param2, param3); // bind需要先綁定狞玛,再執(zhí)行
7. caller, callee和arguments分別是什么?
參考答案: caller,callee之間的關(guān)系就像是employer和employee之間的關(guān)系,就是調(diào)用與被調(diào)用的關(guān)系涧窒,二者返回的都是函數(shù)對象引用.a(chǎn)rguments是函數(shù)的所有參數(shù)列表心肪,它是一個類數(shù)組的變量.
代碼演示
? ? 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. 什么是閉包,閉包有哪些用處?
參考答案: 閉包這個術(shù)語纠吴,無論中文翻譯還是英文解釋都太2B了硬鞍,我必須罵人,因為它什么其實都不是.非要講它是什么的話戴已,兩個字函數(shù)固该,更多字嵌套函數(shù)的父子自我引用關(guān)系.所有函數(shù)都是閉包.通俗的說,閉包就是作用域范圍糖儡,因為js是函數(shù)作用域伐坏,所以函數(shù)就是閉包.全局函數(shù)的作用域范圍就是全局,所以無須討論.更多的應(yīng)用其實是在內(nèi)嵌函數(shù)握联,這就會涉及到內(nèi)嵌作用域桦沉,或者叫作用域鏈.說到內(nèi)嵌,其實就是父子引用關(guān)系(父函數(shù)包含子函數(shù)金闽,子函數(shù)因為函數(shù)作用域又引用父函數(shù)纯露,這它媽不是死結(jié)嗎?所以叫閉包)代芜,這就會帶來另外一個問題埠褪,什么時候引用結(jié)束?如果不結(jié)束,就會一直占用內(nèi)存组橄,引起內(nèi)存泄漏.好吧荞膘,不用的時候就引用設(shè)為空,死結(jié)就解開了.
9. defineProperty, hasOwnProperty, isEnumerable都是做什么用的玉工?
參考答案:Object.defineProperty(obj, prop, descriptor)用來給對象定義屬性,有value,writable,configurable,enumerable,set/get等.hasOwnProerty用于檢查某一屬性是不是存在于對象本身羽资,繼承來的父親的屬性不算.isEnumerable用來檢測某一屬性是否可遍歷,也就是能不能用for..in循環(huán)來取到.
10. js常用設(shè)計模式的實現(xiàn)思路遵班,單例屠升,工廠,代理狭郑,裝飾腹暖,觀察者模式等
參考答案:
? ? 1)單例: 任意對象都是單例,無須特別處理
? ? var obj = {name: 'michaelqin', age: 30};
? ? 2)工廠: 就是同樣形式參數(shù)返回不同的實例
? ? 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)代理: 就是新建個類調(diào)用老類的接口,包一下
? ? 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'); //代理調(diào)用Person的方法sayName()
? ? pp.callMethod('sayAge'); //代理調(diào)用Person的方法sayAge()?
? ? 4)觀察者: 就是事件模式翰萨,比如按鈕的onclick這樣的應(yīng)用.
? ? 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);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }
? ? }; //發(fā)布者
? ? 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}); //發(fā)布一個對象到所有訂閱者
? ? publisher.notify('2 subscribers will both perform process'); //發(fā)布一個字符串到所有訂閱者
11. 列舉數(shù)組相關(guān)的常用方法
參考答案: push/pop, shift/unshift, split/join, slice/splice/concat, sort/reverse, map/reduce, forEach, filter
12. 列舉字符串相關(guān)的常用方法
參考答案: indexOf/lastIndexOf/charAt, split/match/test, slice/substring/substr, toLowerCase/toUpperCase
node核心內(nèi)置類庫(事件脏答,流,文件亩鬼,網(wǎng)絡(luò)等)
node概覽
1. 為什么要用node?
參考答案: 總結(jié)起來node有以下幾個特點:簡單強大殖告,輕量可擴展.簡單體現(xiàn)在node使用的是javascript,json來進行編碼,人人都會雳锋;強大體現(xiàn)在非阻塞IO,可以適應(yīng)分塊傳輸數(shù)據(jù)黄绩,較慢的網(wǎng)絡(luò)環(huán)境,尤其擅長高并發(fā)訪問玷过;輕量體現(xiàn)在node本身既是代碼爽丹,又是服務(wù)器,前后端使用統(tǒng)一語言;可擴展體現(xiàn)在可以輕松應(yīng)對多實例辛蚊,多服務(wù)器架構(gòu)粤蝎,同時有海量的第三方應(yīng)用組件.
2. node的構(gòu)架是什么樣子的?
參考答案:主要分為三層,應(yīng)用app >> V8及node內(nèi)置架構(gòu)>>操作系統(tǒng). V8是node運行的環(huán)境嚼隘,可以理解為node虛擬機.node內(nèi)置架構(gòu)又可分為三層:核心模塊(javascript實現(xiàn)) >> c++綁定>> libuv + CAes + http.
3. node有哪些核心模塊?
參考答案: EventEmitter, Stream, FS, Net和全局對象
node全局對象
1. node有哪些全局對象?
參考答案: process, console, Buffer和exports
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中的事件循環(huán)是什么樣子的?
參考答案: event loop其實就是一個事件隊列诽里,先加入先執(zhí)行,執(zhí)行完一次隊列飞蛹,再次循環(huán)遍歷看有沒有新事件加入隊列.執(zhí)行中的叫IO events, setImmediate是在當前隊列立即執(zhí)行,setTimout/setInterval是把執(zhí)行定時到下一個隊列,process.nextTick是在當前執(zhí)行完灸眼,下次遍歷前執(zhí)行.所以總體順序是: IO events >> setImmediate >> setTimeout/setInterval >> process.nextTick
6. node中的Buffer如何應(yīng)用?
參考答案: Buffer是用來處理二進制數(shù)據(jù)的卧檐,比如圖片,mp3,數(shù)據(jù)庫文件等.Buffer支持各種編碼解碼焰宣,二進制字符串互轉(zhuǎn).
EventEmitter
1. 什么是EventEmitter?
參考答案: EventEmitter是node中一個實現(xiàn)觀察者模式的類霉囚,主要功能是監(jiān)聽和發(fā)射消息,用于處理多模塊交互問題.
2. 如何實現(xiàn)一個EventEmitter?
參考答案: 主要分三步:定義一個子類匕积,調(diào)用構(gòu)造函數(shù)盈罐,繼承EventEmitter
代碼演示
? ? var util = require('util');
? ? var EventEmitter = require('events').EventEmitter;
? ? function MyEmitter() {
? ? ? ? EventEmitter.call(this);
? ? } //構(gòu)造函數(shù)
? ? util.inherits(MyEmitter, EventEmitter); //繼承
? ? var em = new MyEmitter();
? ? em.on('hello', function(data) {
? ? ? ? console.log('收到事件hello的數(shù)據(jù):', data);
? ? }); //接收事件榜跌,并打印到控制臺
? ? em.emit('hello', 'EventEmitter傳遞消息真方便!');
3. EventEmitter有哪些典型應(yīng)用?
參考答案: 1) 模塊間傳遞消息 2) 回調(diào)函數(shù)內(nèi)外傳遞消息 3) 處理流數(shù)據(jù),因為流是在EventEmitter基礎(chǔ)上實現(xiàn)的. 4) 觀察者模式發(fā)射觸發(fā)機制相關(guān)應(yīng)用
4. 怎么捕獲EventEmitter的錯誤事件?
參考答案: 監(jiān)聽error事件即可.如果有多個EventEmitter,也可以用domain來統(tǒng)一處理錯誤事件.
代碼演示
? ? 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');
? ? });
5. EventEmitter中的newListenser事件有什么用處?
參考答案: newListener可以用來做事件機制的反射盅粪,特殊應(yīng)用钓葫,事件管理等.當任何on事件添加到EventEmitter時,就會觸發(fā)newListener事件票顾,基于這種模式础浮,我們可以做很多自定義處理.
代碼演示
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
1. 什么是Stream?
參考答案: stream是基于事件EventEmitter的數(shù)據(jù)管理模式.由各種不同的抽象接口組成,主要包括可寫奠骄,可讀豆同,可讀寫,可轉(zhuǎn)換等幾種類型.
2. Stream有什么好處?
參考答案: 非阻塞式數(shù)據(jù)處理提升效率含鳞,片斷處理節(jié)省內(nèi)存影锈,管道處理方便可擴展等.
3. Stream有哪些典型應(yīng)用?
參考答案: 文件,網(wǎng)絡(luò)蝉绷,數(shù)據(jù)轉(zhuǎn)換精居,音頻視頻等.
4. 怎么捕獲Stream的錯誤事件?
參考答案:監(jiān)聽error事件,方法同EventEmitter.
5. 有哪些常用Stream,分別什么時候使用?
參考答案: Readable為可被讀流潜必,在作為輸入數(shù)據(jù)源時使用靴姿;Writable為可被寫流,在作為輸出源時使用;Duplex為可讀寫流,它作為輸出源接受被寫入磁滚,同時又作為輸入源被后面的流讀出.Transform機制和Duplex一樣佛吓,都是雙向流,區(qū)別時Transfrom只需要實現(xiàn)一個函數(shù)_transfrom(chunk, encoding, callback);而Duplex需要分別實現(xiàn)_read(size)函數(shù)和_write(chunk, encoding, callback)函數(shù).
6. 實現(xiàn)一個Writable Stream?
參考答案:三步走:1)構(gòu)造函數(shù)call Writable 2) 繼承Writable 3)實現(xiàn)_write(chunk, encoding, callback)函數(shù)
代碼演示
var Writable = require('stream').Writable;
var util = require('util');
function MyWritable(options) {
? ? Writable.call(this, options);
} //構(gòu)造函數(shù)
util.inherits(MyWritable, Writable); //繼承自Writable
MyWritable.prototype._write = function(chunk, encoding, callback) {
? ? console.log("被寫入的數(shù)據(jù)是:", chunk.toString()); //此處可對寫入的數(shù)據(jù)進行處理
? ? callback();
};
process.stdin.pipe(new MyWritable()); // stdin作為輸入源垂攘,MyWritable作為輸出源? ?
文件系統(tǒng)
1. 內(nèi)置的fs模塊架構(gòu)是什么樣子的?
參考答案: fs模塊主要由下面幾部分組成: 1) POSIX文件Wrapper,對應(yīng)于操作系統(tǒng)的原生文件操作2)文件流fs.createReadStream和fs.createWriteStream 3)同步文件讀寫,fs.readFileSync和fs.writeFileSync 4)異步文件讀寫, fs.readFile和fs.writeFile
2. 讀寫一個文件有多少種方法?
參考答案: 總體來說有四種: 1) POSIX式低層讀寫 2) 流式讀寫 3) 同步文件讀寫 4) 異步文件讀寫
3. 怎么讀取json配置文件?
參考答案: 主要有兩種方式维雇,第一種是利用node內(nèi)置的require('data.json')機制,直接得到j(luò)s對象; 第二種是讀入文件入內(nèi)容晒他,然后用JSON.parse(content)轉(zhuǎn)換成js對象.二者的區(qū)別是require機制情況下吱型,如果多個模塊都加載了同一個json文件,那么其中一個改變了js對象陨仅,其它跟著改變津滞,這是由node模塊的緩存機制造成的,只有一個js模塊對象; 第二種方式則可以隨意改變加載后的js變量灼伤,而且各模塊互不影響触徐,因為他們都是獨立的,是多個js對象.
4. fs.watch和fs.watchFile有什么區(qū)別狐赡,怎么應(yīng)用?
參考答案: 二者主要用來監(jiān)聽文件變動.fs.watch利用操作系統(tǒng)原生機制來監(jiān)聽撞鹉,可能不適用網(wǎng)絡(luò)文件系統(tǒng); fs.watchFile則是定期檢查文件狀態(tài)變更,適用于網(wǎng)絡(luò)文件系統(tǒng),但是相比fs.watch有些慢鸟雏,因為不是實時機制.
網(wǎng)絡(luò)
1. node的網(wǎng)絡(luò)模塊架構(gòu)是什么樣子的?
參考答案: node全面支持各種網(wǎng)絡(luò)服務(wù)器和客戶端享郊,包括tcp, http/https, tcp, udp, dns, tls/ssl等.
2. node是怎樣支持https,tls的?
參考答案: 主要實現(xiàn)以下幾個步驟即可: 1) openssl生成公鑰私鑰 2) 服務(wù)器或客戶端使用https替代http 3) 服務(wù)器或客戶端加載公鑰私鑰證書
3. 實現(xiàn)一個簡單的http服務(wù)器?
參考答案: 經(jīng)典又很沒毛意義的一個題目.思路是加載http模塊,創(chuàng)建服務(wù)器孝鹊,監(jiān)聽端口.
代碼演示
? ? var http = require('http'); //加載http模塊
? ? http.createServer(function(req, res) {
? ? ? ? res.writeHead(200, {'Content-Type': 'text/html'}); // 200代表狀態(tài)成功,文檔類型是給瀏覽器識別用的
? ? ? ? res.write('
我是標題按读稹!
這么原生惶室,初級的服務(wù)器温自,下輩子能用著嗎?!'); //返回給客戶端的html數(shù)據(jù)? ? ? ? res.end(); //結(jié)束輸出流
? ? }).listen(3000); //綁定3ooo,查看效果請訪問http://localhost:3000?
child-process
1. 為什么需要child-process?
參考答案: node是異步非阻塞的,這對高并發(fā)非常有效.可是我們還有其它一些常用需求皇钞,比如和操作系統(tǒng)shell命令交互悼泌,調(diào)用可執(zhí)行文件,創(chuàng)建子進程進行阻塞式訪問或高CPU計算等夹界,child-process就是為滿足這些需求而生的.child-process顧名思義馆里,就是把node阻塞的工作交給子進程去做.
2. exec,execFile,spawn和fork都是做什么用的?
參考答案: exec可以用操作系統(tǒng)原生的方式執(zhí)行各種命令,如管道cat ab.txt | grep hello; execFile是執(zhí)行一個文件; spawn是流式和操作系統(tǒng)進行交互; fork是兩個node程序(javascript)之間時行交互.
3. 實現(xiàn)一個簡單的命令行交互程序?
參考答案:那就用spawn吧.
代碼演示
? ? var cp = require('child_process');
? ? var child = cp.spawn('echo', ['你好', "鉤子"]); //執(zhí)行命令
? ? child.stdout.pipe(process.stdout); // child.stdout是輸入流可柿,process.stdout是輸出流
? ? //這句的意思是將子進程的輸出作為當前程序的輸入流鸠踪,然后重定向到當前程序的標準輸出,即控制臺
4. 兩個node程序之間怎樣交互?
參考答案:用fork嘛复斥,上面講過了.原理是子程序用process.on, process.send营密,父程序里用child.on,child.send進行交互.
代碼演示
? ? 1) fork-parent.js
? ? var cp = require('child_process');
? ? var child = cp.fork('./fork-child.js');
? ? child.on('message', function(msg){
? ? ? ? console.log('老爸從兒子接受到數(shù)據(jù):', msg);
? ? });
? ? child.send('我是你爸爸,送關(guān)懷來了!');
? ? 2) fork-child.js
? ? process.on('message', function(msg){
? ? ? ? console.log("兒子從老爸接收到的數(shù)據(jù):", msg);
? ? ? ? process.send("我不要關(guān)懷目锭,我要銀民幣评汰!");
? ? });
5. 怎樣讓一個js文件變得像linux命令一樣可執(zhí)行?
參考答案: 1)在myCommand.js文件頭部加入#!/usr/bin/env node 2) chmod命令把js文件改為可執(zhí)行即可3)進入文件目錄,命令行輸入myComand就是相當于node myComand.js了
6. child-process和process的stdin,stdout,stderror是一樣的嗎?
參考答案: 概念都是一樣的痢虹,輸入被去,輸出,錯誤奖唯,都是流.區(qū)別是在父程序眼里惨缆,子程序的stdout是輸入流,stdin是輸出流.
node高級話題(異步丰捷,部署坯墨,性能調(diào)優(yōu),異常調(diào)試等)
1. node中的異步和同步怎么理解
參考答案: node是單線程的瓢阴,異步是通過一次次的循環(huán)事件隊列來實現(xiàn)的.同步則是說阻塞式的IO,這在高并發(fā)環(huán)境會是一個很大的性能問題畅蹂,所以同步一般只在基礎(chǔ)框架的啟動時使用,用來加載配置文件荣恐,初始化程序什么的.
2. 有哪些方法可以進行異步流程的控制?
參考答案: 1) 多層嵌套回調(diào) 2)為每一個回調(diào)寫單獨的函數(shù),函數(shù)里邊再回調(diào) 3) 用第三方框架比方async, q, promise等
3. 怎樣綁定node程序到80端口?
參考答案:多種方式1) sudo 2) apache/nginx代理3)用操作系統(tǒng)的firewall iptables進行端口重定向
4. 有哪些方法可以讓node程序遇到錯誤后自動重啟?
參考答案: 1) runit 2) forever 3) nohup npm start &
5. 怎樣充分利用多個CPU?
參考答案: 一個CPU運行一個node實例
6. 怎樣調(diào)節(jié)node執(zhí)行單元的內(nèi)存大小?
參考答案:用--max-old-space-size和--max-new-space-size來設(shè)置v8使用內(nèi)存的上限
7. 程序總是崩潰,怎樣找出問題在哪里?
參考答案: 1) node --prof查看哪些函數(shù)調(diào)用次數(shù)多2) memwatch和heapdump獲得內(nèi)存快照進行對比叠穆,查找內(nèi)存溢出
8. 有哪些常用方法可以防止程序崩潰?
參考答案: 1) try-catch-finally 2) EventEmitter/Stream error事件處理3) domain統(tǒng)一控制4) jshint靜態(tài)檢查5) jasmine/mocha進行單元測試
9. 怎樣調(diào)試node程序?
參考答案: node --debug app.js和node-inspector
常用知名第三方類庫(Async, Express等)
1. async都有哪些常用方法少漆,分別是怎么用?
參考答案: async是一個js類庫,它的目的是解決js中異常流程難以控制的問題.a(chǎn)sync不僅適用在node.js里硼被,瀏覽器中也可以使用. 1) async.parallel并行執(zhí)行完多個函數(shù)后示损,調(diào)用結(jié)束函數(shù)
? ? async.parallel([
? ? ? ? function(){ ... },
? ? ? ? function(){ ... }
? ? ], callback);
2) async.series串行執(zhí)行完多個函數(shù)后,調(diào)用結(jié)束函數(shù)
? ? async.series([
? ? ? ? function(){ ... },
? ? ? ? function(){ ... }
? ? ]);
3) async.waterfall依次執(zhí)行多個函數(shù)嚷硫,后一個函數(shù)以前面函數(shù)的結(jié)果作為輸入?yún)?shù)
? ? 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'?
? ? });
4) async.map異步執(zhí)行多個數(shù)組检访,返回結(jié)果數(shù)組
? ? async.map(['file1','file2','file3'], fs.stat, function(err, results){
? ? ? ? // results is now an array of stats for each file?
? ? });
5) async.filter異步過濾多個數(shù)組,返回結(jié)果數(shù)組
? ? async.filter(['file1','file2','file3'], fs.exists, function(results){
? ? ? ? // results now equals an array of the existing files?
? ? });
2. express項目的目錄大致是什么樣子的
參考答案: app.js, package.json, bin/www, public, routes, views.
3. express常用函數(shù)
參考答案: express.Router路由組件,app.get路由定向仔掸,app.configure配置脆贵,app.set設(shè)定參數(shù),app.use使用中間件
4. express中如何獲取路由的參數(shù)
參考答案: /users/:name使用req.params.name來獲取; req.body.username則是獲得表單傳入?yún)?shù)username; express路由支持常用通配符?, +, *, and ()
5. express response有哪些常用方法
參考答案: res.download()彈出文件下載
res.end()結(jié)束response
res.json()返回json
res.jsonp()返回jsonp
res.redirect()重定向請求
res.render()渲染模板
res.send()返回多種形式數(shù)據(jù)
res.sendFile返回文件
res.sendStatus()返回狀態(tài)
其它相關(guān)后端常用技術(shù)(MongoDB, Redis, Apache, Nginx等)
1. mongodb有哪些常用優(yōu)化措施
參考答案: 類似傳統(tǒng)數(shù)據(jù)庫,索引和分區(qū).
2. redis支持哪些功能
參考答案: set/get, hset/hget, publish/subscribe, expire
3. redis最簡單的應(yīng)用
參考答案:
? ? 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();
4. apache,nginx有什么區(qū)別?
參考答案: 二者都是代理服務(wù)器起暮,功能類似.a(chǎn)pache應(yīng)用簡單卖氨,相當廣泛.nginx在分布式,靜態(tài)轉(zhuǎn)發(fā)方面比較有優(yōu)勢.
常用前端技術(shù)(Html5, CSS3, JQuery等)
1. Html5有哪些比較實用新功能
參考答案: File API支持本地文件操作; Canvans/SVG支持繪圖; 拖拽功能支持; 本地存儲支持; 表單多屬性驗證支持; 原生音頻視頻支持等
2. CSS3/JQuery有哪些學(xué)常見選擇器
參考答案: id, 元素负懦,屬性, 值筒捺,父子兄弟, 序列等
3. JQuery有哪些經(jīng)典應(yīng)用
參考答案: 文檔選擇,文檔操作纸厉,動畫, ajax, json, js擴展等.