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