【譯】每一個JavaScript 開發者應該瞭解的10個面試題

原文地址javascript

1. 你能說出兩種對 JavaScript 應用開發者而言的編程範式嗎?

JavaScript 是多範式語言,支持 命令式/程序式編程,以及 OOP(面向對象編程)和函數編程。JavaScript 經過原型繼承支持 OOP。html

但願聽到:

  • 原型繼承(還有:原型,OLOO)
  • 函數式編程(還有:閉包,第一等函數,lambadas(匿名函數))

紅牌警告:java

  • 沒有範式概念,沒有提到原型對象或函數編程

瞭解更多:git

2. 什麼是函數編程?

函數編程經過建立數學意義上的方法來避免共享狀態和修改數據來生成程序。Lisp 是最先支持函數編程的,受到 lambda 的啓發。Lisp 和 不少Lisp 家族語言至今仍然使用。程序員

函數式編程是 JavaScript 基本概念。一些常見的函數工具在 ES5 中被添加。github

但願聽到:

  • 純函數
  • 無反作用
  • 單一功能構成
  • 函數式語言:Lisp,ML,Haskell,Erlang,Clojure,Elm,F Sharp,OCaml等等
  • 提到支持函數式編程的特性:一等函數,高階函數,做爲參數/值的函數

紅牌警告:面試

  • 沒有提到純函數和避免反作用
  • 不能提供函數式編程語言的例子
  • 不能識別 JavaScript 中函數式編程的特色

瞭解更多:算法

3. 類繼承和原型繼承的不一樣?

類繼承:繼承來自類(相似藍圖-類的一種描述),建立子類關係:等級分類法。經過構造函數的 new 關鍵字實例化。類繼承可能在 ES6 中不容許使用 class 關鍵字。編程

原型繼承:實例繼承直接來自另外一個對象。實例是經過工廠方法或者 Object.create()實現。實例可能從多個不一樣的對象中組成,容許容易地選擇性繼承。設計模式

在 JavaScript 中,原型繼承比類繼承更加簡單和可擴展。

但願聽到

  • 類:建立緊密耦合或者層次結構分類
  • 原型:提到連接繼承,原型委託,函數繼承,對象組合

紅牌警告:

4. 函數式編程和麪向對象編程的優缺點?

OOP優勢:容易理解對象的基本概念,容易理解方法調用的意義。OOP 傾向使用命令式風格而不是聲明式風格,它讀起來像是直接指示計算機去作什麼。

OOP缺點:OOP 典型地依賴共享狀態。對象和行爲被一個實體跟蹤,也就是說任何數量的無序命令用函數能夠隨機訪問,會致使像競爭條件同樣的不可描述的行爲。

FP優勢:函數式範式,程序員能夠避免共享狀態和反作用,也就消滅了同個資源的多個函數計算引發的bug。這種特性是 point-free風格的可用性。相較於 OOP,函數傾向於快速簡單而容易的重組通用的可複用代碼。

函數式編程更喜歡聲明和聲明風格,它不會一步步指示操做,而是結合要作的事,讓潛在的方法關係如何去作。這爲重構和性能優化留下巨大的空間,甚至容許你替換所有算法只須要一點點代碼改變,這種更有效的方式(好比:內存管理,使用懶惰評估替換有限評估)

利用純函數的計算也很容易在多個處理器或跨分佈式計算集羣中擴展,而沒必要擔憂線程資源衝突,競爭條件等...

FP缺點:過分使用FP功能(如無點樣式和大型組合)可能會下降可讀性,由於生成的代碼一般更抽象地指定,更簡潔,更具體。

與函數式編程相比,更多人熟悉OO和命令式編程,所以即便是函數式編程中常見的習慣也會讓新團隊成員感到困惑。

FP比OOP有更陡峭的學習曲線,由於OOP的普遍流行使得OOP的語言和學習材料變得更具會話性,而FP的語言每每更具學術性和正式性。 FP概念常常被寫成使用來自lambda演算,代數和類別理論的習語和符號,全部這些都須要在這些領域中的先驗知識基礎被理解。

但願聽到

  • 提到共享狀態的問題,競爭相同資源的不一樣事物等等......
  • 意識到FP可以從根本上簡化許多應用程序。
  • 意識到學習曲線的差別。
  • 闡明反作用以及它們如何影響程序的可維護性。
  • 意識到功能強大的代碼庫可能具備陡峭的學習曲線。
  • 意識到與同等的FP代碼庫相比,高度OOP代碼庫能夠很是耐受變化而且很是脆弱。
  • 意識到不可變性致使了一個極易訪問和可延展的程序狀態歷史記錄,容許輕鬆添加諸如無限撤消/重作,倒帶/重放,時間旅行調試等功能。 能夠在任一範例中實現不變性,但共享有狀態對象的擴散使OOP中的實現變得複雜。

紅牌警告:沒法列出一種風格或另外一種風格的缺點-有經驗的人對任何風格都能說出一些限制。

瞭解更多

5. 何時類繼承是一個合適的選擇?

答案永遠不會,或者幾乎從不。 固然永遠不會超過一個級別。 多級類層次結構是反模式。 多年來我一直在發出這個挑戰,我聽過的惟一答案屬於幾種常見的錯誤觀念之一。 更常見的是,挑戰是沉默。

「若是某個功能有時頗有用 有時很危險 若是有更好的選擇 而後老是使用更好的選擇。「 -- Douglas Crockford

但願聽到

  • 不多,幾乎歷來沒有,或從未。
  • 從一個框架基類,如React.Component,單個級別有時是能夠的。
  • 「同意對象組合而不是類繼承。」

瞭解更多

6. 何時原型繼承是一個合適的選擇?

原型繼承有多種類型:

  • 受權(即原型鏈)。
  • 鏈接(即mixins,Object.assign())。
  • 功能性(不要與函數式編程混淆。用於爲私有狀態/封裝建立閉包的函數)。

每種類型的原型繼承都有本身的一組用例,但它們在啓用組合方面一樣有用,它建立了有一個或用一個或能夠作一個的關係而不是使用類繼承建立是一個的關係。

但願聽到

  • 在模塊或函數編程沒有提供明顯解決方案的狀況下。
  • 當須要從多個來源組合對象時。
  • 任什麼時候候你須要繼承。

紅牌警告:

  • 不知道什麼時候使用原型。
  • 沒有意識到mixins或Object.assign()

瞭解更多

7.「同意對象組合超過類繼承」是什麼意思?

這是「設計模式:可重用的面向對象軟件的元素」的引用。 這意味着代碼重用應該經過將較小的功能單元組裝到新對象中而不是從類繼承並建立對象分類來實現。

換句話說,使用can-do,has-a或 uses-a 關係而不是is-a關係。

但願聽到:

  • 避免使用類層次結構。
  • 避免脆弱的基類問題。
  • 避免緊耦合。
  • 避免嚴格的分類(強制是一種新用例最終錯誤的關係)。
  • 避免大猩猩香蕉問題(「你想要的是香蕉,你獲得的是拿着香蕉的大猩猩,以及整個叢林」)。
  • 使代碼更靈活。

紅牌警告:

  • 沒有提到上述任何問題。
  • 未能闡明構成和階級繼承之間的差別,或組成的優點。

8.什麼是雙向數據綁定和單向數據流,它們有何不一樣?

雙向數據綁定意味着 UI 表單被綁定,用來動態地建模數據,使得當 UI 表單改變時,模型數據隨之改變,反之亦然。

單向數據流意味着模型是單一的事實來源。 UI中的更改觸發消息,指示用戶對模型的意圖(或React中的「存儲」)。 只有模型纔有權更改應用程序的狀態。 結果是數據老是在單一方向上流動,這使得它更容易理解。

單向數據流是肯定性的,而雙向綁定可能致使更難以遵循和理解的反作用。

但願聽到:

  • React是單向數據流的新規範示例,所以說起React是一個很好的信號。 Cycle.js是單向數據流的另外一種流行實現。
  • Angular是一種使用雙向綁定的流行框架。

紅牌警告:

  • 不瞭解任何一個意味着什麼。 沒法闡明差別。

9.單一與微服務架構的優缺點是什麼?

單一體系結構意味着您的應用程序是做爲一個有凝聚力的代碼單元編寫的,其組件旨在協同工做,共享相同的內存空間和資源。

微服務架構意味着您的應用程序由許多較小的獨立應用程序組成,這些應用程序可以在本身的內存空間中運行,而且可能在許多不一樣的機器上相互獨立地進行擴展。

單一優勢:單一架構的主要優點在於大多數應用程序一般都有大量的交叉問題,例如日誌記錄,速率限制以及審計跟蹤和DOS保護等安全功能。

當一切都在同一個應用程序中運行時,很容易將組件與這些跨領域的問題聯繫起來。

還有性能優點,由於共享內存訪問比進程間通訊(IPC)更快。

單一架構缺點:隨着應用程序的發展,單一應用程序服務每每會緊密耦合並糾纏在一塊兒,所以很難將服務隔離,例如獨立擴展或代碼可維護性。

單一體系結構也很難理解,由於當您查看特定服務或控制器時,可能存在依賴性,反作用和魔法,這些並不明顯。

微服務優勢:微服務架構一般組織得更好,由於每一個微服務都有很是特定的工做,而且不關心其餘組件的工做。解耦服務也更容易重構和從新配置,以知足不一樣應用程序的需求(例如,同時提供Web客戶端和公共API)。

它們還能夠具備性能優點,具體取決於它們的組織方式,由於它能夠隔離熱服務並將其擴展爲獨立於應用程序的其他部分。

微服務缺點:當您構建新的微服務架構時,您可能會發現許多在設計時沒有預料到的跨領域問題。一個單一的應用程序能夠創建共享的魔術助手或中間件來處理這些跨領域的問題,而不須要太多的努力。

在微服務架構中,您須要爲每一個交叉問題產生單獨模塊的開銷,或者將交叉問題封裝在全部流量路由經過的另外一個服務層中。

最終,即便是單一的體系結構也傾向於經過外部服務層來傳輸流量以解決交叉問題,可是採用單一體系結構,能夠延遲這項工做的成本,直到項目更加成熟爲止。

微服務常常部署在他們本身的虛擬機或容器上,致使VM爭用工做激增。這些任務常常經過容器隊列管理工具自動完成。

但願聽到:

  • 儘管初始成本高於monolthic應用程序,但對微服務的積極態度。意識到微服務從長遠來看每每會表現更好而且規模更大。
  • 關於微服務與單片應用程序的實用性。構建應用程序,以便服務在代碼級別彼此獨立,但在開始時很容易捆綁在一塊兒做爲單個應用程序。微服務開銷成本可能會延遲,直到付出代價變得更加實際。

紅牌警告:

  • 不瞭解單片和微服務架構之間的差別。
  • 對微服務的額外開銷沒有意識到或不切實際。
  • 不知道IPC和網絡通訊對微服務形成的額外性能開銷。
  • 對微服務的缺點太負面了。沒法明確解決單一應用程序的分離方式,以便在時機成熟時將它們輕鬆拆分爲微服務。
  • 低估了獨立可擴展微服務的優點。

10.什麼是異步編程,爲何它在JavaScript中很重要?

同步編程意味着,除了條件和函數調用以外,代碼從上到下依次執行,阻止長時間運行的任務,如網絡請求和磁盤I / O.

異步編程意味着引擎在事件循環中運行。當須要阻塞操做時,將啓動請求,代碼將繼續運行而不會阻塞結果。當響應準備就緒時,將觸發中斷,從而致使運行事件處理程序,控制流繼續執行。經過這種方式,單個程序線程能夠處理許多併發操做。

用戶界面本質上是異步的,而且花費大部分時間等待用戶輸入來中斷事件循環並觸發事件處理程序。

默認狀況下,節點是異步的,這意味着服務器的工做方式大體相同,在循環中等待網絡請求,並在處理第一個請求時接受更多的傳入請求。

這在JavaScript中很重要,由於它很是適合用戶界面代碼,而且很是有利於服務器上的性能。

但願聽到:

  • 瞭解阻塞意味着什麼,以及性能影響。
  • 瞭解事件處理,以及爲何它對UI代碼很重要。

紅牌警告:

  • 不熟悉異步或同步的術語。
  • 沒法表達性能影響或異步代碼與UI代碼之間的關係。

結論

堅持高級主題。若是他們可以回答這些問題,那一般意味着他們有足夠的編程經驗能夠在幾周內得到語言怪癖和語法,即便他們沒有不少JavaScript經驗。

不要基於易於學習的東西(包括經典的CS-101算法或任何類型的拼圖問題)取消候選人資格。

你真正須要知道的是,「這位候選人是否理解如何將應用程序放在一塊兒?」

這就是口語採訪。

在真實的採訪中,我更增強調編碼挑戰和觀察候選人代碼。這些主題在個人「掌握JavaScript面試」系列中有詳細介紹。

pic
相關文章
相關標籤/搜索