04月01, 2021

我经常和面试者聊的一个题目

本文背景

作为一个Web前端从业者,资深B/S架构的应用开发,通常我们负责的内容都是侧重的浏览器端比较多,即便目前Vue、React等各种框架库流行的年代,核心实现也依然是JS API操作DOM;如果资历更深一些的同学,还会熟知jQuery,更是因为各浏览器API不统一作为其解决的问题痛点。

在长期担任Web前端面试官的过程中,我归纳沉淀了一些有趣的面试题目,今天来聊其中一个与DOM操作相关的题,可以用于考察一个前端工程师的逻辑条理性、问题分析解决能力、纯Web前端(浏览器端)JS技术基础情况等。

面试原题描述

如图,红色矩形是网页中的一个DOM元素(比如是个普通DIV)。

需求:当用户鼠标在该DOM元素上移动时,判定光标相对于灰色对角线所处位置状态(左上、右下、刚好在线上)。

alt

粗略解答思路

相信你一定已经看懂是个啥需求,需要做些啥了吧?

所以不需要赘述了,直接上解法:!!!

  1. 首先,我们需要确定判定方法,以及需要传入的参数。

  2. 然后,再通过DOM行为监听、事件&DOM属性读取,得到参数具体数值,传入上面实现的方法。

很简单对不对?让我想到了经典的“怎么画好一匹马”。

alt

别急,具体处理方式容我再慢慢道来。

一点面试的心得感受

被我面试时聊过这个问题的人,不上几千肯定也过几百了。

所以,技术问题之外,也会有一些心得感悟。

比如我经常对新参加面试工作的同事说的一句话:“切记:面试不是拿你自己准备好的、或者熟悉的问题,创造出一个不公平的沟通场景,然后再跟被面试者比谁更聪明;面试官的职责是通过针对特定话题的沟通,来检验其过往经历的真实性、判定这个人特定方向的能力边界。

如果一个被面试者,第一次遇到这个非纯知识考查的怪异问题,还能做到冷静思考、清晰表述思路,那么我们完全可以判定这个人的基本素质:临场应变、抽象变通都不错。

如果接下来还能提供代码实现过程的表述,那更是这个方向上,问题分析解决能力、编程经验丰富了。

能达到上述表现的,对心理抗压、临场应变、相关技能储备是个不小的挑战,往往是凤毛麟角。

而在我面试他人的经历中,还有两种非常有趣的极端情况会经常遇到:

  1. 看完不假思索、或稍微思考一会,直接选择放弃的。
  2. 缺乏思考或没有清晰的思路,强拉硬扯一通,然后提供一些牵强附会的结论。

当我作为面试官遇到上述极端情形时的感受往往是:

  1. 是不是没太大必要继续浪费时间了。
  2. 这个同学任用可一定得慎重。

当然,感受归感受,现实里面我并不会这么武断的定下结论。此时需要再回顾一下前文加粗的那点感想。

如果一个人的临场应变能力不是非常优秀,也不一定就是能力问题。

谁也难免会有紧张、脑筋卡壳的时候。我自己就经常这样啊 ----- 往往晚上睡觉时趟在床上,回想一天的过往,“嘿,我那个想法、那句话,简直就是SB至极”。

所以遇到上述两种极端情况,换到应聘者角色又或者是这样呢:

  1. 问我这些?简直是羞辱,我不屑回答。
  2. 怎么办,怎么办,好紧张,可我不能不要面子啊:“巴拉巴拉巴拉...”

所以如果我作为面试官遇到不太能给出思路的同学,会试图引导一下,强调“面试不一定非得纯问答题,也是个相互沟通、相互学习的过程,想到啥都可以说说看”。

而作为面试官通过进一步沟通,也可以更可靠、清晰的确认一下对被面试者能力范围的判定。

学霸式解题方法思路

如果面试中遇到数学基础不错的学霸,往往会直接甩出向量方案。

像下图三种状态代表性的点 P1P2P3,求其点坐标到对角线的向量值,根据正、负、零自然也就映射到要判定的状态了。

alt

但是,像我这种连“向量:具有大小和方向的量”的基础概念都忘光光的学渣,肯定不会啊。

所以引导他人解题时候,更是不敢聊向量这个话题了,我经常用逻辑推理的方式。

逻辑推理式解题思路之一

毕竟是引导别人,我也要面子嘛:通常会先建议再想一想、确定一下参照坐标系、画一画辅助线试试。

比如,我们假设任意光标点为P1,DOM元素左下角为二维坐标系原点P0呢?有没有想到啥思路?

还没有思路的话,将P1-P0连线呢?跟对角线比较是啥关系,能不能映射到题目需求状态上?

对嘛,斜线P0-P1与底边的夹角如果大于、等于、小于对角线与底边或左边的夹角,不就判定出来了。

不过要计算角的大小好像也会很麻烦(我三角函数都忘光光了,太难了、不会啊)....

其实,刚刚我们已经不知不解决的假定了底边是x轴、左边是y轴(原点P0嚒 ლ(′◉❥◉`ლ)),也就形成了一个二维坐标系。

在这个坐标系里,P1到左边的距离X、到底边的距离Y,跟矩形宽度boxWidth、boxHeight的比例关系刚好也可以映射到题目需求的三个位置状态上诶!!

即:

  1. X/Y === boxWidth/boxHeight 那么点在对角线上。
  2. X/Y < boxWidth/boxHeight 那么点在对角线左上。
  3. X/Y > boxWidth/boxHeight 那么点在对角线右下。

alt

到这里判定方法确定了,剩下就是怎么去获取这些参数值了。

必要参数值获取

现在我们需要获取4个数值:X、Y、boxWidth、boxHeight。

我就知道,你一定会觉得很简单,没错,这是算是基本JS API基础了。

事件处理及对应值获取

回到题目“当用户鼠标在该DOM元素上移动时”,不就是监听鼠标事件、然后取相关对象的目标属性值么,这有啥难点?

我也一直这么认为的,但经过那么多次面试,发现竟然很多人都不知道(╮(╯▽╰)╭),能通过筛选的怎么也是有几年前端工作经验的呢。

遇到过:“不知道”、 “onMouseover”、“onTouch”、“o(╯□╰)o”...

确定了事件监听方式,那么我们通过事件中的哪个对象啥属性获取X、Y呢?

曾经收到过的答案们(只拿X值关联属性示例):不知道、div.x、event.x、evnet.left、event.offsetX、event.clientX、event.pageX、... ???

上面这些肯定有错误的或者存在问题的,聪明的你,一定想到了正确的方案了。

你拿到的值是相对哪个坐标系的?如果得到的是 pageX值,是不是还得换算一下,又进一步依赖哪个属性怎么获取?

DOM属性读取

X、Y坐标值能取到了,那么boxWidth、boxHeight怎么取呢?

曾经收到的答案们(只拿宽度值关联属性示例):不知道、div.width、div.style.width、div.contentWidth、div.getAttribute('xxx')、div.offsetWidth、div.outerWidth、div.innerWidth、div.getBoundingClientRect().width....

上面这些还是存在错误的,聪明的你,又一定想到了正确的方案了。~O(∩_∩)O~

延展讨论

“既然聊到事件了,如果我页面里有好多元素,还存在懒加载动态插入的,都想达成这个题目的需求,事件绑定有没有一次绑定也都能生效的方案嘞?”、“是不是有个啥事件委托、事件代理?”

“事件可以自定义么?"

"如果我在JS代码里悄悄的自动触发一个元素的事件可以么,会不会有啥问题?”

“诶,上面你好像聊到了 div.style.width、div.offsetWidth,这俩货有啥区别啊?”、“浏览器里是不是有个盒模型的说法?”

“如果鼠标移动频度很高,会不会有性能问题?”、“可以怎么优化一下吗?”。

“如果要在DOM元素里绘制这个斜对角线,该怎么画?”

"你刚说用两个DOM元素分别实现上下三角区域,再绑定onClick判断?" “那这俩三角区域CSS咋写出来?”

收个尾

今天先想到啥写啥了,回头再想到啥再补充。

可能有同学会非常纳闷,“怎么会有这么个题目,前端工程师怎么可能用到?”。

首先这个问题,来自我11年前的一个真实项目经历中的产品需求:

alt

如上图:“当某个WEB应用启用精简排版模式时,将第二行中俩功能按钮合并成第一行的那一个,按照点击位置判定并执行为独立按钮一样的目标行为。”

再后来,稍微了解了一点计算机图形学三角剖分法、纹理贴片,我勒个乖乖,全是三角形,太吓人了,果断放弃。

レ(゚∀゚;)ヘ=3=3=3

本文链接:http://blog.pyzy.net/post/itker.html

-- EOF --

Comments

可以发邮件 huzunjie@pyzy.net 或移步到 https://github.com/huzunjie/blog.pyzy.net/issues 评论交流。