咱们在开开心心作几道JavaScript机试题 - 01中吐了槽,也顺势展开了机试题之旅,本章咱们暂时压抑本身的吐槽之心,继续就题目前行。仍然但愿对各位正确认识JavaScript
这门语言,已经在面试过程当中遇到这些问题时,如何思考!javascript
项目地址:fe-interviewjava
本题主要考查对数组的工具函数的理解、认识。不少朋友习惯了遇事儿就喷一堆
for loop
在那恶心人,忽略变量污染、没必要要的遍历操做、含义模糊等问题可能带来的潜在隐患。对抱有这种错误认识的朋友,只要考考这些常见的数组快捷函数的实现原理,原形毕露!^^git
答案:程序员
var find = function(array, func) { for (var i = 0; i < array.length; i++) { if (func(array[i], i)) { return array[i]; } } }; module.exports = find;
关于这一点,能够阅读:Functional programming in Javascript: map, filter and reduceangularjs
本题和上题的惟一区别在于,寻找最后一个符合条件的指定元素github
答案:面试
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;
这个考察的就是对数组和
literal object
的组合使用正则表达式
答案:redis
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;
我只用了
for loop
形式,欢迎更简洁写法的PRexpress
本题考查了两个数组的比较,查找第二数组里没有出现的第一个数组的元素。其中对
isNaN
有比较细节的针对
答案:
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;
个人答案用了
reduce
来获取最终结果;若是有朋友对found < 0 && previous.push(i)
不明白,能够看:短路求值。若是对,
的使用不了解,那说明你没看上一章
本题考查对字符串的各类处理手段
答案:
var camelcase = function(str) { return str.toLowerCase() .replace(/(\s+|-+)(.)/g, function(matched, separator, letter) { return letter.toUpperCase(); }); }; module.exports = camelcase;
我这里用了一套组合技,先
toLowerCase
,再配合正则表达式,用一个replace
结束战斗
本题考查了对数组便捷函数的理解认识,重点在于第二个参数是
callback
,不少人都被String
和Boolean
给吓到了,想不通为何结果会是那个样子。其实String和Boolean都是构造函数,能够直接调用的。
答案:
var times = function(n, func) { return Array .apply([], new Array(n)) .map(function(item, index) { return func(index); }); }; module.exports = times;
很少说了,依旧围绕数组。虽然数组的题比较多,但在面试过程当中能够选择作答,没必要所有都写
答案:
var filter = function(arr, iteratee) { return arr.reduce(function(previous, item) { return (iteratee(item) && previous.push(item), previous); }, []); }; module.exports = filter;
个人答案仍然利用了
reduce
和短路求值
这个题目对部分朋友来讲,可能又过度了。但相信我,题目不是为了羞辱谁,而是考察关于
JavaScript
,你到底知道多少?函数式编程不是写Javascript
的必需条件,但函数式表达的简洁性,对于代码更深刻的理解仍是颇有帮助的。
关于什么是thunk
?咱们先来看看简单定义:“一个封装了特定行为使其能够延迟执行的函数,一般咱们称之为thunk
”,若是但愿了解更多关于thunk
的内容,看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;
关于
arguments
为何须要Array.prototype.slice.call(arguments)
转换成Array
,看arguments
答案:
var zipobject = function(arr1, arr2) { return arr1.reduce(function(previous, key, index) { return (previous[key] = arr2[index], previous); }, {}); }; module.exports = zipobject;
本题考查数组合并/压缩,我用了
reduce
来处理。经过最近这几题能够看出来,reduce
真的能作不少事情哦!
本题考查对“缓存”的理解,不少人会被这个概念唬住,觉得又是什么浏览器缓存啦,服务器缓存啦,甚至有人想到了
redis
、memcached
等工具,而后被吓得半死。其实没那么牛逼,你就是写一个变量,只要不销毁,均可以叫缓存。
答案:
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;
经过设置一个
executed
的标记来判断该函数是否已经执行过了
本题考查对
map
的理解。
答案:
var flatmap = function(array, iteratee) { return Array.prototype.concat.apply([], array.map(iteratee)); }; module.exports = flatmap;
一个小技巧,对于二维数组,利用
concat
函数处理,代码更简洁
多少人写了好久的
express
,结果搞不清middleware
是什么,怎么工做的,如何书写middleware
,怎么使用middleware
。这一切都源于对“中间件”这个概念的模糊,以及对express
中“中间件”的实现原理的不解
答案:
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;
关于
middleware
的详细介绍,能够看guide。
本题考查对
URl
的理解,各部分都是什么意思。在咱们过往的经历中,常常发现候选人搞错一些概念,譬如:什么是query parameter
,protocol
指的是哪一段,domain
又是哪一段,咱们常说的hash/fragment
是什么?分清楚各部分是什么,方便分解这道题
关于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;
这个答案我用了正则和
map
、reduce
,略显臃肿。强烈欢迎更优解法
这又是个有故事的题,关于“节流阀”,是一种下降计算频率的处理。最多见的使用场景:当页面滚动时计算某一个值,相信若是你直白的在
onScroll
里写了计算行为后会发现,每移动一个像素都会触发一次计算,若是计算量还有一点大的话,卡不死你。这时候就用到了节流阀
的技巧。关于“节流阀”更多详情,请看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;
用过
AngularJS
的朋友确定都见识到了“依赖注入”的威力(固然若是你是java转型的程序员,更应该有体会),依赖注入是一种解藕手段,咱们在java中一般如是介绍:“依赖注入是实现IoC
(控制反转)一种方式”。关于依赖注入,你也能够看手写依赖注入
答案:
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
实现里的typeof Inst === 'function' ? new Inst() : Inst;
使得若是注册的是一个构造函数,那么每次使用都会注入一个新的实例,这和AngularJS
里使用单例的策略不一样,这里留下一个问题,若是我但愿使用单例策略,答案要作如何修改?
这是余下的15个题目,随时欢迎PR,欢迎指正,欢迎优化。