好吧,我認可太標題黨了,這篇文章是經過一道前端面試題引出的純技術討論。我先要矯情無比的從中外詩歌提及。javascript
傳統的佛學經典裏,被世人熟知的有這樣一句話:「一花一世界,一葉一菩提,一木一浮生,一草一天堂,一砂一極樂,一方一淨土,一笑一塵緣,一念一清靜。」前端
昔時佛祖拈花,唯迦葉微笑,既而步往極樂。從一朵花中便能悟出整個世界,得昇天堂,佛祖就是佛祖,誰人能有這樣的境界。java
同時,早在18世紀,英國偉大的浪漫主義詩人Black名爲《天真的暗示》的詩中,也相似寫道:"To see a world in a grain of sand, and a heaven in a wild flower",一顆沙裏一個世界,一朵野花一座天堂。git
轉念,雖卑爲碼農,咱們寫出的代碼,卻彰顯了功力:菜鳥和大神之間的差距,每每工程線上卑微的幾行代碼,便有天壤之差。github
一道系列面試題,在JS知識體系中雖滄海一粟,但考察點充分評判面試者的能力。
管中窺豹,期待讀者有不一樣想法與我討論。面試
題目是我在《effective javascript》一書中提取的。這一星期陸陸續續面試了很多於10我的,其中不乏工做履歷突出的候選者。
可是很遺憾沒有能徹底在較短期內有較高質量的回答。數組
這道題能夠分爲先後兩個部分,第一部分很簡單,通常有必定JS OOP基礎的候選者應該均可以答好:微信
一個社交網絡有一組成員(member),每一個成員有一個本身的名字,和存儲其朋友信息的列表。請實現這樣一個Member構造器。網絡
正確答案不難理解:frontend
function Member (name) {
this.name = name;
this.friends = [];
}複製代碼
是否是很是簡單。它的典型錯誤包括可是不限於:
function Member (name) {
this.name = name;
}
Member.prototype.friends = [];複製代碼
關於方法和屬性是應該放在原型上,仍是構造函數中,若是您不明白的話,是時候補一補原型原型鏈的知識了。推薦給你們看一下個人同事顏海鏡早在3年前的一篇文章。
一樣,這道題上我會順便考察一下面試者對JS中變量的存儲方式,包括堆棧存儲的不一樣狀況和引用賦值的掌握狀況。
以上是對JS基礎的考察,可是在這道題目的基礎上,我進行了更深一步提問。但願對候選者的臨場思惟、JS基礎甚至一些設計能力,又更進一步認識。
我要實現一個帶環社交網絡(社交圈):
var a = new Member('Alice');
var b = new Member('Bob');
var c = new Member('Carol');
var d = new Member('Dieter');
var e = new Member('Eli');
var f = new Member('Fatima');
a.friends.push(b);
b.friends.push(c);
c.friends.push(e);
d.friends.push(b);
e.friends.push(d, f);複製代碼
這種狀況下,須要實現一個inNetwork方法,判斷某目標成員是否在另外一個對象成員的社交圈中。規定:順着社交鏈能找到目標成員,就認爲在社交圈中。不然,不在其社交圈。
若是剛接觸到這樣的題目,尤爲是在面試現場,做爲面試者極可能會慌亂一下。這時候,須要作的就是先準確分析題目。
根據題目,畫出符合上述題目代碼的實例化網絡:
接下來思考,搜索意味着須要遍歷整個社交網絡。咱們應該:
1)以單個根節點開始,
2)而後添加發現的節點,
3)移除訪問過的節點,防止死環
最終實現:
Member.prototype.inNetwork = function (target) {
var visited = {};
var worklist = [this]; // 用於存放社交鏈上的個體信息,初始時以「本身」做爲根節點
while (worklist.length > 0) {
// 將worklist裏的最後一項成員刪除並取出
var member = worklist.pop();
// 若是存在環的狀況,須要避免重複訪問
if (member.name in visited) {
continue;
}
visited[member.name] = member;
if (member === target) {
return true;
}
// 將當前成員的朋友列表加入worklist當中,他們都在根節點的社交鏈上
member.friends.forEach(function(friend) {
worklist.push(friend);
})
}
return false;
}複製代碼
我在代碼中加上了註釋,若是您還不明白也沒有關係。建議去跑一下程序,進行debugger和console,嘗試去理解。
測試:
a.inNetwork(f) // true
f.inNetwork(a) //false複製代碼
哈哈,果真Alice能經過朋友圈查找到Fatima,而Fatima卻不能反向找到Alice!固然,這樣我認爲是違反人類社會常識的。可是,誰讓他是題目呢?
一道簡單的題卻覆蓋了不少知識點,好比:while循環中的流程控制(continue),數組的基本方法(pop,forEach,push),for...in等等。
它的典型錯誤包括可是不限於:使用對象承載worklist,而後用for...in循環遍歷worklist。
這樣作的問題在於:for...in循環並無要求枚舉對象的修改與當前循環保持一致。事實上,標準規範規定了:
「若是被枚舉對象在枚舉期間添加了新的屬性,那麼枚舉期間並不能保證新添加的屬性可以訪問」。
這道題考察了面試者包括JS OOP在內的多項基礎,尤爲是後半道考察了候選者的思惟能力、反應能力。若是讀者不能理解,歡迎留言問我。或者去查閱:《effective javascript》一書。
扯回原詩句,談一下感悟,在天體的轉動和歲月的輪迴中,咱們分明的感覺到每個個體所擁有生命週期的單薄無力,在宏大的宇宙觀中恐怕眇小不及滄海一粟。詩句的後半句拿出來共勉:「Hold infinity in the palm of your hand, and eternity in an hour 把無限放在你的手上,永恆在一剎那裏收藏」。
在前端快速迭代發展的學習中,做爲初學者,每每面對浩瀚的知識海洋望洋興嘆,此時基礎即是那可以收藏「永恆和無限」的潘多拉魔盒。
本文對你有幫助?歡迎掃碼加入前端學習小組微信羣: