面试遇到的

一有离意便按耐不住自己,面试了一周半便确定了自己即将去的地方,不知道是不是太快了点…前后林林总总面了10家过一点,有5家给了我offer,有些问题没回答上来但还是通过了,还有些就没通过,再次根据回忆主要记录下, 问的太多了,所以下面的问题都是印象比较深刻的,印象深刻嘛,要嘛是不会的,要嘛是问了次数比较多的。对了,我是一个前端,主要的问题也都是针对前端,因为一直在做 vue 项目,所以很多问题也都跟 vue 相关

一位腾讯大佬有这样的面试技巧(或者说招聘技巧):看候选人 github 有个技巧,看他 activityissue 区讨论、给知名开源项目的 PR、merged PR 数量和质量

被问到两次以上的

前端优化方案

涉及太多请自行谷歌

webpack相关

当你讲述你的项目经验的时候,当面试官听到你在用 vue 全家桶的时候,所有相关的问题都会问题, 其他的我都能说个123来,但 webpack 却没咋用,项目中都是别人构建的…也为后面的 thoughtwork 一道开放性作品题失败埋下了伏笔。面试官听到我不会也就没再问了,现在开始补 webpack 的知识

es6相关

你用了哪些 es6 的东西,都是啥,其中 箭头函数 与普通函数的区别最常被问

原型链相关:如何实现原型链继承,原型与构造函数的关系,new 对象的时候发生的过程

下面这张图可以清晰明白的帮助我们理解,如果还想深入理解,参考 这儿1这儿2
原型链

下面附上 es5es6 实现继承的方式:
es5:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function Hero(name, level) {
this.name = name;
this.level = level;
}

// Adding a method to the constructor
Hero.prototype.greet = function() {
return `${this.name} says hello.`;
}

// Creating a new constructor from the parent
function Mage(name, level, spell) {
// Chain constructor with call
Hero.call(this, name, level);

this.spell = spell;
}
const hero1 = new Mage('Lejon', 2, 'Magic Missile');
console.log(hero1)

es6:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// Initializing a class
class Hero {
constructor(name, level) {
this.name = name;
this.level = level;
}

// Adding a method to the constructor
greet() {
return `${this.name} says hello.`;
}
}

// Creating a new class from the parent
class Mage extends Hero {
constructor(name, level, spell) {
// Chain constructor with super
super(name, level);

// Add a new property
this.spell = spell;
}
}
const hero2 = new Mage('Lejon', 2, 'Magic Missile');
console.log(hero2)

结果

1
2
3
4
// hero1
Mage {name: "Lejon", level: 2, spell: "Magic Missile"}
__proto__:
constructor: ƒ Mage(name, level, spell)

1
2
3
4
// hero2
Mage {name: "Lejon", level: 2, spell: "Magic Missile"}
__proto__: Hero
constructor: class Mage

apply 与 call 的区别

都是为了改变调用函数的上下文,唯一的区别就是传参格式的区别,call 接受多个参数, apply 接受数组参数,如下:

1
2
fun().call(thisObj, arg1, arg2 ...)
fun().apply(thisObj, [arg1, arg2 ...])

vue 的生命周期

请参照 vue官网

vue 父子、兄弟组件间传递消息

父子: $emit, props
兄弟: eventBus, vuex

cookie、localStorage、sessionStorage的区别

可以参考我的这篇 文章

登陆超时如何处理

客户端 cookiesessionIdajax 请求携带 cookie,后端判断对应 sessionId 对应的客户,后端存的 session 如果超时了就给接口返回超时的标志位,前端根据该标志跳转到登录页并清空 cookie
其他的方法还有使用 token ,具体可以参照 这儿

如何适配不同大小的显示屏

我回答了 响应式布局、 rem 、 flex,自己对这个并不深入

只被问了一次的

vuex 一般什么时候使用

为了存储一些公用的数据,比如有一个功能需要好几步,你还可以返回上一步,这时候就要用了。

项目中使用了 keep-alive,如何让返回列表页的时候重新刷新数据

我们的项目中并没有使用 keep-alive ,但我知道使用了之后组件的 生命周期方法 是不触发的,于是询问面试官(这个面试官非常和善) route 的钩子触发吗?
面试官给了肯定的答复后作了下面的回答:

可以利用 route 的导航钩子: beforeRouteEnter,在这里处理刷新事项

面试官点了点头。后面经过查证,这个钩子确实是触发的,同时还有我从没注意到的 生命周期方法 也会被触发: activateddeactivated,这是 vue 专门为了 keep-alive 创建的钩子

跨域如何处理

jsonpcorsnginx反向代理等方法,项目上线肯定不能用 nginx反向代理,jsonp我还从没用过,我知道局限性很大, cors 设置的 allow-origin: * 又不安全。而在 vue 项目的开发中,使用的是 webpackproxy

什么是重绘和回流

请参考 这儿

深拷贝一个function

请参考 这篇文章 里关于 深拷贝 的描述

浏览器渲染html的详细过程

回头翻答案,发现自己也了解过这个…但是被问到的时候,一点印象都没,只记得是先渲染 dom 树 ,再渲染具体的。具体的渲染过程请参照 这儿

数组相关

排序算法: 可能是我记性太差,我总感觉不常用的东西很容易忘。排序算法我也模拟实现了插值排序,其他算法也都看过好几遍,结果…写纸上,也没法验证,根据面试官的表情好像写错了。
数组去重: 人家要求说出两种,第一种可以用 [...new Set(arr)], 第二种自己实现…唉,问我的时候我比较慌,说了个双层遍历的方法,下面提供一个单层遍历的:

1
2
3
4
5
6
7
8
9
10
function distinct(arr) {
var obj = {};
if (Array.isArray(arr) && arr.length > 0) {
for (let i = 0, len = arr.length; i < len; i += 1) {
obj[arr[i]] = true;
}
return Object.keys(obj);
}
return [];
}

require导入和import导入有啥区别

刚开始接触 es6 的时候还看过这个,时间久了又忘记了…
CommonJSnode 的规范,它是用 require。而 es6 是用 import,下面是他们的区别:

  • CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。
  • CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。

第二个差异是因为 CommonJS 加载的是一个对象(即 module.exports 属性),该对象只有在脚本运行完才会生成。而 ES6 模块不是对象,它的对外接口只是一种静态定义,在代码静态解析阶段就会生成。显然 编译期 早于 运行期。

更多了解请查看阮大神的 ECMAScript 6 入门

注意: 你可以在同一个文件中同时使用 requireexport. 但不能同时使用 importmodule.exports. 不然会报错——Cannot assign to read only property 'exports' of object '#<Object>'

请列举下js的数据类型

一共7种,es6中新增加了一个数据类型 Symbol。其中 引用类型 只有一种,就是 ObjectArrayFunction 都不算,具体请看 这儿

移动端点击事件 300ms 延迟处理

我回答的是可以用 tap 代替 click,我只记得 angular 还是 ionic 里有这么个方法,官方推荐使用这个…这明显不是面试官想要的答案
后面查了一下:
原因: 等待 300ms 看用户是点击还是双击缩放
解决办法:

  • 禁止缩放 <meta name="viewport" content="user-scalable=no"> ,这样的话双指缩放也被禁了,不推荐
  • 设置默认视口宽度为设备宽度: <meta name="viewport" content="width=device-width, initial-scale=1"> ,加了这个之后浏览器认为该网站已经对移动端做过了适配和优化,就无需双击缩放操作了
  • 设置 css : touch-action:none;touch-action:manipulation; ,属性说明看 这儿
  • fastclick.js

移动端 1px 边框问题

多种方案:1px border 的6种方法

最佳方案: 利用伪类

1. 定义border时使用下面的类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
.bd {
border-style: solid;
border-color: #ccc;
&.bd-l {
border-left-width: 1px;
}
&.bd-r {
border-right-width: 1px;
}
&.bd-t {
border-top-width: 1px;
}
&.bd-b {
border-bottom-width: 1px;
}
&.bd-all {
border-width: 1px;
}
}

2. 利用js添加缩放类 scale-bd

1
2
3
if(window.devicePixelRatio && devicePixelRatio >= 2){
document.documentElement.className = `scale-bd scale-${window.devicePixelRatio}`;
}

3. 定义高清屏下的border:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
.scale-bd {
.bd {
position: relative;
border: none !important;
&::before {
content: '';
position: absolute;
border-color: #ccc;
border-style: solid;
transform-origin: 0 0;
}
&.bd-l::before {
left: 0;
top: 0;
border-left-width: 1px;
}
&.bd-r::before {
right: 0;
top: 0;
border-right-width: 1px;
}
&.bd-t::before {
left: 0;
top: 0;
border-top-width: 1px;
}
&.bd-b::before {
left: 0;
bottom: 0;
border-bottom-width: 1px;
}
&.bd-all::before {
border-width: 1px;
}
}
}
// 对于 devicePixelRatio 为 2 的屏幕
.scale-2 {
.bd {
&::before {
width: 200%;
height: 200%;
transform: scale(0.5);
}
}
}
// 对于 devicePixelRatio 为 2 的屏幕
.scale-3 {
.bd {
&::before {
width: 300%;
height: 300%;
transform: scale(0.33);
}
}
}

sql相关

有面试官问了些简单的 sql ,因为我说我不熟,所以问的都很简单,而且我面的是前端岗…涉及太多请自行谷歌

vuex原理

很抱歉我没了解这个,源码也没看过…请自行谷歌

机试题和开放性题目

我们常碰到的是笔试然后面试,偶尔也会碰到机试题,我这次就碰到了。还碰到了两家比较牛的公司,是让我先做开放性的题目,然后将东西发给人家,人家审核通过了再给你发面试邀请。

  • 机试的公司要求是用框架搭建一个小页面,挺简单的。
  • 一家公司的题库里我选做的是 杨辉三角, 虽然结果正确,但人家邮件回复说没通过,不知道为什么,问原因也没回我。
  • 另一家就是 thoughtwork ,大概的题目是要 自己搭建脚手架工具,我选择了 webpack,再用原生 js 实现一个小的管理系统,不涉及数据库,附带的功能有 响应式布局、单元测试… 很繁杂,虽然花了很久,但没做出来…这就是经常用框架的坏处吧,发现自己短板还挺多的…得补充下了

非技术性问题

为什么离职

我说的是为了多见识多学习,^_^

最近解决的最难的问题是什么

…因人而异

你做的哪件事表现出你有出色的学习能力

…同上

以后的发展规划

这个我也比较迷茫,我觉得前端有些浅,希望能接触到其他的技术。再就是走一步看一步了

结语

还有很多问题都忘记了,想到了会再加上去。想要抱怨的是一些大公司审核太慢了…等你们的时间我已经找到了。上面的题有些是不是很难,哈哈,其中难得题目大多数都是由3个人问出来的: 一个架构师、 一个大公司的大佬、一家使用 jquery的技术leader(他们还没有拥抱 es6 ,所以对 es5 里的一些比较麻烦的问题问的比较多),一般的问题都是比较简单的。和行业内的大佬交流挺有意思的,大多数面试官都感觉人很好。

堂 wechat
欢迎关注我的微信公众号,里面有各种小故事哦!
坚持原创技术分享,您的支持将鼓励我继续创作!