摘要:碰到這種面試官,你只有是個題霸,再加上眼緣夠才能順利入圍。只要按照我題目的思路,甚至打出來測試用例看看,就能實現這個題目了。答案根據的,對答案做出修正。另我的答案絕不敢稱最佳,隨時歡迎優化修正。但了解總歸是好的。
我們在長期的面試過程中,經歷了種種苦不堪言,不訴苦感覺不過癮(我盡量控制),然后主要聊聊常見JavaScript面試題的解法,以及面試注意事項
憶苦面試第一苦,面試官的土 - 有些面試官自己就非常不專業,詞不達意、不知所云,這類面試常常表現為網上搜題,面試時照本宣科,只會比較候選人的答案最終的結果,自動忽略候選人對題目的見解以及解題思路。碰到這種面試官,你只有是個題霸,再加上眼緣夠才能順利入圍。苦!
面試第二苦,候選人的虎 - 有些候選人的表現好像菜市場的大媽,表述永遠走“樸實無華”路線,譬如:說個iife,他一定要說“就是那個小括號包裹,里面寫一個函數,最后再來一對括號,函數里面寫一堆閉包的寫法”, 注意,這里面一定會說“里面寫閉包”這句話,以彰顯專業性,殊不知從一開始就露怯了。苦!
面試第三苦,雙方都在賭 - 面試官自說自話,候選人答非所問,場面一片歡愉,結果不言而喻!
面試,是一個非常需要認真思考的事情,無論面試官還是候選人,選什么人、怎么選;面什么公司、什么崗位、題目不會該如何作答?不思考胡說一通,那不苦才有鬼!
通常面試都是聊天、筆試,機試環節常常短缺。但捫心自問,我們真的需要程序員熟背所有Javascript API么?我們真的需要程序員熟背所有Web API么?我們真的需要程序員瞬間給出“某某網站慢的完全優化方案”么?
覺醒我在想,前兩問完全可以Google,考察的重點不在于候選人能默寫多少API,而在于當他記不住的時候,是否知道去哪里查!關于后一問,瞬間給出完全優化方案?別鬧了,你自己面對這個產品那么些年也沒搞定,別人在沒有任何了解的情況下,看一眼(有時連看都沒看著,僅聽描述)就能給出方案,那你們公司養的都是廢物吧?這里考察的重點應該是思路,候選人會從哪幾個方面思考問題的癥結所在,至于是否能給出解決方案,我覺得可能性不大,一個產品涉及的東西太多,離開背景細節,給出解決方案的可能性不大。
缺少上機測試會有什么問題?(其實沒什么大差錯),不過可能會損失一些“嘴笨”的實踐派干活能手,他們信奉“能動手就別BB”,這類人通常在與面試官face 2 face的“聊天”中不能討得面試官歡心,但他們真心能寫的一手好碼,可惜沒機會展示,也是苦!
于是我覺得大家應該互相給對方一個機會,談談我自己用的一套機試題目fe-interview,以及作為面試官希望了解的候選人關于Javascript方面的能力的看法。
以下是該機試題目的開始界面(retro風格),通過鍵盤光標上/下鍵選擇題目,按回車鍵確認選中
雖然寫了“算法考核”,但其實沒什么算法題,這也算是標題黨吧^^
確認選中后,會出現如下選擇器,候選人可以再次上/下鍵選擇"查看題目描述"、“查看測試用例”、“檢驗答題結果”
"查看測試用例"的目的是幫助候選人,通過查看測試用例的代碼來改進自己的題目解答。
該測試工具需要本地安裝,詳情請看:安裝/使用手冊
簡單了解測試工具之后,我們就可以開始愉快的答題了
最后再來回顧一下機試目標:機試的目的不是為了讓候選人在指定時間內完成一個完美無瑕的功能,那是高考!我們期待的是通過不同的題目,考察候選人的基本功、編碼能力、思考方法。。。,通過這些綜合指標,判斷該候選人是否一個你期望的JavaScript工程師
下面讓我們一起走上答題之路
答題之路 01 - 請嘗試刪除數組的指定下標對應的元素題目非常簡單,完成一個可以刪除數組指定下標對應元素的函數
答案:
var removeArray = function(arr, index) { arr.splice(index, 1); }; module.exports = removeArray;
02 - 請嘗試完成可以判斷傳入變量是否為string的模塊真心沒什么花哨的地方,這個題目不涉及任何高深的知識。旨在考察候選人對基礎API的熟練程度,關于splice你可能想知道更多
答案:
var isString = function(value) { return Object.prototype.toString.call(value) === "[object String]"; }; module.exports = isString;
03 - 請嘗試完成一個簡單的使柯里化(currying)模塊這里考察的重點是new String("hello")到底是個什么東西?至于我給的答案用了Object.prototype.toString方法,我可以負責任的告訴你,這個做法是有風險的,因為該方法的實現由平臺提供,意思是:不同的JavaScript執行引擎實現可能不同,所以結果并不能保證。還是那句話,結果不是最重要的,解題思路,看清本質最為關鍵,也是最重要的能力。當然關于Object.prototype.toString,你也可能想知道更多
這題可能對一些同學來講有點過了,但相信我,我的測試用例并不{{BANNED}},你完全不必寫出一個“完美”的柯里化。只要按照我題目的思路,甚至打出來測試用例看看,就能實現這個題目了。
首先為了普法,還是先簡單介紹下什么是“柯里化”,說白了柯里化也是一個函數。假設我們有函數A經過柯里化函數處理過后,A就被賦予了一種能夠被部分執行的能力!這話說的聽不懂了是吧?我們來看個例子:
//假設我們有個add函數,她接受兩個參數a和b;并返回二者之和 var add = function(a, b){ return a + b; };
簡單吧?那么問題來了,如果我現在只給了你一個參數a,另一個參數我想過會兒再給你,怎么辦?傳統思維是那就過一會再調用add唄!這當然沒錯!但是憑借柯里化,我們有另外一種思路使得以下成為可能:
var add3 = add(3);//執行了一半 setTimeout(function(){ console.log(add3(5));//這里拿到了另一半參數5,再計算最終結果 }, 5000);
我這里不會大篇幅講柯里化有多牛逼的好處,當然如果你有興趣,可以看Why Curry Helps
答案:
var currying = function(func) { var len = func.length;//獲取一個函數形參的個數 var getCurry = function(params) { return function() { //參數拼接 var next = params.concat(Array.prototype.slice.call(arguments)); //持續接收的參數已經滿足當初原始函數的形參個數,執行原始函數,返回結果 if (len - next.length <= 0) { return func.apply(this, next); } //不滿足個數,將已經獲取的參數繼續遞歸 return getCurry(next); }; }; return getCurry([]); }; module.exports = currying;04 - 請嘗試完成一個"duplicate(重復)"的模塊
如此簡單的題目,我想考察的依舊是Array的內置API,不記得不要緊,我是允許上網查的(誰沒有個記不住的時候)。但你要是玩出花來,譬如有人寫了幾十行的方法,這個我就有點懵了。
答案:
var duplicate = function(array) { return array.concat(array); }; module.exports = duplicate;
05 - 請嘗試完成可以淺拷貝的模塊其實concat足矣。關于concat,更多詳情
“淺拷貝”,顧名思義,對于引用類型的數據,只拷貝其引用,也就是題目中copied[0].name = "world";之后,原先的value也被改了。
答案:
var shallowCopy = function(value) { return Object.assign(new (Object.getPrototypeOf(value).constructor)(), value); }; module.exports = shallowCopy;
06 - 請嘗試完成一個類似"_.flatten"的模塊根據@Tommy Troy Lin的PR,對答案做出修正。原因是我在題目里提到了對Object的支持,而我的答案以及題目考核的最初想法都沒有考慮Object的情況(記憶錯亂了)。再次感謝指正
關于Object.assign,不明白的同學看這里assign;對于Object.getPrototypeOf不清楚的同學,看getPrototypeOf
如何“拍平”一個多維數組,這是好玩意兒
答案:
var flatten = function(array) { return array.reduce(function(previous, i) { if (Object.prototype.toString.call(i) !== "[object Array]") { return (previous.push(i), previous); } return (Array.prototype.push.apply(previous, flatten(i)), previous); }, []); }; module.exports = flatten;
07 - 請嘗試完成一個"繼承"的實現本題在“遞歸”這個問題上,做了一些考慮。我想考查的主要是面對多維數組,候選人將如何處理!
我的答案用了reduce方法,如果你還沒用過,你需要看reduce。另外可能有人對于逗號的使用有疑惑,可以看Comma_Operator。另:我的答案絕不敢稱最佳,隨時歡迎優化/修正。
考查ES5時代基于prototype的類繼承實現,如果你心系ES6,這個可以忽略。但了解總歸是好的。
答案:
Parent
var Parent = function(name) { this.name = name; }; Parent.prototype.getName = function() { return this.name; }; module.exports = Parent;
Son
var Parent = require("./Parent"); var Son = function(parentName, name) { Parent.call(this, parentName); this.childName = name; }; Son.prototype = Object.create(Parent.prototype); Son.prototype.constructor = Son; Son.prototype.getChildName = function() { return this.childName; }; module.exports = Son;
08 - 請嘗試完成一個類似"_.map"的模塊以上算是基本繼承概念,如果不清楚的,看看這篇教程OOP in JS, Part 2 : Inheritance。你也可能對與Object.create的使用感到疑惑,那么請看create
接受@我仍舊在這里 建議,把new Parent()換成了Object.create(Parent.prototype)
通過長期觀察我們發現一個現象,就是在ES2015甚至ES2016大行其道的今天,仍然有人打著“我要兼容IE8”的旗號拒絕進步。自ES5開始就有的Array新方法map, forEach、reduce常常有人搞不懂,也不會用,更不知道干嘛用的。往往一言不和就吐一堆for循環出來惡心人!本題主要就是甄別候選人是否自己口中所說的那樣“積極、愛學習”,如果連ES5就有的常見方法都不會,還是“積極、愛學習”,那我只能呵呵了!
答案:
var map = function(arr, func, ctx) { var array = []; arr.forEach(function(i, index) { array.push(func.call(ctx, i, index, arr)); }); return array; }; module.exports = map;
09 - 請嘗試完成一個類似"_.reduce"的模塊這里解法也是多種多樣,無所謂用哪一種,關鍵在于是否真正理解了什么是map?文檔看:map
最為ES5里Array的幾個好兄弟,reduce的用法/原理我想還是應該掌握的。
答案:
var reduce = function(arr, func, initialValue) { var base = typeof initialValue === "undefined" ? arr[0] : initialValue; var stepForward = typeof initialValue === "undefined" ? 1 : 0; var startPoint = stepForward; arr .slice(startPoint) .forEach(function(val, index) { base = func(base, val, index + stepForward, arr); }); return base; }; module.exports = reduce;
10 - 請嘗試完成一個獲取原始數據值的模塊仍然不理解reduce工作原理的,看Understanding Eloquent Javascript"s Reduce function
永遠獲取傳入參數的最終執行結果,如果是函數的,就執行、執行、再執行,直到拿到了最終的非函數結果。
答案:
var value = function(anything) { if (Object.prototype.toString.call(anything) !== "[object Function]") { return anything; } return value(anything()); }; module.exports = value;
今天實在寫不動了,先來10題試試反響,如果大家覺得還有用,我再繼續補后面的題目。當然也歡迎直接Github給我PR,star那自然是最好的啦^^
欲知后事,請看下集
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/79827.html
摘要:前集回顧我們在開開心心做幾道機試題中吐了槽,也順勢展開了機試題之旅,本章我們暫時壓抑自己的吐槽之心,繼續就題目前行。其實和都是構造函數,可以直接調用的。請嘗試完成一個解析模塊本題考查對的理解,各部分都是什么意思。 前集回顧 我們在開開心心做幾道JavaScript機試題 - 01中吐了槽,也順勢展開了機試題之旅,本章我們暫時壓抑自己的吐槽之心,繼續就題目前行。仍然希望對各位正確認識Ja...
摘要:學堂碼匠計時器的第一個參數,包含幾種不同的書寫方法,可以是函數名,匿名函數,代碼字符串,還有一些面試題當中會出現函數調用的書寫方式。 HTML5學堂-碼匠:計時器的第一個參數,包含幾種不同的書寫方法,可以是函數名,匿名函數,JS代碼字符串,還有一些面試題當中會出現函數調用的書寫方式。 那么,這些不同的書寫方法分別表示什么呢?在計時器中出現的第一個參數,作用域又是在哪里創建的? 計時器第...
摘要:對象方法中的當以對象里的方法的方式調用函數時,它們的是調用該函數的對象。注意,在何處或者如何定義調用函數完全不會影響到的行為。在這次執行期間,函數中的將指向。 原文鏈接 與其他語言相比,函數的this關鍵字在JavaScript中的行為略有不同。并且它在嚴格模式和非嚴格模式之間也有一些區別。 在絕大多數情況下,函數的調用方式決定了this的值。this不能在執行期間被賦值,在每次函數被...
閱讀 1260·2021-11-23 09:51
閱讀 1627·2021-11-16 11:45
閱讀 4013·2021-10-09 09:43
閱讀 2681·2021-07-22 16:47
閱讀 944·2019-08-27 10:55
閱讀 3449·2019-08-26 17:40
閱讀 3083·2019-08-26 11:39
閱讀 3228·2019-08-23 18:39