2017 版 Node.js 面試問題及答案
兩年前,我們發布了我們的第一篇關于Node.js面試的文章 Node.js面試常見問題和答案 ,近兩年,JavaScript和Node.js生態系統有了很多更新和發展,因此,是該更新這些面試問題和答案的時候了。
免責聲明(重要)
僅僅通過面試問題去評價一個面試者,從來都不是一個好的選擇。但是 這些問題可以讓你大體了解面試者在Node.js開發上的經驗。
當然,這些問題并不能全面反映一個人的思維方式和開發習慣。
我相信,開發中遇到的問題,更能反映面試者的知識水平 - 所以,我們鼓勵面試者和候選者做結對編程(結對編程技術是指兩位程序員坐在同一工作臺前開發軟件)。
最后也是最重要的:我們都是人,要盡最大的可能讓面試者感到尊重和被歡迎。這些問題并不意味著題目和正確答案,只是讓面試有話可聊。
2017 Node.js面試問題
-
什么是error-first回調模式?
-
如何避免“回調地獄”?
-
什么是Promises?
-
什么工具統一團隊的代碼風格?為什么統一的代碼風格很重要?
-
什么時候應當用npm?什么時候應當用yarn?
-
什么是樁代碼(stub)? 請描述一個應用場景!
-
什么是測試金字塔?請舉例說明!
-
你最欣賞的HTTP框架是什么?為什么?
-
如果保證你的cookie安全?如何阻止XSS攻擊?
-
如何確認項目的相關依賴安全?
答案
什么是error-first回調模式?
應用error-first回調模式是為了更好的進行錯誤和數據的傳遞。第一個參數保留給一個錯誤error對象,一旦出錯,錯誤將通過第一個參數error返回。其余的參數將用作數據的傳遞。
fs.readFile(filePath, function(err, data) {
if (err) {
// handle the error, the return is important here
// so execution stops here
return console.log(err)
}
// use the data object
console.log(data)
})
如何避免“回調地獄”?
解決這個問題的方法有很多:
-
模塊化設計: 講回調拆分成幾個獨立的函數
-
使用 流程控制庫 , 比如 async
-
組合使用 generators和Promises
-
使用 async/await 函數 (只能在Node v7 release版本運行, Node LTS版本尚不支持
什么是Promises?
promise的概念早在上個世紀八十年代就被提出,現在已經是大多數現代編程語言中支持的特性,讓你能更輕松地實現異步模型。
舉個簡單的例子, 正常來說100ms 之后將會輸出 result 。一旦失敗, catch 可以拋出異常。Promises允許鏈式操作。
new Promise((resolve, reject) => {
setTimeout(() => {
resolve('result')
}, 100)
})
.then(console.log)
.catch(console.error)
什么工具統一團隊的代碼風格? 為什么統一的代碼風格很重要?
團隊協作時,始終如一的代碼風格十分重要,代碼風格一致,團隊成員可以更輕松的構建項目,不用為每次構建項目都使用新的代碼風格而擔心。
同時, 始終如一的代碼風格,可以通過靜態分析排除代碼問題。
幫助規范代碼的工具:
如果你想更上一層樓,我推薦你立刻學習 JavaScript Clean Coding 原則。
什么是樁代碼(stub)? 請描述一個應用場景!
樁代碼(stub)就是在某些組件或模塊中,模擬某些功能的代碼。樁代碼(stub)的作用是占位,讓代碼在測試過程中順利運行。
一個例子,它實際的作用是寫一個文件,但是這段代碼并沒有真正的做這件事。
var fs = require('fs')
var writeFileStub = sinon.stub(fs, 'writeFile', function (path, data, cb) {
return cb(null)
})
expect(writeFileStub).to.be.called
writeFileStub.restore()
什么是測試金字塔?請舉例說明!
測試金字塔描述了單元測試(unit test),集成測試(integration tests),端到端測試(end-to-end test)在測試中占的比例。
舉個例子,測試一個HTTP API需要:
-
大量關于models 的單元測試 ( 使用樁代碼處理 ) ,
-
一些關于models如何和其他models交互的集成測試 ( 未使用樁代碼處理 ) ,
-
少量的端到端測試,也就是真實環境下的調用 ( 未使用樁代碼處理 ) .
你最欣賞的HTTP框架是什么?為什么?
這道題沒有標準答案。出這道題的目的是,看看面試者對他所使用框架,理解的有多深。只要面試者回答出框架的優缺點,為什么使用這個框架就可以了。
什么時候應該在后臺進程中使用消息服務?怎么處理工作線程的任務/怎么給worker安排任務?
消息隊列適用于后臺數據傳輸服務,比如發送郵件和數據圖像處理。
消息隊列有很多解決方案,比如 RabbitMQ 和 Kafka .
如何保證你的cookie安全?如何阻止XSS攻擊?
XSS攻擊是指攻擊者向Html頁面里插入惡意JavaScript代碼。
為了防止攻擊,你需要對HTTP header里的 set-cookie 進行處理:
-
HttpOnly- 這個屬性幫助防止跨站腳本攻擊,它禁止通過JavaScript訪問cookie。
-
secure- 這個屬性告訴瀏覽器,僅允許通過HTTPS協議訪問cookie。
所以,你需要做的是在請求頭里寫 Set-Cookie: sid=; HttpOnly 。如果你正在使用Express框架,可以使用 express-cookie session ,他會默認做出上述防止XSS攻擊的設置。
如何確認項目的相關依賴安全?
使用Node.js開發, 很容易出現有成百上千個依賴的情況 。
舉例來說,如果你依賴Express,準確的說這意味著也依賴 27 個其他的模塊 , 手動檢測更新這些模塊不是一個的選擇!
唯一的選擇就是自動的安全的更新你的依賴,你有如下免費或付費的選擇:
-
npm outdated
Node.js 答疑解惑
下面這部分主要給正在準備Node.js 面試者解決一些困惑和棘手的問題。
下面的代碼有什么錯誤?
new Promise((resolve, reject) => {
throw new Error('error')
}).then(console.log)
答案
在 then 后沒有 catch ,沒有捕捉異常。這樣做會造成故障沉默,不會拋出異常。
為了完善這段代碼,我們可以做如下操作:
new Promise((resolve, reject) => {
throw new Error('error')
}).then(console.log).catch(console.error)
如果你調試一個巨大的代碼庫,并且比不知道哪個Promise函數有潛在的問題, 你可以使用 unhandledRejection 這個工具。它將會打印出所有未處理的reject狀態的Promise。
process.on('unhandledRejection', (err) => {
console.log(err)
})
下面的代碼有什么錯誤?
function checkApiKey (apiKeyFromDb, apiKeyReceived) {
if (apiKeyFromDb === apiKeyReceived) {
return true
}
return false
}
答案
在進行數據校驗(security credentials)時,避免任何信息泄露是最重要的。所以,我們要控制數據校驗的執行時間。我們要保證,不管傳過來的數據是什么,我們校驗數據消耗的時間是相同的。如果你做不到這一點,你的程序對 時序攻擊 的抵抗力很低。
為什么會有這種現象?
Node.js使用的V8 JavaScript引擎會從性能角度優化你的代碼。V8引擎比較數據的方式是字節比較, 一旦發現有一個字節不一致, 比較運算就會停止。 因此,攻擊者傳入的password校驗時間越長,說明password正確的部分越多。
為了修復這個問題, 你可以使用npm模塊 cryptiles 。
function checkApiKey (apiKeyFromDb, apiKeyReceived) {
return cryptiles.fixedTimeComparison(apiKeyFromDb, apiKeyReceived)
}
下面這段代碼輸出的是什么?
Promise.resolve(1)
.then((x) => x + 1)
.then((x) => { throw new Error('My Error') })
.catch(() => 1)
.then((x) => x + 1)
.then((x) => console.log(x))
.catch(console.error)
答案
答案是 2 - 像這類問題 我建議面試者說明每一行代碼運行的結果是什么,這樣考官可以知道面試者是如何思考的 , 比如:
-
創建一個Promise對象,輸出 1
-
結果 +1,現在的輸出為 2
-
輸出結果被拋棄,拋出一個error
-
error被丟棄, 返回一個新的value ( 1 )
-
catch進行異常處理,但catch后程序不停止執行, 返回一個信息+1之后的 value ( 2 )
-
value正常輸出
-
value已正常輸出,這一行不會執行
花時間相處一天比技術提問更有效
花至少半天的時間和面試者相處,比考1000道這樣的面試題更有價值
如果你真的這樣做了, 你可以更深入的了解面試者能否適應公司的文化,是否具備契合崗位的技能。
來自:http://www.w3ctech.com/topic/1969