小强赵的个人站点

精进自己,服务他人

我是怎么面试的

这一篇是"面试 & 薪酬"的一节,内容太多单独拿出来,这样内容结构更清晰。

先讲个故事

上次更新两个月后,老板让我负责筛选简历并面试,之前有过的一些思考得到了部分验证,把这段时间面试的一些东西再做一个总结。

最开始总结的面试本质经受住了考验,这里再重复一遍:面试就是抽样了解一个人编码技能存量,预估未来几年技能增量。

先来说个真实的故事,大概一年多之前我面试过一个人,是我老板推荐的,在基础知识考察的时候没达到我的预期就没让过。一个月前新入职一个同事,感觉好面熟,一问就是我一年前面过的那哥们儿。原来是不久前又过来面了一次,过了。首先从面试侧重点来说,我考察的基础占比比其他人的要大一些,对样式的基本功考察的比较严格,因为我觉得如果样式不过关写出来的东西不好维护,这是基础。其次是工作流程的问题,我老板和那人都是乐视出来的,乐视有专门写 CSS 的人,他们写 JS 和 CSS 的人是分开的,我觉得这是造成同一个人给出不同结果的因。所以面试有相当的运气成分在里面。一个月足够看清一个人了,实时证明这个人值得成为同事。

我想从两个角度来说,首先是对“基础”定义的思考,感觉我之前理解的“基础”还不够基础,基础应该是那些写代码绕不过去的理论根基,什么是绕不过去的理论根基我们下面再展开;其次是推荐的力量,如果是前同事,一起工作过,熟悉对方是什么样子的人,靠谱和踏实是很难在面试的时候看出来的,但是推荐能很好的补上这个不足,后来这位同事也确实很给力,在我休假的时候替我接了一个项目,沟通时把自己放得很低,每天赶工到很晚,项目很稳,对于老板来说还有什么奢求呢。

简历筛选

首先是简历的筛选,大多人的简历都是在一个我没听过的公司做了一些大同小异的项目,然后罗列一些技术名词,这种简历我称为“没亮点”,但是收到的大多数简历都是这样的。我帮招过外包和正式T4两个岗位,再高的我自己都还没到那个水平不敢说,留做自我要求吧,也欢迎别人给我提要求。就外包和T4两个岗位来说说吧。

先说比较低一点的外包岗:

1、工作两年以上,这一条不绝对,从概率上的自我经验,第一年刚入门,第二年获得项目经验能独立负责项目;

2、做过和我们现在技术栈相同的项目,熟练使用 git;

3、三个月之内的跳槽不能有,这一条也不绝对,同样是概率上的自我经验,根本上说符合这 3 条的简历很多,挨个面试肯定面不过来,只能舍弃一部分,而舍弃需要有个原则;

4、学校是某大学的优先,贴自己 git 或 博客链接的优先,注明项目是独立完成的并贴链接的优先。

符合前 3 条大概能过滤掉一半以上的简历,然后用第 4 条结合经验,外加相互之间对比每天安排一到两个人来面试。

再说说 T4 岗:

1、上面 3 条依然适用;

2、本科及以上学历,本科 211 或者研究生优先,很抱歉面对陌生的简历这一招真管用,抱歉这条我自己也没达到“优先”,先别打我,要打看完了再打好么;

3、大厂工作过 1 年以上,美团、小米、乐视、网易、新浪、京东、滴滴等,我也不来那么多虚的,对一个我没听过的公司我真的无从判断;

4、有不错的开源作品或者同事推荐的前同事上面 3 条可忽略,同样适用于外包岗。

符合上面条件的人就不多了,经常好几天出不了一份简历,有时老板催得紧也会放宽一点要求。

从另一个角度总结一下,通过的简历主要是两种特质,符合其中一种就可以:

1、履历出色,这些人名校毕业或有大厂经验,能考上名校说明这个人智商较高或能下得了笨功夫,有大厂背书其他人已经帮我们考察过了;

2、不是所有人都能读名校,大厂工作总要有第一份,如果你想从我这里开始,那就要拿出点东西来,比如你基础扎实,深入的了解过某个技术,总的来说就是我(应聘者)具备了这些能力,你(面试官)看看能不能干得了你的活儿。

面试都问点什么

HTML

我会先从最简单的 HTML 问起,首先是让他概述,一般都能想得到超文本、语义化这些点,能提到文档类型、meta标签、再提几个H5的标签,什么 canvas、section、article、nav、aside 什么的都是加分项。文档类型的那些怪异模式我也背不过来,也不会事先准备好难为别人,meta 标签标记编码,移动端的宽度自适应都是一样,只要知道有这么个事就能加分,具体怎么写可以搜一下,但是如果连从哪个方向搜都不知道那这一块就不好意思了,不能加分。然后还问一个侧导航你会用 nav 还是 aside,在我心中用 nav 是比较正确的,因为“把导航重构成头部导航”的可能性要比“把导航去掉侧栏换成其他什么功能”的可能性要大,当然其他理由要是能自圆其说也行。还会问一个 section、article、div 怎么区分使用,每天写页面的人如果对细节有追求他应该思考过这个问题,面对新的东西能有所好奇,而不是 div 一撸到底完成工作酬和交差,我想能保持在细节上不断完善自己的人技术的路能走的更长远一点,也能和他做更长时间的同事。但是以上问题只是加分项,不会成为卡人的条件,因为还有另一种人,他们不太注重这些细节,但是大局观很好,能把有限的时间用在更复杂的技术上。

所以加分项不一定出现在最后,可能出现在开头,也可能出现在每一题中,能回答道每个层次,或者答到了某个点上也能加分。

CSS

然后是 CSS:请概述 CSS,他有那几部分组成,相关的周边技术有哪些?

上面提到筛选简历有一份运气的成分在里面,面试也一样,我力图把面试中的运气成分降到最低,先扔一个很开放的问题出来收集信息,然后根据对方提到的点深入问下去,这样能避免有些技术点我自己掌握的很好但是对方只是听说过,对方有些擅长的点由于我不擅长没问到。如果对方说的某些点是我所不知道的还能顺便学到东西,那么如果对方提了一个我没听说过的东西,那我还要不要问下去?我的答案是要问下去,能把一个概念在短时间内讲清楚是一个很重要的技能,这个能从侧面不但能反映出这个人表达能力,还能反映出这个人的学习能力。之前听过一句话:怎么判断一个东西你学会了吗,能把他教给一个不会的人那你就真学会了。至于他说的对不对回来一查不就知道了。

我个人认为 CSS 的重要内容有这几块:选择器、盒模型、布局、动画。当然这不是唯一答案,能自圆其说就好,如果对方没回答上来我会引导,这几项内容我都会问到,怎么问往下看。

问:先说一下选择器都有哪些点?

基本期望:

如果不知道属性选择器,vue 的组件样式作用域原理就不可能理解,关系选择器 > + ~ 和结构伪类 :first-child :last-child 至少熟练使用其中一个。

选择器优先级除了规则表述正确外,还会问下面这个题,哪行样式生效,如果答错了那就进黑名单了,如果后面的不能表现突出的话就危险了。

<div class="a">
    <div class="b">
        <div class="c"></div>
    </div>
</div>
.b .c {}
.a .c {}

盒模型,width margin padding border box-size 这些属性的关系和效果要说清楚。弹性盒模型的概念要说的清除,flex 有哪几个属性值要了解(这里放弃老生常谈的 position 属性考察),要明确兼容性,移动端可用(手淘已经在用了),PC 端 IE11 才能用。

然后是动画,transition 和 animation 至少要说上来一个

布局,可以口述出常见的布局和实现方案,什么是栅格布局加分。 http://www.cnblogs.com/dojo-lzz/p/4621627.html

如果简历里面有写预处理器,会问几个简单的语法,嵌套,变量定义。

CSS 部分最后是两个编程题:

1、左侧栏固定宽度,右内容区自适应宽度。进一步衍生:如果要加个折叠功能样式怎么改,要兼容 IE8 还有什么办法。这其实是盒模型、布局、动画的综合考题。两块之间的间距,两块的高度等细节都是基础是否扎实的体现。

2、版权信息吸底,要求内容不过多的时候在最底部,内容超过一屏时自动往下撑。版权信息每个系统都有,能否把他写的极致能体现对工作的态度。主要的点有 html 和 body 这两个特殊节点的渲染表现,定位和占位等小技巧。

JS

请概述 Js,他有那几部分组成,相关的周边技术有哪些?

首先是 Js 本身语法层面的东西:数据类型、各种中数据类型的相关知识点、作用域(闭包)、递归。当然还有很多的点,比如面向对象、函数式编程、各种设计模式,之所以不问是因为在自审的时候这些东西我自己也不一定使用,比如函数式编程就算用了也不是处处都能做到,设计模式有吗么一段时间看了了解了,不去刻意记忆好多模式是背不过的,不说 23 种了,14 种在 js 中常用的设计模式大家可以问问自己能说上来多少,我觉得设计模式这东西是融在代码里的。当然这些知识,作为面试官需要事先准备。

然后是和浏览器相关的事情:事件模型、Ajax。当然还有 canvas、history、跨域

最后是前端框架,原理,用法。

下面是面试题:

Array 有哪些方法?说说 some 和 every 的异同点。两个考察点,第一是基础,这两个方法不算偏吧;第二是表达,能把这两个函数的入参出参等说明白。

说说Promise。使用 Ajax 必然会遇到的,问问 then 和 finally,多个异步串行与并行的写法。

正则能做什么事情?模式识别,替换,提取。正则去除收尾空格怎么写。

现在有 3 个 li,用原生 Js 写事件绑定,点击的时候弹出当前是第几个。这个题考察原生 Js 的基本调用和闭包的使用,是很常规的一个题。

取URL的参数。实际操作题,需要考虑等好后没有值,后面有哈希等情况。

递归实现斐波那契数列:1 1 2 3 5 8。

注:f(n) = f(n - 1) + f(n - 2),f(1) = f(2) = 1。

function f(n) {
    if (n < 3) {
        return 1;
    }
    else {
        return f(n - 1) + f(n - 2);
    }
}

主要考察有没有递归的思想,各种异常的判断可以加分,负数,小数(Number.isInteger)。

框架主要问 vue,我们这边主要用的也是这个。

父子组件传参需要注意的点,prop 里面的参数是否能直接用在子组件的 v-model 上?

// 父组件
<template>
<div>
    <c :a="msg"></c>
</div>
</template>
<script>
import c from './c';
export default {
    components: {c},
    data() {
        return {
            msg: 'Welcome to Your Vue.js App'
        };
    }
};
</script>
// 子组件
<template>
<div>
    <input type="text" v-model="a">
</div>
</template>
<script>
export default {
    props: ['a'],
    data() {
        return {};
    }
};
</script>

父组件可以直接向子组件传参,但是子组件不能直接改变传进来的值,这是使用 vue 必趟的坑,属于基础题。

组件数据双向绑定有哪几种写法,各适合什么场景?

// 父组件
<template>
<div>
    <c v-model="m"></c>
</div>
</template>
<script>
import c from './c';
export default {
    components: {c},
    data() {
        return {
            m: true
        };
    }
};
</script>
// 子组件
<template>
<div>
    {{checked}}
    <input type="button" value="改变值" @click="changeValue">
</div>
</template>

<script>
export default {
    model: {
        prop: 'checked',
        event: 'change'
    },
    props: {
        checked: Boolean
    },
    data() {
        return {};
    },
    methods: {
        changeValue() {
            this.$emit('change', !this.checked);
        }
    }
};
</script>

自定义 v-model 可以用来做双向绑定,对父组件来说比较简单,直接省略自定义事件的监听。需要注意的是 model 中定义的 prop 必须在 props 中定义,event 定义的事件名,被用做 $emit 函数的第一个参数。

// 父组件
<template>
<div>
    {{m}}
    <c :a.sync="m"></c>
</div>
</template>
<script>
import c from './c';
export default {
    components: {c},
    data() {
        return {
            m: true
        };
    }
};
</script>
// 子组件
<template>
<div>
    {{checked}}
    <input type="button" value="改变值" @click="changeValue">
</div>
</template>

<script>
export default {
    props: {
        a: Boolean
    },
    data() {
        return {
            checked: true
        };
    },
    methods: {
        changeValue() {
            this.checked = !this.checked;
            this.$emit('update:a', this.checked);
        }
    }
};
</script>

sync 是 2.3 又加回来的属性,也是一种通过事件更新父组件属性的写法,与 v-model 在技术上不同的是它可以加多个。model 中的 event 硬编码不知道有什么特别的用处。

slot 的作用域是什么?直接拿官方的代码上来:

<my-awesome-list :items="items">
<!-- 作用域插槽也可以是具名的 -->
<template slot="item" scope="props">
    <li class="my-fancy-item">{{ props.text }}</li>
</template>
</my-awesome-list>

知不知道 runtime only 的概念,框架上说说 runtime + compute 和 runtime only 的区别。

其他

如果简历里有写搭建脚手架,可以问问工程上的问题,webpack 和 gulp 的异同。

如果有写是团队 leader 的,问问管理中出现过什么问题,怎么解决的。

潜力

没有太多经验,这里借用黄之昊的问法:近期有什么挑战,你自学的途径有哪些?

下面是我自己的回答:

总的来说我的学习方法是:快速度规范,仔细读源码,折腾写点啥。那怎么选择学习的方向呢,我一般是实用主义,能带来自己和团队效率提升,或者在工作中其他人在做我不会做。毫不避讳的说,我迟早会带领自己的团队,现在团队中的一切工作,甚至包括和外团队的合作工作都需要了解。

近期做完的事情:

1、git 的深入学习,各种命令、各种坑,比如远程分支已经删除了本地 git branch 还能看到,git branch -d 删除不好使怎么解决。git flow、git feature、git master 各种工作流的利弊。

2、怎么开发 cli 工具,规范包括文件夹的定义和 npm 相关的东西,源码看了 vue cli,关键的知识点有怎么收集用户输入:alert、radio、checkbox、input 等表单元素在命令行中的实现,从远程下载模板,模板解析,小的东西包括命令行 loading、高亮等,然后顺手定制了一个 vue 脚手架。关于挑战,没找到比较好的 less sass stylus 格式校验工具(像 eslint 之于 js),IDE 插件的开发还没搞定。

3、面试总结,就是你当前看到的这篇文章,遇到的最主要的问题就是候选人会的我没问到,我用到的一些东西的候选人没用过因而答不上来,解决方式就是只问最基础的,从他提到的技术点往深挖。

正在进行的事情:

1、操作系统的学习。

2、node 的学习,已经帮团队做了一个小个工具,用到文件存储,上传下载等。

对面试者说几句

不要简历造假,否则你失去的可能不仅仅是这一次面试机会。在一个平台上,后面面试的公司是可以看到前面公司的评价的,如果有公司给你打上简历造假的标签,那后面的公司看到后根本没可能给你面试的机会了。

开始几年尽量找一家能提升自己的公司,大厂优先,技术氛围优先,互联网小公司由于传统大公司的信息部。

总结

上面这些大概一个小时的量,面试真是个技术活儿,共勉。