许多注重技术的互联网公司在工程师招聘的技术面环节都会要求提名人在纸上写代码(后文用“纸上代码”代称),面试官想经过这种办法调查哪些点?提名人该留意哪些点?本文根据美团早几年常用的一道区分度比较高的面试题来做详细解说,这道题我现在还在用,面过的人许多,可是纸上代码环节能答到满分的少之又少。
本文为《BETWAY登录面试》系列文章的第 3 篇,前 2 篇链接在这儿:闭包篇、DOM 篇。
为什么要纸上代码?
纸上代码(也有或许在白板上写)的做法乍看起来不行人道,但假如你是团队的 Leader,什么样的人能更好的融入团队?假如你是老板,你乐意掏钱养什么样的职工?纸上代码的根本意图便是调查提名人是否具有出活的才干,顺便调查提名人是否思路灵敏、常识面广。
纸上代码环节怎样调查出活的才干?首先是出活的速度,没有编码根本功的人快速出活的概率是极低的,100% 依靠百度或许 IDE 主动完结才干完结根本使命的工程师算不上合格的工程师;其次是出活的质量,经过编码进程能够了解提名人经过学习和练习堆集下来的编码风格、考虑办法等;此外,经过纸上代码也能够了解提名人承受和完结使命的主动性,是不是乐意承受任何团队需求完结的使命。
某种程度上说,纸上代码进程便是今后作业的缩影,既然如此,面试时排练下不是挺好的么?
纸上代码该怎样做?
一般来说,纸上代码都不会问特别杂乱的问题,很或许仅仅完结十分通用的需求,处理实践遇到的事务问题,或许用某种言语完结某种算法。在提出实践事务问题的代码题之前,面试官会经过部分前置问题了解提名人对处理事务问题所需常识的把握程度,并在必要的状况下给出常识弥补。
比方,前文说到的那道美团的代码题是:不凭借第三方库的条件下,用 JS 编写函数从下面的 URL 串中解分出一切的参数:
https://www.domain.com/?user=anonymous&id=123&id=456&city=%E5%8C%97%E4%BA%AC&d&enabled
希望的回来成果格局如下:
- {
- user: 'anonymous',
- id: [123, 456], // 重复呈现的 key 要拼装成数组,能被转成数字的就转成数字类型
- city: '北京', // 中文
- enabled: true, // 未指定值的 key 约好值为 true
- }
关于运用过 Node.js 中的 querystring 或许社区中的 qs、uri.js 模块的同学对这个或许再了解不过了,而那些不熟 HTTP GET 恳求参数带着办法的提名人也不必着急,由于这种状况下面试官会解说 URL 参数的结构规矩,至于对网络常识的把握程度,是别的的注重点了。实践操作中,在我拿出这个问题之前,现已跟提名人聊了比较多的 HTTP 话题了。
1. 开端着手前
适当份额的提名人拿到问题,会当即提笔开端写代码,这是面试官最不肯看到的,和校园考试的填空题不同,纸上代码作为归纳本质环节,面试官希望看到全面的你,假如作业中也是这样拿到需求不分青红皂白就开搞,终究的成果或许常常是得不偿失。
谋定而后动,着手前一定要搞清楚问题。怎样才算是把问题搞清楚了?要清楚输入的特征,是否会呈现各种古怪的输入(脑子里边有这根弦的人一般不会差,可是面试官会当心求证,看看你能想到哪些);要清楚对处理办法的其他约束条件,比方时刻杂乱度,空间杂乱度。而搞清楚问题的办法便是诘问面试官,比方,针对上面的代码,能够诘问的问题:
未指定值的 key 是否会重复呈现?假如重复呈现该怎样处理?
数字中只包括整数?是否包括浮点数?科学计数法?
对代码的功用要求是怎样的?提出这个问题的时分,提名人心中或许现已有多重办法了。
就如同在实践作业中接需求的时分,需求知道需求的鸿沟,各种或许的特殊状况,协作方关于排期的希望,需求中各个关键优先级界定,从决策论的视点来看,把握更充沛的信息,才干让你对技术杂乱度、需求排期有更合理的预估,防止在做到一半或做完的时分发现与实践需求不符。
搞清楚问题之后,相信你心中现已有了根本思路,不过着手的机遇还没到,你应该把思路介绍给面试官,供认自己是否自己是否疏忽了某些关键,这也是展现交流才干的好时机,知道什么是有用交流的同学应该能了解接纳信息后向信源供认的重要性。
需求留意的是,质疑精力激烈的同学在着手前会提许多问题,看起来是好事情,但假如仅仅停留在质疑层面,不乐意着手,留给面试官的形象就会是你是个挑活的人。在我的招聘阅历中就曾遇到过由于觉得代码题要处理的问题没有任何含义而回绝写代码的人,我没办法只能谦让的把他送走。由于,对不认同事物的宽恕程度很低的人很简略给团队带来坏滋味。
确认了问题鸿沟和处理问题的思路,接下来你能够开端着手编码。
2. 编码进程中
处理 QueryString 参数解析问题的思路有好多种,比方字符串线性遍历法、字符串分割法、正则表达式办法,在我面过的人中,用字符串分割法的人最多,下面的评论咱们就环绕这种办法打开。线性遍历法的完结能够参阅 Node.js 内置的 querystring 模块。
编码进程中需求考虑哪些要素呢?下面用详细的例子来剖析,比方我常常拿到这样的成果代码:
- function parse(str) {
- var obj = {};
- var ary = str.split('&');
- for (var i = 0; i < ary.length; i++) {
- var tmp = ary[i].split('=');
- if (!obj[tmp[0]]) {
- obj[tmp[0]] = tmp[1] || true;
- } else {
- var tmp2 = [obj[tmp[0]], tmp[1] || true];
- obj[tmp[0]] = tmp2;
- }
- }
- return obj;
- }
看到这样的代码,相信你也现已皱起了眉头,这段代码在表层、逻辑谨慎性、强健性都存在问题,更严峻的是没有满意数值型参数的需求,透过这段代码也能够揣度提名人大概率是个不善于学习的人。
表层问题
表层问题主要指代码可读性,点评规范是:是否看起来简练?是否看一眼就能了解它在做什么?上面的成果有哪些详细的表层问题呢?
可读性方面,假如你想在循环体里边要追寻解析到的键值对,需求在大脑中坚持映射 key = tmp[0], value = tmp[1];
变量命名方面,比方 tmp 的屡次运用,ary 代称数组尽管也能够,社区顶用 arr 比较多,变量命名多用约好俗成的会更好;
做了表层改善的参阅代码如下:
- function parse(str) {
- var paramObj = {};
- var paramArr = str.split('&');
- for (var i = 0; i < paramArr.length; i++) {
- var tmp = paramArr[i].split('=');
- // 把 key 和 value 独自拆开来,会明晰许多
- var key = tmp[0];
- var value = tmp[1] || true;
- if (!paramObj[key]) {
- paramObj[key] = value;
- } else {
- var newValue = [paramObj[key], value];
- paramObj[key] = newValue;
- }
- }
- return paramObj;
- }
逻辑问题
逻辑不谨慎的代码在不同输入状况下的成果是不稳定的,详细表现为:
obj[tmp[0]] 不能正确判别成果中是否现已存在某个 key,由于或许呈现值为 0 的状况;
上面的代码不能正确处理重复呈现 2 次以上的 key,部分提名人到面试完毕还没想了解为啥;
依照规范,URL 中的的各种参数需求在 encode 之后拼接到 URL 中,对应的解析时需求 decode;
处理掉逻辑问题的参阅代码如下:
- function parse(str) {
- var paramObj = {};
- var paramArr = decoeURI(str).split('&'); // 先解码
- for (var i = 0; i < paramArr.length; i++) {
- var tmp = paramArr[i].split('=');
- var key = tmp[0];
- var value = tmp[1] || true;
- if (typeof paramObj[key] === 'undefined') { // 判别 key 是否存在
- paramObj[key] = value;
- } else {
- var newValue = Array.isArray(paramObj[key]) ? paramObj[key] : [paramObj[key]]; // 正确处理数组
- newValue.push(value);
- paramObj[key] = newValue;
- }
- }
- return paramObj;
- }
强健问题
整段代码没有做任何的防御性编程,会让它很容报错,哪些地方该做防御性编程是值得拿捏的问题。QueryString 解析函数至少要要求自己的参数是字符串吧?在函数最初添加如下代码会更好:
- //...
- if (typeof str !== 'string') {
- return {};
- }
- //...
需求问题
代码中没有对数字做任何处理,拿到问题就静心写代码的提名人简直都有这个问题,这个问题的考点是怎样把能转换成数字的值转成数字。你想好怎样做了么?用 parseInt?仍是用 parseFloat?
下面是能正确处理数字的参阅代码:
- function parse(str) {
- if (typeof str !== 'string') {
- return {};
- }
- var paramObj = {};
- var paramArr = decodeURI(str).split('&');
- for (var i = 0; i < paramArr.length; i++) {
- var tmp = paramArr[i].split('=');
- var key = tmp[0];
- var value = tmp[1] || true;
- // 处理数字:许多人疏忽这儿的类型判别,布尔值传给 Number 也会解分出数字
- if (typeof value === 'string' && isNaN(Number(value)) === false) {
- value = Number(value);
- }
- if (typeof paramObj[key] === 'undefined') {
- paramObj[key] = value;
- } else {
- var newValue = Array.isArray(paramObj[key]) ? paramObj[key] : [paramObj[key]];
- newValue.push(value);
- paramObj[key] = newValue;
- }
- }
- return paramObj;
- }
不算问题的问题
下面两点不算是问题,可是假如提名人能做到,无疑是加分项。
在 ES6 成为新言语规范的景象下,提名人还在许多的运用 var,尽管并没有错,可是你要有没有更好的办法;
能够用更语义化的 JS 数组办法来安排代码,比方 map、reduce,假如你知道的化,在面试中能够斗胆运用;
运用 ES6 编写的参阅代码如下:
- function parse(str) {
- if (typeof str !== 'string') {
- return {};
- }
- return decodeURI(str).split('&').map(param => {
- const tmp = param.split('=');
- const key = tmp[0];
- let value = tmp[1] || true;
- if (typeof value === 'string' && isNaN(Number(value)) === false) {
- value = Number(value);
- }
- return { key, value };
- }).reduce((params, item) => {
- const { key, value } = item;
- if (typeof params[key] === 'undefined') {
- params[key] = value;
- } else {
- params[key] = Array.isArray(params[key]) ? params[key] : [params[key]];
- params[key].push(value);
- }
- return params;
- }, {});
- }
此外,注重BETWAY登录技术发展的同学或许会留意到部分现代阅览器供给了 URLSearchParams 的支撑,能够用这个特性 1 行代码就搞定需求。
3. 编码完毕后
代码初版写完之后,不要着急立刻展现给面试官,就像是需求开发完,你至少得自己先按需求文档走一遍,把代码原题中的输入代进自己的代码做推演和简略的鸿沟测验,然后再对着代码和面试官解说。不出意外的话,推演进程你自己会发现部分问题,或许显着的改善点,这些内容你都能够跟面试官提出来,由于这也是展现你的才干的时机。
总结
感谢你花时刻读到这儿,相信你现已了解了经过纸上代码的进程和成果能够深化调查提名人的根本本质、作业办法、出活才干,也知道了在回答代码题的不同环节该留意哪些关键:着手前搞清楚问题;编码时留意编码风格、逻辑谨慎性、程序强健性;编码后要先自己测验和推演。当然,假如你之前没留意到这些,需求接下来作业中多加练习。最终祝你能找到你想要的作业。
转载请注明: 文章转载自:BETWAY官网网 https://www.nucmc.com/show-66-1104-1.html