摘要:前集回顧我們?cè)陂_(kāi)開(kāi)心心做幾道機(jī)試題中吐了槽,也順勢(shì)展開(kāi)了機(jī)試題之旅,本章我們暫時(shí)壓抑自己的吐槽之心,繼續(xù)就題目前行。其實(shí)和都是構(gòu)造函數(shù),可以直接調(diào)用的。請(qǐng)嘗試完成一個(gè)解析模塊本題考查對(duì)的理解,各部分都是什么意思。
前集回顧
我們?cè)陂_(kāi)開(kāi)心心做幾道JavaScript機(jī)試題 - 01中吐了槽,也順勢(shì)展開(kāi)了機(jī)試題之旅,本章我們暫時(shí)壓抑自己的吐槽之心,繼續(xù)就題目前行。仍然希望對(duì)各位正確認(rèn)識(shí)JavaScript這門(mén)語(yǔ)言,已經(jīng)在面試過(guò)程中遇到這些問(wèn)題時(shí),如何思考!
項(xiàng)目地址:fe-interview
答題之路 11 - 請(qǐng)嘗試完成一個(gè)類似"_.find"的模塊本題主要考查對(duì)數(shù)組的工具函數(shù)的理解、認(rèn)識(shí)。很多朋友習(xí)慣了遇事兒就噴一堆for loop在那惡心人,忽略變量污染、不必要的遍歷操作、含義模糊等問(wèn)題可能帶來(lái)的潛在隱患。對(duì)抱有這種錯(cuò)誤認(rèn)識(shí)的朋友,只要考考這些常見(jiàn)的數(shù)組快捷函數(shù)的實(shí)現(xiàn)原理,原形畢露!^^
答案:
var find = function(array, func) { for (var i = 0; i < array.length; i++) { if (func(array[i], i)) { return array[i]; } } }; module.exports = find;
12 - 請(qǐng)嘗試完成一個(gè)類似"_.findlast"的模塊關(guān)于這一點(diǎn),可以閱讀:Functional programming in Javascript: map, filter and reduce
本題和上題的唯一區(qū)別在于,尋找最后一個(gè)符合條件的指定元素
答案:
var findlast = function(array, func) { for (var i = array.length - 1; i > -1; i--) { if (func(array[i], i)) { return array[i]; } } }; module.exports = findlast;13 - 請(qǐng)嘗試完成一個(gè)查找出現(xiàn)頻率最高元素的模塊
這個(gè)考察的就是對(duì)數(shù)組和literal object的組合使用
答案:
var findmost = function(array, identity) { var occurrence = {}; var most; for (var i = 0; i < array.length; i++) { var item = array[i]; var id = identity ? identity(item) : item; if (!occurrence[id]) { occurrence[id] = {count: 1, raw: item}; } else { occurrence[id].count++; } if (!most || (most !== id && occurrence[id].count > occurrence[most].count)) { most = id; } } return occurrence[most].raw; }; module.exports = findmost;
14 - 請(qǐng)嘗試完成一個(gè)類似"_.difference"的模塊我只用了for loop形式,歡迎更簡(jiǎn)潔寫(xiě)法的PR
本題考查了兩個(gè)數(shù)組的比較,查找第二數(shù)組里沒(méi)有出現(xiàn)的第一個(gè)數(shù)組的元素。其中對(duì)isNaN有比較細(xì)節(jié)的針對(duì)
答案:
var isNaN = Number.isNaN; var difference = function(arr1, arr2) { return arr1.reduce(function(previous, i) { var found = arr2.findIndex(function(j) { return j === i || (isNaN(i) && isNaN(j)); }); return (found < 0 && previous.push(i), previous); }, []); }; module.exports = difference;
15 - 請(qǐng)嘗試完成一個(gè)類似"_.camelCase"的模塊我的答案用了reduce來(lái)獲取最終結(jié)果;如果有朋友對(duì)found < 0 && previous.push(i)不明白,可以看:短路求值。如果對(duì),的使用不了解,那說(shuō)明你沒(méi)看上一章
本題考查對(duì)字符串的各種處理手段
答案:
var camelcase = function(str) { return str.toLowerCase() .replace(/(s+|-+)(.)/g, function(matched, separator, letter) { return letter.toUpperCase(); }); }; module.exports = camelcase;
16 - 請(qǐng)嘗試完成一個(gè)類似"_.times"的模塊我這里用了一套組合技,先toLowerCase,再配合正則表達(dá)式,用一個(gè)replace結(jié)束戰(zhàn)斗
本題考查了對(duì)數(shù)組便捷函數(shù)的理解認(rèn)識(shí),重點(diǎn)在于第二個(gè)參數(shù)是callback,很多人都被String和Boolean給嚇到了,想不通為什么結(jié)果會(huì)是那個(gè)樣子。其實(shí)String和Boolean都是構(gòu)造函數(shù),可以直接調(diào)用的。
答案:
var times = function(n, func) { return Array .apply([], new Array(n)) .map(function(item, index) { return func(index); }); }; module.exports = times;17 - 請(qǐng)嘗試完成一個(gè)類似"_.filter"的模塊
不多說(shuō)了,依舊圍繞數(shù)組。雖然數(shù)組的題比較多,但在面試過(guò)程中可以選擇做答,不必全部都寫(xiě)
答案:
var filter = function(arr, iteratee) { return arr.reduce(function(previous, item) { return (iteratee(item) && previous.push(item), previous); }, []); }; module.exports = filter;
18 - 請(qǐng)嘗試完成一個(gè)簡(jiǎn)單的thunkify函數(shù)我的答案仍然利用了reduce和短路求值
這個(gè)題目對(duì)部分朋友來(lái)說(shuō),可能又過(guò)分了。但相信我,題目不是為了羞辱誰(shuí),而是考察關(guān)于JavaScript,你到底知道多少?函數(shù)式編程不是寫(xiě)Javascript的必需條件,但函數(shù)式表達(dá)的簡(jiǎn)潔性,對(duì)于代碼更深入的理解還是很有幫助的。
關(guān)于什么是thunk?我們先來(lái)看看簡(jiǎn)單定義:“一個(gè)封裝了特定行為使其可以延遲執(zhí)行的函數(shù),通常我們稱之為thunk”,如果希望了解更多關(guān)于thunk的內(nèi)容,看Thoughts On Thunks
答案:
var thunkify = function(func) { return function() { var _this = this; var args = Array.prototype.slice.call(arguments); return function(cb) { try { func.apply(_this, args.concat([cb])); } catch (e) { cb(e); } }; }; }; module.exports = thunkify;
19 - 請(qǐng)嘗試完成一個(gè)類似"_.zipObject"的模塊關(guān)于arguments為什么需要Array.prototype.slice.call(arguments)轉(zhuǎn)換成Array,看arguments
答案:
var zipobject = function(arr1, arr2) { return arr1.reduce(function(previous, key, index) { return (previous[key] = arr2[index], previous); }, {}); }; module.exports = zipobject;
20 - 請(qǐng)嘗試完成一個(gè)類似"_.once"的模塊本題考查數(shù)組合并/壓縮,我用了reduce來(lái)處理。通過(guò)最近這幾題可以看出來(lái),reduce真的能做很多事情哦!
本題考查對(duì)“緩存”的理解,很多人會(huì)被這個(gè)概念唬住,以為又是什么瀏覽器緩存啦,服務(wù)器緩存啦,甚至有人想到了redis、memcached等工具,然后被嚇得半死。其實(shí)沒(méi)那么牛逼,你就是寫(xiě)一個(gè)變量,只要不銷毀,都可以叫緩存。
答案:
var once = function(func) { var value, executed; return function() { var args = Array.prototype.slice.call(arguments); if (!executed) { executed = true; value = func.apply(this, args); return value; } return value; }; }; module.exports = once;
21 - 請(qǐng)嘗試完成一個(gè)類似"_.flatMap"的模塊通過(guò)設(shè)置一個(gè)executed的標(biāo)記來(lái)判斷該函數(shù)是否已經(jīng)執(zhí)行過(guò)了
本題考查對(duì)map的理解。
答案:
var flatmap = function(array, iteratee) { return Array.prototype.concat.apply([], array.map(iteratee)); }; module.exports = flatmap;
22 - 請(qǐng)嘗試完成一個(gè)簡(jiǎn)單的middleware模塊一個(gè)小技巧,對(duì)于二維數(shù)組,利用concat函數(shù)處理,代碼更簡(jiǎn)潔
多少人寫(xiě)了很久的express,結(jié)果搞不清middleware是什么,怎么工作的,如何書(shū)寫(xiě)middleware,怎么使用middleware。這一切都源于對(duì)“中間件”這個(gè)概念的模糊,以及對(duì)express中“中間件”的實(shí)現(xiàn)原理的不解
答案:
var Middleware = function() { this.pool = []; }; Middleware.prototype.use = function(cb) { this.pool.push(cb.bind(this)); }; Middleware.prototype.start = function(cb) { var _this = this; var pullOut = function() { if (_this.pool.length === 0) { return cb.call(_this); } _this.pool.shift()(pullOut); }; pullOut(); }; module.exports = Middleware;
23 - 請(qǐng)嘗試完成一個(gè)URL解析模塊關(guān)于middleware的詳細(xì)介紹,可以看guide。
本題考查對(duì)URl的理解,各部分都是什么意思。在我們過(guò)往的經(jīng)歷中,經(jīng)常發(fā)現(xiàn)候選人搞錯(cuò)一些概念,譬如:什么是query parameter,protocol指的是哪一段,domain又是哪一段,我們常說(shuō)的hash/fragment是什么?分清楚各部分是什么,方便分解這道題
關(guān)于URL,你可能想看到如下圖解:
答案:
var urlparser = function(url) { var result = /^(?:(https?):)//([.-w]+)(?:([/w]+))?(?:?([w=&]+))?$/.exec(url); var parsed = {protocol: result[1], host: result[2]}; if (result[3]) { parsed.path = result[3]; } if (result[4]) { parsed.query = result[4].split("&") .map((query) => query.split("=")) .reduce((params, pairs) => (params[pairs[0]] = pairs[1], params), {}); } return parsed; }; module.exports = urlparser;
24 - 請(qǐng)嘗試完成一個(gè)類似"_.throttle"的模塊這個(gè)答案我用了正則和map、reduce,略顯臃腫。強(qiáng)烈歡迎更優(yōu)解法
這又是個(gè)有故事的題,關(guān)于“節(jié)流閥”,是一種降低計(jì)算頻率的處理。最常見(jiàn)的使用場(chǎng)景:當(dāng)頁(yè)面滾動(dòng)時(shí)計(jì)算某一個(gè)值,相信如果你直白的在onScroll里寫(xiě)了計(jì)算行為后會(huì)發(fā)現(xiàn),每移動(dòng)一個(gè)像素都會(huì)觸發(fā)一次計(jì)算,如果計(jì)算量還有一點(diǎn)大的話,卡不死你。這時(shí)候就用到了節(jié)流閥的技巧。關(guān)于“節(jié)流閥”更多詳情,請(qǐng)看throttle
答案:
var throttle = function(func, wait) { var last, timer; return function() { var args = Array.prototype.slice.call(arguments); var _this = this, now = new Date().getTime(); if (typeof last === "undefined") { last = now; return func.apply(_this, args); } clearTimeout(timer); if (now - last > wait) { last = new Date().getTime(); return func.apply(_this, args); } timer = setTimeout(function() { last = new Date().getTime(); func.apply(_this, args); }, wait + last - now); }; }; module.exports = throttle;25 - 請(qǐng)嘗試完成一個(gè)類似angularjs的依賴注入模塊
用過(guò)AngularJS的朋友肯定都見(jiàn)識(shí)到了“依賴注入”的威力(當(dāng)然如果你是java轉(zhuǎn)型的程序員,更應(yīng)該有體會(huì)),依賴注入是一種解藕手段,我們?cè)趈ava中通常如是介紹:“依賴注入是實(shí)現(xiàn)IoC(控制反轉(zhuǎn))一種方式”。關(guān)于依賴注入,你也可以看手寫(xiě)依賴注入
答案:
var Di = function() { this.instanceStore = {}; }; Di.prototype.register = function(name, inst) { this.instanceStore[name] = inst; }; Di.prototype.run = function(arr) { var _this = this, lastIndex = arr.length - 1; arr[lastIndex].apply(null, arr.slice(0, lastIndex) .map(function(name) { var Inst = _this.instanceStore[name]; if (!Inst) { throw new Error("You are expecting a non-exist instance"); } return typeof Inst === "function" ? new Inst() : Inst; })); }; module.exports = Di;
注意我在run實(shí)現(xiàn)里的typeof Inst === "function" ? new Inst() : Inst;使得如果注冊(cè)的是一個(gè)構(gòu)造函數(shù),那么每次使用都會(huì)注入一個(gè)新的實(shí)例,這和AngularJS里使用單例的策略不同,這里留下一個(gè)問(wèn)題,如果我希望使用單例策略,答案要做如何修改?
這是余下的15個(gè)題目,隨時(shí)歡迎PR,歡迎指正,歡迎優(yōu)化。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/79879.html
摘要:碰到這種面試官,你只有是個(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) 憶苦 面試第一苦,面試官的土 ...
摘要:學(xué)堂碼匠計(jì)時(shí)器的第一個(gè)參數(shù),包含幾種不同的書(shū)寫(xiě)方法,可以是函數(shù)名,匿名函數(shù),代碼字符串,還有一些面試題當(dāng)中會(huì)出現(xiàn)函數(shù)調(diào)用的書(shū)寫(xiě)方式。 HTML5學(xué)堂-碼匠:計(jì)時(shí)器的第一個(gè)參數(shù),包含幾種不同的書(shū)寫(xiě)方法,可以是函數(shù)名,匿名函數(shù),JS代碼字符串,還有一些面試題當(dāng)中會(huì)出現(xiàn)函數(shù)調(diào)用的書(shū)寫(xiě)方式。 那么,這些不同的書(shū)寫(xiě)方法分別表示什么呢?在計(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ù)被...
摘要:年開(kāi)始的前三個(gè)學(xué)期有篇的產(chǎn)出。從技術(shù)角度來(lái)看,編程節(jié)奏加緊。十年文學(xué),我等你。寫(xiě)給即將二十歲的你此你非彼你,寫(xiě)給一直伴我的你。巧合遇到你后的這段光陰,無(wú)比的充實(shí)與激情飽滿。編程技術(shù)獨(dú)立的挑戰(zhàn)鼓勵(lì)你。希望足以承擔(dān)我愛(ài)你。 showImg(https://segmentfault.com/img/remote/1460000011417994); 這倆年通過(guò)體驗(yàn)博客園、常駐簡(jiǎn)書(shū)、甚至搭建靜...
閱讀 3054·2021-11-23 09:51
閱讀 3834·2021-11-22 15:29
閱讀 3294·2021-10-08 10:05
閱讀 1620·2021-09-22 15:20
閱讀 1042·2019-08-30 15:56
閱讀 1136·2019-08-30 15:54
閱讀 788·2019-08-26 11:54
閱讀 2690·2019-08-26 11:32