2020年底前端面试记录

375 阅读13分钟

面试结果

先说下面试结果:

  1. 美团offer:难度中等偏上
  2. 蚂蚁offer:难度中等
  3. 猿辅导、贝壳10月份拿到offer,但没去,后来问了下可以去,但是薪资不调整,遂over,猿辅导的面试还是比较有技术含量的,当时其实想走了,后来想想等等年终奖吧,就没去
  4. 滴滴一面挂
  5. 快手、头条三面挂:难度偏上
  6. 腾讯二面挂,难度适中。其实是有希望过,只是面的时候发现不是自己想去的部门,面试官说你可想好。。不然要出问题,然后面试官估计看出我不想去,后面的流程就不走了。

感受

  1. 整体下来,快手、头条的难些,其次是美团、猿辅导、滴滴,蚂蚁和腾讯适中。
  2. 面试基本每次都一个小时左右,视频面试,都是面完一轮再约下一轮。hr面会短些。
  3. 年前面试可能会出现职位没那么多,腾讯就属于年前有点冻结hc了。其他的还好。
  4. 阿里和腾讯的流程都比较慢,所以预留好时间。

建议每一次面试后记下面试题

每次面试完记得总结,把每一个知识点都学习会,防止后面再面又不会。 我以下记录的都不全,其实有重复的题。但有的没弄明白,后面又会答不好。

面试题

猿辅导

一面

  1. async defer区别
  2. 端能力,js如何和native通信,写一下iframe通信
  3. 箭头函数和普通函数区别
var obj = {
  test: '123',
  f1: () => {
    console.log(this.test)
  },
  f2: function () {
    console.log(this.test)
  },
}

obj.f1() // undefined
obj.f2() // 123

new obj.f1() // throw error
new obj.f2() // instance
  1. promise相关
Promise.reject(1)
  .then(() => console.log(1))
  .catch(() => console.log(2))
  .then(() => console.log(3))
  .finally(() => console.log(4))

2 3 4
Promise.reject(1).then(res, rej))
const promise = new Promise((resolve, reject) => {

  console.log(1);

  resolve();

  console.log(2);

})

setTimeout(() => console.log(3), 0)

promise.then(() => {

  console.log(4);

})

console.log(5);
  1. 求一个二叉树的最大宽度
  2. 介绍项目

em....太久没说项目了 有点直直呼呼说的不清楚

二面

  1. sleep(4).then(console.log).then(console.log) sleep(4).catch(console.log).catch(console.log) 实现连续输出4 说说promise then的理解

  2. {isA ? <label>A</label> : <label>B</label>}都发生了什么?

  3. 工作中有哪些提高效率的地方?包括看到的或者自己做的:答的不好

  4. 说下看过的源码:答的不好,忘了

  5. 自己的学习方式

二面回答比较开放式,答的不是很好 回答的问题:

  1. 回答没有逻辑性,想到哪说到哪,应该分步骤一个个说清楚
  2. okam源码相关忘了。。。依赖分析怎么做的?编译?vue呢 都看的太浅了,需要花时间看看

三面

当时没记录下来,问的计算机基础知识较多,网络等各种。最后通过了。

美团

一面

  1. 为啥要有跨域策略?安全(csrf)、内容保护
  2. 小程序原理
  3. 数组打平并且排序:[1,2,3, [5,4], [7,6]] //输出 [1,2,3,4,5,6,7]
  4. 实现原理
  5. 微信红包分配算法 1块钱分给10个人

二面

当时没记那么多,现在就只记了一道了。。

const tree = {
  type: 'html',
    children: [{
      type: 'div',
        children: [{
          type: 'p'
          }, {
          type: 'span',
      }],
  }],
};
// 节点一定有 type,且 type 是任意字符串
// 不一定有 children
// children是节点数组
const countTree = (tree) => Object<string, number>
​
{html: 1, div: 1, p: 1, span: 1}

三面

  1. hn原理,没讲清楚。

三面面的不是很好,觉得有挂的可能,不过后来还是过了,感谢面试官。

当晚hr面,但是说三面不一定过。。

滴滴

一面挂。。当时一个星期没有通知面试,滴滴的投的约的比较早,一面确实面的不太好,可能之前滴滴挂的面试记录,对面试也有影响吧。滴滴聊了一会,做了一套面试题,用腾讯文档出的,基本是粘贴的题的图,所以下面也直接粘过来了。

一面

  1. fis3原理 vs webpack
  2. 用 JS 实现二分查找(折半查找)算法,并写出时间复杂度。
  3. 用 JS 实现深拷贝。

5. 如下代码,分别弹出什么信息?考察作用域

 var a = 100
  function create() {
    var a = 200;
    return function() {
        console.log(a)
    }
  }
  var fn = create();
  fn(); // 200

  var a = 100
  function invoke(fn) {
    var a = 200
    fn();
  }
  function fn() {
    console.log(a)
  }
  invoke(fn); // 100

5. 用 flex 实现下图效果。容器宽高不定,子元素宽高固定?

  • 考察align-self?
.box {
    display:flex;
}
.item:nth-child(2) {
    align-self: center;
}
.item:nth-child(3) {
    align-self: flex-end;
}

6. 现有瀑布流式图片页面(页面下拉时无限加载图片),用 JS 监听每个图片的点击事件。原生的如何写?

$(document).on('click', 'img', function(e) {
alert('click')
})

7. 执行如下代码,然后点击每个 <a> 标签分别弹出什么信息?并写明原因。

 $body = $('body')
  let arr = [1, 2, 3, 4, 5]
  var i,
  length = arr.length
  for (i = 0; i < length; i++) {
    $a = $(`<a>${i}</a>`)
    $body.append($a)
    $a.click(function () {
        console.log(i);
    })
  }

全部是5,因为事件执行的时候i早就变成5了。

8.  执行下面代码会输出什么信息

  const obj = {a: 100}
  const obj1 = obj;
  let a1 = obj.a;

  obj1.a = 200
  console.log(obj.a)
  console.log(a1)
  a1 = 300
  console.log(obj.a)
  console.log(obj1.a)

200 100 200 200

9.  执行如下代码,会输出什么信息?

200 300 100

10.  执行如下代码,abc 会是什么颜色? 并且说明原因。

red

10.  执行如下代码,分别打印出什么?

123 instanceof Number
new Number(123) instanceof Number
Number(123) instanceof Number // 陷阱,这里是把123变成数字了

false true false

  1. 执行如下代码,会输出什么信息?
var a = {}, b = '123', c = 123
a[b] = 'b'
a[c] = 'c'
console.log(a[b]);

var a = {}, b = {key: '123'}, c={key: '456'}
a[b] = 'b'
a[c] = 'c'
console.log(a[b]);

var a = {}, b = Symbol('123'), c=Symbol('123');
a[b] = 'b'
a[c] = 'c'
console.log(a[b]);

答案:c c b

快手

快手当时每次都记下来了,所以题记录的比较全面,前2面还行,三面问的开放一些,答的不好,题也写的不好,挂掉了。

一面

  1. new 做了什么?
/**
    1. 创建一个对象
    2. 将构造函数的属性和方法copy到自身
    3. 将对象的原型赋值为构造函数的原型
    4. 返回对象,如果函数本身有返回对象,则返回自身的,否则返回对象
**/
function newOperator(f, ...args) {
    let o = {};
    let res = f.apply(o, ...args);
    o.__proto__ = f.prototype;
    return res instanceof Object ? res : o;
}

  1. 原型链
Object instanceof Function
Function instanceof Object

Object.__proto__ === Function.prototype;
Object.prototype.__proto__ === null;
Function.__proto__ === Function.prototype;
Function.prototype.__proto__ === Object.prototype;
  1. 箭头函数和普通函数的区别?
var name = 'x'
var people = {
  name: 'y',
  setName: (name) => {
    console.log(this, this.name)
    this.name = name
    return () => {
    return this.name
  }
}
​
var getName = people.setName('name')
console.log(people.name)
console.log(getName())
如果换成function,结果是啥
  1. promise、timeout时序题
console.log('start')
setTimeout(() => {
  console.log('timer1')
  Promise.resolve().then(function () {
    console.log('promise1')
  })
}, 0)
setTimeout(() => {
  console.log('timer2')
  Promise.resolve().then(function () {
    console.log('promise2')
  })
}, 0)
Promise.resolve().then(function () {
  console.log('promise3')
})
console.log('end')
  1. es2016-es2020新增的语法特性有哪些?
  • async/await、import('./module')、BigInt、obj?.prop
  1. 为什么JS中0.1+0.2 !== 0.3?如何处理这种情况?
  • 浮点数精度,1/2的整数次方;因为js的存储是64位的,而0.1 0.2转换成二进制时会产生精度损失,导致计算错误。
  • 解决:转整数,写一下
function add(num1, num2) {
    let num1Len = (String(num1).split('.')[1] || '').length;
    let num2Len = (String(num2).split('.')[1] || '').length;
    let base = Math.pow(10, Math.max(num1Len, num2Len));
    return (num1 * base + num2 * base) / base;
}
add(0.1, 0.2);
add(1.111, 2.3)
  1. css选择器权重优先级。10个class会大于id吗?
  • important>style>id>class>tag 。不会
  1. vue的scoped css是如何实现样式隔离的?
<style lang="less" scoped>
​
.button {color:green;}
.button {color:red;}
</style>
​
<template><template>
​
className="has123_button"
style={styles.button}

.button[data-v-w2c3nc9d]
.button[data-v-111111]
  1. 单文件vue-loader原理

    1. 先将文件三部分内容提取出来,分别进行处理,最后生成一个js文件
    2. template部分使用vue-template-compiler进行编译,转换为ast 再生成render函数,然后插入到js部分生成的组件对象中
    3. js部分,webpack配置中所有对js生效的rules都会生效,可以用babel进行处理
    4. css部分,css的rules会应用到其中,应该会引入js中吧
  2. vue生命周期,父子组件生命周期

beforeCreate
created
beforeMount
mounted
beforeUpdate
updated
beforeDestory
destoryed

父子生命周期
父 beforeCreate
created
beforeMount
子 beforeCreate
create
beforeMount
子 mounted
父 mounted
  1. vue中if和show区别?如果为了减少首屏时间,使用谁?
  • if:减少dom创建,减少了哪一步?只是生成了vdom,没有从vdom生成真实dom
  1. css的scoped,作用是啥,如果要改变第三方组件的样式,符合更改?
  2. ajax跨域。JSONP、CORS、proxy
  3. 前端性能优化做过哪些工作?
  • 图片base64、雪碧图、webp、require懒加载;强缓存/协商缓存概念区分。expire/cache-control、last-modified/etag
  1. http2特性?
  • 多路复用,头部压缩,服务端推送
  1. 防抖和节流是什么?实现防抖
function debounce(fn, time) {
    let timer = null;
    let outerArgs = Array.prototype.slice.call(arguments, 2);
    return function () {
        clearTimeout(timer);
        const innerArgs = Array.prototype.slice.call(arguments);
        timer = setTimeout(() => {
            fn.apply(this, outerArgs.concat(innerArgs))
        }, time);
    };
}
  1. 数组洗牌
input: [1, 2, 3, 4, 5]
output: [3, 4, 2, 5, 1]
/**
* @param {Array} arr
* @returns {Array}
*/
function shuffle(arr) {
    for (let i = 0; i < arr.length; i++) {
        let tmp = arr[i];
        let valindex = parseInt(Math.random() * (arr.length - i) + i, 10);
        console.log(valindex);
        arr[i] = arr[valindex];
        arr[valindex] = tmp;
    }
    return arr;
}

二面

  1. 前端路由实现,区别是啥?
    • hash实现:修改hash改变页面,也会进历史记录,hashChange监听修改,只能改变hash部分
    • history pushState(进历史记录)、replacestate(替换历史记录)改变页面url,onpopState监听前进后退,但监听不了pushstate和replacestate和a跳转,a跳转通过点击监听,push和replace通过api直接监听,可以改变域名后整个path,为啥要nigix配置,因为刷新后直接请求后端,如果没有对应的path会直接404
  • 区别:
    • hash 能兼容到IE8, history 只能兼容到 IE10;
    • hash回车刷新会加载到地址栏对应的页面,hash后端请求不会带hash,所以还是原来的页面,history一般就是404掉了
  1. 浏览器缓存,lastmodified解决了什么?
    • 打开文件没有修改,时间戳也会变,导致返回相同的数据;最小单位是1s,但是1s内文件修改了,这期间又来了其他请求,导致还是返回原来数据。
  2. rollup与webpack区别
  3. 预取判断元素可见范围 observeMutation 好处?
  4. rem原理
  5. commonsChunkPlugin 与splitChunkPlugin区别?
  6. webpack5 新特性
  7. vue3新特性
  8. add(1)(2)(3)(4)() => 10
  9. 原型链
function A () {}
A.prototype
A.__proto__

var a =new A()
a.prototype
a.__proto__
  1. ToPromise
ajax( url, (succ, err)=> {})
var p = ToPromise(ajax)
p(url).then().catch()
const toPromise = fn => {
    return function(...args) {
        return new Promise((resolve, reject) => {
            const cb = (succ, err) => {
                if (succ) {
                    resolve(succ);
                }
                if (err) {
                    reject(err);
                }
            };
            fn.apply(this, args.concat(cb)); 
        });
    }; 
};
  1. 求树的最大深度
const depth = node => {
  if (!node) {
      return 0;
  }
  let maxDepth = 0;
  node.children.forEach(item => {
     const childDepth = depth(item);
     if (childDepth > maxDepth) {
         maxDepth = childDepth;
     }
  });
  return maxDepth + 1;
};
  1. 实现一个组件
CheckboxGroup
x  1,2,3
--------
x  1, 3
x  
x

<CheckboxGroup v-model='selected' option={option}/>
option = [
{label: xxx, value:1},
{label: xxx, value:2},
{label: xxx, value:3},
]

selected  =[1,2]

三面

  1. 请实现一个cacheRequest方法,保证当使用ajax(请求相同资源时,此题中相同资源的判断是以url为判断依据),真实网络层中,实际只发出一次请求(假设已存在request方法用于封装ajax请求)?
const a = cacheRequest('/api/1')
const b = cacheRequest('/api/1')
const c = cacheRequest('/api/1')
  • url为key存储promise
  1. 介绍下cloud hybrid方案
  2. 跨域方案

阿里

阿里是四轮技术面,一轮hr,流程走了快一个月,最后是通过了,三面四面当时没有记录下来,题目暂时记不住了,一二面难度中等,三面稍难,四面主要是项目,开放性的问题。

一面

  1. for in和for of区别
  2. 响应式布局,rem原理
  3. vue中全局api confirm如何实现
  4. 全局拦截弹窗
  5. webpack loader 和plugin区别,常用loader,实现一个上传至cdn的应该在哪里实现?
  • 常用loader:
    • css:style-loader css-loader less-loader postcss-loader
    • 图片处理:file-loader url-loader
    • 编译:babel-loader typescript-loader vue-loader
    • 代码检测:eslint-loader
  • 常用plugin:
    • html-webpack-plugin:生成html和自动引入js css
    • extract-text-webpack-plugin mini-css-extract-plugin: css提取到单独的文件
    • copy-webpack-plugin: 拷贝资源
    • clean-webpack-plugin:
    • uglifyjs-webpack-plugin/terser-webpack-plugin:代码压缩
    • DefinePlugin:定义变量
    • SplitChunksPlugin: 代码分割
  1. 一个严格递增数列,末尾部分移动到最前端,寻找最小值的位置,语言不限 例如 输入: [4,5,6,1,2,3] 输出: 3 详细 对于一个严格递增数列123456, 某末端移动到最前端,变为了456123, 寻找最小值点1的位置3。

  2. 前端页面静态资源和html这类文件发布顺序有什么要求? 8.实现一个前端缓存模块,主要用于缓存 xhr 返回的结果,避免多余的网络请求浪费,要求:

  1. 生命周期为一次页面打开
  2. 如果有相同的请求同时并行发起,要求后发起的能挂起并且等待另外第一个发起的请求返回并读取该缓存。

二面

  1. 事件冒泡机制
  2. flex原理
  3. 自响应原理
  4. 给定一个排序数组,和一个sum值,选择其中2个等于sum的值
  5. 浏览器缓存

腾讯

腾讯这个投递简历投错了,这个明显跟自己想去的不一样,所以over了,后来转了其他部门,但是当时腾讯的hc调整,没有再继续面了。有点浪费机会了。

一面

1 test(1)(2)(3)

function test(x) {
    return function (y) {
      if (!y) {
        return x;
      }
      return test(y);
    };
}
  1. 遍历对象:
  • for in: 遍历自身和继承的可枚举的属性
  • Object.keys: 遍历自身的可枚举属性
  • Object.getOwnPropertyNames: 包含自身的可枚举不可枚举的属性
  • 以上三个都不包含symbols属性
  • Object.getOwnPropertySymbols: 自身的symbol属性
  • Reflect.ownKeys: 包含自身的可枚举、不可枚举、symbol属性

二面

  1. 项目居多,技术问题少,最后聊着发现跟我预想的职位不一样,后面流程就不走了,其实当时面的还挺好,是有可能拿offer的。

头条

头条的面试我放最后面的,因为都说算法多,想多练几道,但事实也没练几道==,头条的面试,确实编程题多,三面遇到了最难的题,没写出来,只是说了思路。题记录的不全。

一面

  1. 项目有挑战的地方
  2. 时序题
console.log('script start');
setTimeout(function() {
console.log('setTimeout');
}, 0);
Promise.resolve().then(function() {
console.log('promise1');
}).then(function() {
console.log('promise2');
});
console.log('script end');
  1. rn底层通信机制
  • js->native:
    • 初始化时,native会将可以调用的模块注入到js环境中,保存在一个全局变量里global的__batchedBridgeConfig,里面就包含了模块、方法和调用方式,前端根据配置表生成调用方法,全部放到nativemodules中,前端就可以调用了
    • 调用时直接调用nativemodules中的方法,最后会走到enqueueNativeCall,将模块id、方法id、回调id进入三个队列中
    • 大于5ms时就执行原生的方法nativeFlushQueueImmediate
    • 小于的话是等待native调用
    • native拿到id就在端的配置表中,找到对应的模块和方法,进行调用
    • jscallback,也是每个callback一个id,自己存一份,将id传给native,native调用时将id回传给js,js根据id查找对应的callback并执行
  • native->js:
    • global 的__batchedBridge存放端可以调用前端的地方
    • native调用js的方法执行
  1. 小程序原理
  2. 单链表反转
  3. 实现数字千分位格式输出 format(num) 输入:123456.789 输出:'123,456.789'
  4. 实现发布订阅模式,取消监听有没有更好的方法?
  5. 基于Promise 实现 Promise.all(promises)
  6. 二叉树层序打印

二面

  1. jssdk项目, 描述表如何维护?
  2. 端通信的方式,iOS和android?小程序,rn,iframe端通信缺点
  3. cloud hybrid方案整个流程
  4. timeformat时间格式化的一个题

三面

  1. 项目相关,希望有宏观的认识,整体都比较清楚,但自己不太清楚
  2. 公司的程序员不够用了,决定把产品经理都转变为程序员以解决开发时间长的问题。
在给定的网格中,每个单元格可以有以下三个值之一:
值 0 代表空单元格;
值 1 代表产品经理;
值 2 代表程序员;
每分钟,任何与程序员(在 4 个正方向上)相邻的产品经理都会变成程序员。
返回直到单元格中没有产品经理为止所必须经过的最小分钟数。如果不可能,返回 -1。

console.log(turn2Coder([[0,2],[1,0]])); // -1 
console.log(turn2Coder([[2,1,1],[1,1,0],[0,1,1]])); // 4