从面试官角度看一次前端面试经历

卡尔
• 阅读 1555

今天被抓差给候选者进行初面。在这里记录一下面试中涉及的几个知识点。

每次面试我都会递给候选者一瓶水,这样可以让候选者没那么紧张,有更好的状态进行面试,毕竟面试是双向选择,公司也需要尽快找到合适的人,没那么多网上说的心理战。

这里我还想吐槽一下面试造火箭工作拧螺丝,尤其是开发行业,很多面试官针对自己擅长的方向大问特问,完全忽略了候选人的优势,从而给候选人带来一个极差的面试体验。面试最好还是要通过候选人身上的优点来判断对方是否适合加入你的团队。

正常的面试应该是按照候选人简历中涉及的技术点发问,不然面试时给你一份简历干嘛,至于简历中未涉及的知识点有没有必要问,我觉得没什么必要的,因为很多人在写简历的时候都是力求全面,恨不得听说过的知识点都写上熟悉。所以按照简历提问就可以了。除此之外再问一些最近流行的技术,主要考察的是候选人对新技术的敏感性和对新事物的接受能力。

如果其中涉及到候选人回答不上的问题也需要给候选人做一番解答,毕竟人家那么远来你这面试,总要有所收获不是。

最后在简历中挑选一个候选人比较擅长的点深入来问,这个环节我一般称为定级,前面的问题如果回答的不错,这个人基本就通过了,到最后就要给人定级。如果前面问题回答的不理想基本也到不了这个环节。

Proxy

在2020年来看Proxy早已经不是一个陌生的词了,他能做的是有很多,尤其在Vue3.0通过Proxy来重构之后,很多面试官喜欢问这个Proxy以及和Object.defineProperty的对比。

Proxy是专门为对象设置访问代理器的,通过Proxy可以轻松监视到对象的读写过程,相比于defineProperty,Proxy他的功能要更为强大甚至使用起来也更为方便。

这里我们定义一个person对象,我们通过new Proxy的方式来去为我们的person来创建一个代理对象。

Proxy构造函数的第一个参数就是我们需要代理的对象,这里是person,第二个参数也是一个对象,我们可以把这个对象称之为代理的处理对象,这个对象中可以通过get方法来去监视属性的访问,通过set方法来去介绍对象当中设置属性这样的一个过程。

const person = {
    name: 'yd',
    age: 18
}

const personProxy = new Proxy(person, {
    get() {},
    set() {}
}) 

先来看get方法,这个方法最简单可以接收两个参数,第一个就是所代理的目标对象,第二个就是外部所访问的这个属性的属性名。这个方法的返回值将会作为外部去访问这个属性得到的结果。

{
    get(target, property) {
        console.log(target, property);
        return property in target ? target[property] : undefined;
    }
} 

再来看下set方法,这个方法默认接收三个参数, 分别是代理目标对象,以及我们要写入的属性名称还有最后我们要写入的属性值。 我们可以做一些校验,比如说如果设置的是age,他的值就必须是整数,否则就抛错。

{
    set(target, property, value) {
        console.log(target, property, value);
        if (property === 'age') {
            if (!Number.isInteger(value)) {
                throw new TypeError(``${value} must be a integer);
            }
        }
        target[property] = value;
    }
} 

相比于Object.defineProperty, Proxy到底有哪些优势。

首先最明显的优势就是在于Proxy要更为强大一些,那这个强大具体体现在Object.defineProperty只能监听到对象属性的读取或者是写入,而Proxy除读写外还可以监听对象中属性的删除,对对象当中方法的调用等等。

第二点优势就是对于数组对象进行监视,通常我们想要监视数组的变化,基本要依靠重写数组方法,这也是Vue的实现方式,proxy可以直接监视数组的变化。以往我们想要通过Object.defineProperty去监视数组的操作最常见的方式是重写数组的操作方法,这也是Vue.js中所使用的方式,大体的方式就是通过自定义的方法去覆盖掉数组原型对象上的push,shift之类的方法,以此来劫持对应的方法调用的过程。

对象的键支持什么类型

这个问题考察的是候选人的基础知识是否扎实。

很多人都会认为对象的键是字符串类型,如果在以前确实没错,但是ES2015版本中对象的键类型还可以是Symbol。

const person = {
       name: 'yd',
    [Symbol()]: 18
} 

这也是引出下面的Symbol。

Symbol

在ECMAScript2015之前,对象的属性名都是字符串,而字符串是有可能会重复的。如果重复的话就会产生冲突。

以前解决这种问题最好的方式就是约定,但是约定的方式只是规避了问题并不是彻底解决了这个问题。如果在这个过程中有人不遵守约定那这个问题仍然会存在。

ES2015为了解决这个问题提供了一种全新的原始数据类型Symbol,翻译过来的意思叫做符号,翻译过来就是表示一个独一无二的值。 通过Symbol函数就可以创建一个Symbol类型的数据,而且这种类型的数据typeof的结果就是symbol,那这也就表示他确实是一个全新的类型。

const s = Symbol();
typeof s; // symbol类型 

这种类型最大的特点就是独一无二,也就是说我们通过Symbol函数创建的每一个值都是唯一的。他永远不会重复。

Symbol() === Symbol(); // false 

考虑到在开发过程中的调试Symbol创建时允许接收一个字符串,作为这个值的描述文本, 对于我们多次使用Symbol时就可以区分出是哪一个Symbol,但这个参数也仅是描述作用,相同的描述字段生成的值仍是不同的。

const s1 = Symbol('foo');
const s2 = Symbol('foo');

s1 === s2; // false 

从ES2015开始,对象就已经允许使用Symbol作为属性名。那也就是说现在对象的属性名可以是两种类型,字符串和Symbol。

const person = {
    [Symbol()]: 123,
    [Symbol()]: 456
} 

如果我们需要在全局去复用一个相同的Symbol值,我们可以使用全局变量的方式去实现,或者是使用Symbol类型提供的一个静态方法去实现。具体就是Symbol的静态方法for,这个方法接收一个字符串作为参数,相同的参数一定对应相同的值。

const s1 = Symbol.for('foo');
const s2 = Symbol.for('foo');

s1 === s2; // true 

这个方法维护了一个全局的注册表,为字符串和Symbol提供了一个对应关系。需要注意的是,在内部维护的是字符串和Symbol的关系,那也就是说如参数不是字符串,会转换为字符串。

const s1 = Symbol.for('true');
const s2 = Symbol.for(true);

s1 === s2; // true 

JSONP

很多人对jsonp的理解都停留在概念上,没有真正理解过他的原理,他为什么可以跨域,当然不仅仅是script标签不受同源策略影响,实际上jsonp是一种前后端约定的解决方案。

不过现在基本已经很少用到了。因为现在已经有了更流行的CORS方案,相对来说也会更安全,不过jsonp还是有其自身的优势的。

很多人都知道浏览器的同源策略,就是发送请求的页面地址和被请求的接口地址的域名,协议,端口三者必须一致,否则浏览器就会拦截这种请求。浏览器拦截的意思不是说请求发布出去,请求还是可以正常触达服务器的,如果服务器正常返回了浏览器也会接收的到,只是不会交给我们所在的页面。这一点查看network是可以看到的。

jsonp一般是利用script标签的src属性,对于服务器来说只有请求和响应两种操作,请求来了就会响应,无论响应的是什么。请求的类型实在太多了。

浏览器输入一个url是一个请求,ajax调用一个接口也是一个请求,img和script的src也是请求。这些地址都会触达服务器。那为什么jsonp一般会选用script标签呢,首先大家都知道script加载的js是没有跨域限制的,因为加载的是一个脚本,不是一个ajax请求。 你可以理解为浏览器限制的是XMLHttpRequest这个对象,而script是不使用这个对象的。

仅仅没有限制还不够,还有一个更重要的点因为script是执行js脚本的标签,他所请求到的内容会直接当做js来执行。

这也可以看出,jsonp和ajax对返回参数的要求是不同的,jsonp需要服务返回一段js脚本,ajax需要返回的是数据。

因此这就要求服务器单独来处理jsonp这中请求,一般服务器接口会把响应的数据通过函数调用的方式返回,比如说返回的内容是'yd',那就要返回成cb('yd')

cb('yd') 

这是一段函数调用的脚本,通过script标签加载之后会立即执行的,如果我们在全局定义一个cb函数。那么这段脚本执行的时候就会调用到我们定义的那个函数,函数中的参数就是服务返回的值了。前端也就可以在这个函数中获取到了。

function cb (data) {
    console.log(data);
} 

所以说jsonp是前后端共同约定的一种结果。

CORS

浏览器通过同源策略来限制前后端的跨域问题,但同时也给了相应的解决方案。

服务器在返回相应的时候可以通过设置响应头来允许哪些网址跨域请求,这样前端就可以成功拿到响应的结果了。所以这也证实了,前端拿不到结果不是服务器不返回,而是浏览器没有给到前端。

Access-Control-Allow-Origin: www.xxxx.com 

webpack的proxy是如何解决跨域的?

前面说了,跨域是因为浏览器的同源策略限制,问题发生在浏览器身上,那我们是不是可以避过浏览器呢,前面我写过一篇前端应该知道的nginx,里面介绍了反向代理和负载均衡,其实这就像是反向代理一样。

我们在使用webpack开发项目的时候,webpack的dev-server模块会启动一个服务器,这个服务器不止帮我们做了自动更新,同时也可以做到反向代理。

就是我们把请求发送给webpack-dev-server, 然后webpack-dev-server再去请求后端服务器,服务之间的请求是没有跨域问题的,只要后端返回了webpack-dev-server就能拿到,然后再返回给前端。

好了基本上就问了这几个问题,老板说面试时间控制在20分钟左右。

面试技巧

最后总结一些面试技巧提供给大家。2021-2-21【新增】

简历要简洁明了,突出个人技能和项目经验,一般简历写个两页纸就可以了,太多也没人看,太少单薄,我一般面试的时候就只看前两页。

简历中个人技能要写在前面,项目经验写在后面,不要弄反了,项目经验中要描述清楚技术栈。个人介绍,工作经历,教育经历简单就好。

如果个人博客和开源作品质量都不错,可以写在简历中,如果没有或者质量一般最后不要放。

简历要保证能力的真实性,不要造价,水份不要过大,切忌不要写精通,也没几个人能真的做到精通。

如何看待加班?这个还是要看个人,我一般是不推荐加班的,就像借钱,救急不救穷,要说明白怎么看待加班,什么样的加班接受什么样的加班不接受。项目特别急并且价值特别大加加班也是没什么的,常态的加班肯定是不可取的。长时间的加班带来的结果必定的虚假繁荣,生产力的低下。

面试中最好不要挑战面试官,如果面试官说的不对可以低调的或者委婉的转变一下说辞,离开也可以不要和面试官争辩,即使你不想要这份工作。

要给面试官惊喜,证明你可以做的更好知道的更多,一个问题如果你能回答及格就要考虑怎么回答到优秀,但是要做到更好不是更多,别说太多废话,也不要说起没完。比如说这个问题还有一个更好的解决办法等等。

遇到不会的问题说出你知道的部分即可,但别岔开话题,给人心虚的感觉,而且面试的过程中你也基本很难岔开话题,这会让面试官很反感。

对于自己的缺点可以换一种话术,委婉一些的表述,人都有缺点这没什么,你可以说你知道自己哪部分知识薄弱最近也正在学习,这样就化缺点为优点了。


欢迎关注,更多内容持续更新

本文转自 https://juejin.cn/post/6907146147065856013,如有侵权,请联系删除。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
3年前
java将前端的json数组字符串转换为列表
记录下在前端通过ajax提交了一个json数组的字符串,在后端如何转换为列表。前端数据转化与请求varcontracts{id:'1',name:'yanggb合同1'},{id:'2',name:'yanggb合同2'},{id:'3',name:'yang
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Stella981 Stella981
3年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
11个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这