跳到主要内容

面经

· 阅读需 33 分钟
早期黑历史

实习面经

腾讯 WXG 一面

很久以前面的,第一次面试,失败原因总结:过于紧张,基础不扎实。

  1. 自我介绍。

  2. 讲一讲Vue的源码。我直接从Vue实例的创建开始,打算一步步的解释,面试官打断说让我讲一下Vue的架构(应该是指Observer, Compiler, Watch这三部分吧?)

  3. 浏览器的渲染原理。

    我以为问的是生成DOM渲染树,布局和绘制,以及回流和重绘的知识点。结果面试官又问我:HTML是怎么转换成DOM树的,然后我就蒙圈了...

    之后谷歌了一下,大概的步骤如下

    1. 编码
    2. 预解析
    3. 标记
    4. 构建树

    详细的构建过程

  4. Script标签对浏览器的阻塞问题。参考

    Script脚本的执行会阻塞html的解析,外链script的下载也会阻塞。

    那么多个script标签代码的执行,也必然是顺序执行,多个script外链的请求到底是串行还是并行的呢?

    比较容易混淆,所以容易会认为请求是串行的,因为

    <script type="text/javascript" src="./test.js"></script>
    <script type="text/javascript" src="./test2.js"></script>

    可能会认为下面html的文档的解析要等到上面script执行完才会开始,因为会阻塞。

    但其实请求是并行的。

    因为html解析成dom的时候会先进行预解析。

  5. 前端常见加密,比如MD5。

    当初面的时候很紧张,没答好。

  6. 问:闭包会造成什么?

    结果我脱口而出,会造成内存泄漏...但实际上闭包会造成内存泄漏这种说法是由于以前IE浏览器的BUG。现在很多人都说闭包会造成内存泄漏,实在是以讹传讹,瞎写代码才会(逃

  7. 性能优化手段。

以下是春招的面试经历

腾讯 CSIG 一面

一面过了,感谢面试官

  1. 介绍一下自己,什么时候开始学习前端的,学习前端的方式,平时都看过哪些书?

    大概讲了一下自己的学习经历,看过什么书籍。

  2. 问高程上我觉得印象深刻的地方?

    我随便说了两个,原型链和this,面试官随便问了点相关知识。

    1. 实现私有的方法/属性,我只回答了两种,一个是提前约定好的私有变量,比如_开头的变量;或者用闭包实现。

      不过答的时候说的有点混乱。

      闭包:

      // 闭包一,实例的私有属性
      class Person {
      constructor() {
      let value = 233
      this.getValue = function() {
      return value
      }
      }
      }

      // 闭包二,原型对象的私有属性
      const Person = (function () {
      let value = '111'
      class Person {
      getValue() {
      return value
      }
      }
      return Person
      })()

      也可以使用Symbol来实现(比较推荐)

      const Person = (function () {
      let s = Symbol()
      class Person {
      constructor() {
      this[s] = '111'
      }
      getValue() {
      return this[s]
      }
      }
      return Person
      })()
    2. ES5实现继承的方法,构造继承,原型链继承,组合继承,寄生组合继承。

    3. this的原理,call,apply,bind的区别。

  3. 垂直居中的几种方法。

    为什么下面的margin可以居中?不太清楚,只知道有这种技巧。

    .outer {
    display: flex;
    }

    .inner {
    margin: auto;
    }

    网上搜到了一个讲这个的,还挺实用的

    块级元素中,当margin-top和margin-bottom为auto时,他们的值为0,所以无法实现垂直居中。

    而在flex内部,当我们设置margin: auto的时候,会将剩下的空闲空间(水平与垂直)分配给该元素的margin。

    因此,借由flexmargin,我们可以更加简单的实现某些功能,比如一个普通的导航栏

    <ul class="g-nav">
    <li>导航A</li>
    <li>导航B</li>
    <li>导航C</li>
    <li>导航D</li>
    <li class="g-login">登陆</li>
    <li>注册</li>
    </ul>
    <style>
    .g-nav {
    display: flex;
    padding: 0;
    margin: 0;
    list-style: none;
    }
    .g-nav li {
    padding: 0 20px;
    }

    .g-login {
    margin-left: auto;
    }
    </style>

margin-top为负值,除了绝对定位还有哪些地方碰到过?说了个双飞燕/圣杯布局,不太清楚其他的应用场景。

  1. 问我平时写不写HTML标签/CSS,这问题有点懵。然后面试官解释说,有的地方写项目代码分工明确,有的人只写CSS,有的人只写JS。

    问前端语义化标签,什么时候你会用到这些标签,语义化标签的好处/作用?

    这个不太清楚怎么回答,我说了个对搜索引擎友好?晚点查一查。

    1. 搜索引擎友好
    2. 便于团队开发和维护
    3. css未加载时也有清晰的结构
  2. 怎么用正则判断当前域名是否为qq.com,或者xxx.qq.com。

    我用的split做的...很繁琐,边界条件的检查也很麻烦,还是正则好。

    正则的写法

    function isUrl(url) {
    return /^https?:\/\/(.+\.)?qq\.com/.test(url)
    }
    isUrl(location.href)
  3. 响应状态码,200(from disk cache),200(from memory cache),304的区别。

    见本博客的Http缓存一节。

    至于from disk cache 和 from memory cache的区别。

    比如第一次打开新页面(有缓存),资源会从硬盘中读取;而如果在已经打开的页面刷新,资源会从内存中读取。

Etag是什么?

通常就是一个资源的哈希值吧。

  1. try...catch...中如果异步代码出错怎么办?如:

    try {
    throw new Error('111')
    } catch (e) {
    console.log(1)
    }
    // 捕捉到异常,输出1

    try {
    setTimeout(() => {
    throw new Error('222')
    })
    } catch (e) {
    console.log(2)
    }
    // 未能捕捉到异常,不输出2

    怎么办?

    async function A() {
    try {
    await new Promise((resolve, reject) => {
    setTimeout(() => {
    reject(new Error('222'))
    })
    })
    } catch (e) {
    console.log(e)
    }
    }

    当await后面的promise状态为reject时,会抛出错误。所以我们可以搭配async/await和promise来进行异步的错误捕捉。

  2. 为什么移动端以前有300ms的问题,原理?fastclick的原理答不上来。

    移动端,当用户点击屏幕的时候,先后触发touchstart, touchmove, touchend, click。其中touchend和click的间隔为300秒,这是为了处理移动端的双击缩放。

    fastclick原理。在touchend阶段,会调用e.preventDefault,然后使用document.createEvent创建一个事件,并在目标元素上触发。

  3. XSS的原理,如何防御XSS?为什么换成实体字符就好了?

    虽然我大概了解一些,但总感觉答的不是很好。

    字符<会被当成标签,而实体字符只会当成纯粹的文本。

  4. 找出数组中n项,n项的和为m。

    解答过程我写在编程题一节。

腾讯 CSIG 二面

分享屏幕,写代码。

  1. 问我的前端是怎么学习的...问了挺多,各种细枝末节的东西。

  2. 创建一个 Person 类,其包含公有属性 name 和私有属性 age 以及公有方法 setAge ;创建一个 Teacher 类,使其继承 Person ,并包含私有属性 studentCount 和私有方法 setStudentCount 。

    const Person = (function () {
    let s = Symbol('age')
    class Person {
    constructor(name) {
    this.name = name
    }

    setAge(newAge) {
    this[s] = newAge
    }

    getAge() {
    return this[s]
    }
    }

    return Person
    })()

    const Teacher = (function () {
    let studentCount
    const setStudentCount = (count) => {
    studentCount = count
    }
    return class Teacher extends Person {
    constructor(name) {
    super(name)
    }
    set(count) {
    setStudentCount(count)
    }
    }
    })()

    以上是我面试的时候写出来的,但写的挺怪的...回来想了想,可以改写如下代码。

    const [Person, Teacher] = (function () {
    const s = Symbol('age')
    const c = Symbol('studentCount')
    const setStudentCount = Symbol('setCount')
    class Person {
    constructor(name, age) {
    this.name = name
    this[s] = age
    }

    setAge(age) {
    this[s] = age
    }
    }

    class Teacher extends Person {
    constructor(name, age, count) {
    super(name, age)
    this[c] = count
    }
    [setStudentCount](count) {
    this[c] = count
    }
    set(count) {
    this[setStudentCount](count)
    }
    }
    return [Person, Teacher]
    })()
  3. 输入框输入值后,数组内找值, 返回匹配的字符串。类似百度输入框的效果。

    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>

    body {
    margin: 0;
    position: relative;
    height: 100vh;
    }


    .center {
    box-sizing: border-box;
    width: 400px;
    padding: 4px 6px;
    position: absolute;
    top: 35%;
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    flex-direction: column;
    }
    .input {
    padding: 10px 4px;
    }
    .list div {
    padding: 10px 6px;
    border: 1px solid #ddd;
    }

    .list div:hover {
    background: grey;
    cursor: pointer;
    }

    .list div:not(:last-child) {
    border-bottom: 1px solid #ddd;
    }
    </style>
    </head>
    <body>
    <div class='center'>
    <input type="text" class='input'>
    <div class='list'>

    </div>
    </div>

    <script>

    const dataList = ['航空母舰','航空吴六', '无关数据', '航x空', '航空飞行器']
    const el = document.querySelector('.input')
    const list = document.querySelector('.list')


    function debounce(fn, wait) {
    let timer
    return function () {
    timer && clearTimeout(timer)
    timer = setTimeout(() => {
    fn.call(this)
    }, wait)
    }
    }

    function getData() {
    list.innerHTML = ''
    let value = el.value
    let ret = []
    for (let i of dataList) {
    if (i.includes(value)) {
    ret.push(i)
    }
    }

    ret.forEach(item => {
    let el = document.createElement('div')
    el.innerText = item
    list.appendChild(el)
    })
    }

    el.addEventListener('input', debounce(getData, 1000))
    </script>
    </body>
    </html>

  4. 请写一个函数,计算一篇英文文章中出现次数最多的单词及出现次数。

    function getWordAnd(str) {
    let arr = str.split(/[,\.\s]/)
    let map = new Map()
    let ret = [[], 0]
    arr.forEach(word => {
    if (word !== '') {
    if (map.has(word)) {
    let times = map.get(word)
    map.set(word, times + 1)
    } else {
    map.set(word, 1)
    }
    }
    })
    for (let [i, j] of map) {
    if (j > ret[1]) {
    ret[0] = [i]
    ret[1] = j
    } else if (j === ret[1]) {
    ret[0].push(i)
    }
    }
    return ret
    }
  5. 问我有什么上线的项目,我说以前的现在都下线了...只有源码。简历是你自己写的吗,答我是fork的...博客呢?我用vuepress搭的,以前写过ghost的主题。(总之就是被吐槽项目经历太少

  6. 有什么想问的吗?

    面试官觉得我哪里需要提高,面试官说我还行,不过项目经历太少了。然后我说所以我想去实习提高项目经历,被教训了一顿...真正的高手自己一个人随便写项目,根本不用实习。(唉,我太菜了

希望能过吧,我一定好好写项目...

腾讯 CSIG 三面

  1. 问项目,我这块答的好差,唉。
  2. Websocket原理,socket.io除了基本的那几个还有哪些Api(太久没用socket.io了,根本不记得啊...),如果客户端突然断网了怎么办(应该是问的心跳包,忘记具体的流程了)
  3. 海量日志中找ip最多出现次数,不会
  4. 智力题(此时我心态已经失衡...),100人教室70人喜欢足球,80人喜欢篮球,问同时喜欢足球和篮球的人数。这时候我的心态真的是超级爆炸,随便说了个答案,唉,暴露了自己智商低的事实。
  5. Http1.1和HTTP2.0的区别,头部有哪些,然后问我现在主要用哪个,我说2.0,结果她问为什么我们网校的网站基本用的1.1...

表现贼差,结果等了一个星期竟然过了!我爱腾讯!

腾讯 CSIG HR面

  1. 自我介绍

  2. 印象深刻的项目,负责怎样的角色

  3. 考不考研

  4. 有没有女朋友

  5. 还有哪些在流程中

  6. 实习的情况,课多不多,可不可以远程实习

  7. 想问什么

  8. 口头offer

感谢腾讯!

阿里 钉钉 一面

  1. 自我介绍

  2. 移动端和PC端的一些区别,技术的选型的区别,兼容性方面的问题。Iphone5和Iphone6的像素不同应该如何处理。

  3. Webpack的按需加载 imort() 和 代码分割

  4. 单页应用和多页应用的优缺点对比。

    单页应用有SEO问题,那么前端通常如何解决SEO的问题呢,没答上来(服务端渲染和同构)

    单页应用的好处有哪些,有点忘了(囧),前后端分离。

  5. 三列布局,flex,圣杯布局,双飞燕布局。

  6. 虚拟DOM的优缺点

    当我们使用虚拟DOM,虚拟DOM的Diff后,我们还是要操作真实的DOM。

    优点:保证性能的下限。我们操作虚拟DOM后,框架底层会自动操作真实的DOM,因此我们可以保障性能的最下限

    缺点:正是同样的道理,虚拟DOM可以保障性能的最下限的前提,是其失去了性能的最上限。如果有一个大牛,代码非常牛逼,它操作真实DOM就可以实现性能最大化。但是虚拟DOM却失去了最大化的可能性。

  7. 编程题

    //评测题目: 无
    /*

    题目
    实现一个方法,用于比较两个版本号(version1、version2)
    如果version1 > version2,返回1;如果version1 < version2,返回-1,其他情况返回0。版本号规则`x.y.z`,xyz均为大于等于0的整数,至少有x位
    输入输出样例
    (如果题目不是实现函数,可以用其他更直观的方法描述预期行为)
    样例一
    输入:compareVersion('0.1', '1.1.1')
    输出:-1
    样例二
    输入:compareVersion('13.37', '1.2 ')
    输出:1
    样例三
    输入:compareVersion('1.1', '1.1.0')
    输出:0
    */

    function compareVersion(v1, v2) {
    let arr1 = v1.split('.')
    let arr2 = v2.split('.')
    let maxLength = Math.max(arr1.length, arr2.length)
    for (let i = 0; i < maxLength; i++) {
    let a = arr1[i] || 0 // 开始给他看的时候没加这个。因为长度不一定一样,可能是undefined
    let b = arr2[i] || 0
    if (a > b) return 1
    if (a < b) return -1
    }
    return 0
    }
  8. 唠嗑。阿里钉钉最近的情况。

阿里插曲1:面的时候表现很不错,结果之后发现流程上变成“已回绝”,失眠,难受了一晚上。

结果第二天的时候和我说,只是流程打回去了而已,对我没影响(???难受一晚上也叫没影响?)

阿里 钉钉 二面

阿里插曲2:电话打过来问我有没有注册钉钉,我说没有(= =事后发现自己是有注册过的,囧)...

  1. 自我介绍。问成绩。

  2. 计算机网络七层介绍,TCP和UDP使用场景的区别,DNS的TTL是什么。

    说我用谷歌,那我是怎么翻墙的... 。我说我之前搭过,后来挂了就用别人的。面试官问我为什么我的就挂了,其他人的就没挂(谁的机场这么稳定?)。

  3. 键盘和CPU是如何相连的,交互原理。

  4. 市面上硬盘主要是什么接口。

  5. 一个CPU是怎么进行进程直接的切换,以及资源是如何分配的,CPU怎么知道切换哪个进程。

    网卡是如何做到同时听音乐和下载东西的。

  6. 图论,有限图中两点最小距离的算法。

  7. 常见排序算法

  8. 前端性能优化

  9. 印象深刻的项目

  10. 兴趣爱好。我说动画啥的,他说他指的是硬件相关的爱好...有没有写过什么机器人呀之类的。然后被吐槽我的爱好优点像文科生(这算不算刻板印象?我这个人爱好广泛的很,小说、动画、漫画、音乐、游戏、电影我都很喜欢,我还想学好英语/日语,想学好画画,围棋业余三段,热爱日麻,还玩过一阵子德州扑克,经常看新闻,甚至开始对历史感兴趣了,特别爱任天堂游戏。难道理科生就一定要喜欢硬件吗?)

阿里插曲3:交谈中大概谈到我写的博客,很明显感觉到面试官的轻视,他用了“从其他地方复制过来”这一词,仿佛这些东西都是没过我脑子就复制过来一样,服了。

阿里 钉钉三面(交叉面)

二面很久后突然说要面,这一面是我面试凉的最快的一次,随便写点。

  1. 自我介绍,项目
  2. 数据结构,数组和链表区别,平衡二叉树等。
  3. 排序算法。
  4. 数据库,索引,事务,死锁。

字节跳动 一面

  1. 自我介绍,介绍完直接发个我五道题(太吓人了)

  2. 用CSS实现一个开关样式,hover时触发,滑块为正方形。

      1. 开关动作均有动画过度(滑块移位、背景色)
      1. 只用一个dom元素实现
      2. 开关的高度是固定的,但宽度不固定,即宽度为未知父元素的100%,宽度始终大于高度

    写出来了,但不够优雅...以下是修改后的代码

    <div class='contain'>

    </div>
    <style>
    .contain {
    --padding: 4px;
    --height: 40px;
    position: relative;
    width: 100px;
    height: var(--height);
    padding: var(--padding);
    background: grey;
    transition: all .3s;
    }

    .contain:hover {
    background: green;
    }

    .contain::before {
    content: '';
    position: absolute;
    z-index: 1;
    right: calc(100% - 40px - var(--padding));
    height: var(--height);
    width: var(--height);
    transition: all .3s;
    background: #fff;
    }
    .contain:hover::before {
    right: var(--padding);
    }
    </style>
  3. // 写出下面这段代码打印的结果
    var result = [];
    var a = 3;
    var total = 0;
    function foo(a) {
    var i = 0;
    for (; i < 3; i++) {
    result[i] = function() {
    total += i * a;
    console.log(total);
    }
    }
    }

    foo(1);
    result[0]();
    result[1]();
    result[2]();

    // 3, 6, 9
    // 因为i始终是3,差点上钩
  4. // 写出下面这段代码打印的结果
    async function async1() {
    console.log('async1 start');
    await async2();
    console.log('async1 end');
    }

    async function async2() {
    console.log('async2 start');
    return new Promise((resolve, reject) => {
    resolve();
    console.log('async2 promise');
    })
    }

    console.log('script start');

    setTimeout(function() {
    console.log('setTimeout');
    }, 0);

    async1();

    new Promise(function(resolve) {
    console.log('promise1');
    resolve();
    }).then(function() {
    console.log('promise2');
    }).then(function() {
    console.log('promise3');
    });

    console.log('script end');


    // 答案
    script start
    async1 start
    async2 start
    async2 promise
    promise1
    script end
    promise2
    promise3
    async1 end
    setTimeout

    // 但我之前把async1 end写在promise2前面了,想了想才发现自己错在哪里。

    function A() {
    return new Promise((r) => {
    r()
    })
    }
    console.log(A())
    // Promise<resolved>

    async function A() {
    return new Promise((r) => {
    r()
    })
    }
    console.log(A())
    // promise<pending>

    // 可以看到async函数和普通函数最终返回的promise状态是不同的。
    // 我们可以再做一个实验。
    let p
    function A() {
    p = new Promise((r) => {
    r()
    })

    return p
    }
    let a = A()
    console.log(a === p) // true

    let p
    async function A() {
    p = new Promise((r) => {
    r()
    })

    return p
    }
    let a = A()
    console.log(a === p) // false

    // 个人观点:
    async function A() {
    return new Promise() {}
    }
    // 执行函数A返回的promise初始状态是pending,并且会生成一个微任务放进微任务队列,当执行该任务后状态才会改变
    // 现在终于可以回答下面两个代码为什么输出顺序不同了

    async function A() {
    await B()
    console.log('a')
    }

    function B() { // 此时不是async函数
    return new Promise((r) => {
    r()
    })
    }
    A()

    new Promise((resolve) => {resolve()}).then(() => {
    console.log('b')
    })

    // a b

    // ------------ 分割线 --------------

    async function A() {
    await B()
    console.log('a')
    }

    async function B() {
    return new Promise((r) => {
    r()
    })
    }
    A()

    new Promise((resolve) => {resolve()}).then(() => {
    console.log('b')
    })
    // b a

  5. // 实现一个二进制加法,输入输出均为二进制字符串
    function binaryAdd(num1: string, num2: string): string {
    // TODO
    }
    //Example
    binaryAdd('1010', '111') // '10001'

    // 其实就是两数相加,只是换成了二进制而已
    function binaryAdd(num1, num2) {
    let carry = 0
    let ret = []
    const [len1, len2] = [num1.length, num2.length]
    const maxLen = Math.max(len1, len2)
    num1 = num1.padStart(maxLen, '0')
    num2 = num2.padStart(maxLen, '0')
    let arr1 = num1.split('')
    let arr2 = num2.split('')
    for (let i = maxLen - 1; i >= 0; i--) {
    let [n1, n2] = [arr1[i], arr2[i]].map(i => Number(i))
    let sum = n1 + n2 + carry
    carry = sum >= 2 ? 1 : 0
    sum %= 2
    ret.unshift(sum.toString())
    }
    if (carry) ret.unshift('1')
    return ret.join('')
    }
  6. // 实现一个带并发限制的异步调度器Scheduler,保证同时运行的任务最多有两个。完善代码中Scheduler类,使得以下程序能正确输出
    class Scheduler {
    add(promiseCreator) {
    // TODO
    }
    // TODO
    }
    const timeout = (time) => new Promise(resolve => {
    setTimeout(resolve, time)
    })
    const scheduler = new Scheduler();
    const addTask = (time, order) => {
    scheduler.add(() => timeout(time))
    .then(() => console.log(order))
    }

    addTask(1000, '1')
    addTask(500, '2')
    addTask(300, '3')
    addTask(400, '4')
    // output: 2 3 1 4
    // 一开始,1、2两个任务进入队列
    // 500ms时,2完成,输出2,任务3进队
    // 800ms时,3完成,输出3,任务4进队
    // 1000ms时,1完成,输出1
    // 1200ms时,4完成,输出4

    // 没做出来,讲了个大概思路,面试官说这道是附加题,写法比较巧妙。

  7. 浏览器/Node的事件循环

  8. 浏览器的渲染机制

  9. CSRF的原理和防御

  10. 有什么想问的吗

字节跳动 二面

  1. 自我介绍

  2. 把数字用千分位分割,如15000000分割为15,000,000

    function transform (num) {
    let arr = []
    while (num >= 1000) {
    let value = num % 1000
    num = num / 1000
    if (value >= 100) {
    value = '' + value
    } else if (100 > value && value >= 10 ){
    value = `0${value}`
    } else {
    value = `00${value}`
    }

    arr.unshift(value)
    }
    num = '' + num
    arr.unshift(num)
    console.log(arr.join(','))
    }
    transform(15000000)

    问:除了用数字,还有什么方便的方法吗?

    之后查了资料,发现可以通过toLocaleString或正则来实现

    正则: num.toString().replace(/\d{1,3}(?=(?:\d{3})+$)/g, '$&,')

  3. HTTP2.0和1.1的对比,优点?缺点?

  4. 服务端推送的资源放在哪里?

  5. 浏览器缓存,你的JS资源是如何使用不同的缓存策略的呢?不太清楚,我说的用webpack进行代码分割,然后分别使用不同的策略

    通常过期时间设置为多久?

  6. 了解哪些跨域。其中cors,post方法算简单请求吗,带cookie需要预检吗?

  7. 之前有提到service worker,有了解吗(没,自己给自己挖坑...)

  8. Node有了解吗,一些Node的优缺点(密集型),Node是单进程还是多进程。

    node是i/o密集型,但处理cpu密集型任务很吃力。面试的时候好像答反了。。。

    Koa,Egg有了解过吗。

  9. 算法题:

    实现js方法,查找第一个缺失的正整数。 时间复杂度O(n) ,空间复杂度 O(1)

    Example 1:

    Input: [1,2,0] Output: 3

    Example 2:

    Input: [3,4,-1,1] Output: 2

    Example 3:

    Input: [7,8,9,11,12] Output: 1

    假设传入的数组长度在10000以内。

    提示:数学上最小正整数是1

不会,哭了。

  1. 前端方向你希望往哪边发展?我说了webgl,因为比较花哨。

  2. 有什么想问的吗?

    问自己的不足。

    问:你们阿里的后端用的哪些(面试官惊了:同学你串台了,这里不是阿里...)

美团 一面

  1. 自我介绍

  2. 介绍项目,觉得有哪些难点。

  3. Node事件循环,Koa的洋葱圈模型,Express和Koa的区别

  4. Node中有哪些全局变量

  5. 项目通常如何部署,pm2,很久以前用过。

  6. Vue和React对比

  7. Vuex的单向流动是如何实现的,我说熟悉Redux,扯到了redux的一些东西。

  8. HTML5有哪些新属性,Doctype的作用,Storage和cookie的对比,localStorage和sessionStorage的对比。

  9. Flex有哪些属性

  10. ES5的继承

  11. 跨域的介绍

  12. sameSite属性,最近默认值变成了lax

  13. linux用过吗,如何删某端口上的进程,ps aux | grep node查看node的进程。

  14. git有用过吗,git rebase知道吗

  15. 一个有序,可重复的数组[1, 2, 3, 3, 3, 3, 4, 5, 5, 6],找到5最后的位置,空间复杂度logn

    二分,不让用lastIndexOf

  16. 有什么想问的吗? 问技术栈,美团主要用的vue,也有rn,小程序。

都是些基础问题。

美团 二面

  1. 学习前端的方式
  2. 讲个人理解中的前端。
  3. ES5和ES6的类
  4. Vue和React,更熟悉哪个。React的setState是同步的吗?二者的虚拟DOM之间有什么不同吗
  5. Vue双向绑定的实现原理
  6. 中间人攻击了解吗?原理
  7. 最近有了解过新技术吗
  8. 了解JS在浏览器的执行的底层原理吗(应该是想问V8啥的)
  9. 操作系统进程的通信方式
  10. 两个单向链表求交点
  11. n级台阶,一次可以走一阶或两阶,有多少种方式走?
  12. 二叉树的根是数组中的最大元素。左子树是通过数组中最大值左边部分构造出的最大二叉树。 右子树是通过数组中最大值右边部分构造出的最大二叉树。
  13. 意向各种城市,有在面其他公司吗,回答说拿了TX的offer了已经
  14. 想问的问题,无

面累到了,就算能让我过我也不想面了...

美团 HR面

二面过了挺久,突然打个电话说我过了,不过offer被我拒了。

校招面经

六个小时结束了akara的秋招。

字节跳动 一面

  1. 自我介绍,介绍项目。

  2. 几个小题目,看代码说结果

  3. [] == ![] [] == []的值(事后发现自己完全答反,万恶的隐式转换,神奇的JS)

  4. new 操作符原理

  5. 盒模型 content-boxborder-box

  6. display:none;visibility: hidden;opacity:0的区别

  7. 事件模型,看代码说结果

  8. 状态码301,302,304

  9. 知道referer头部吗,直接请求服务器时referer是多少,顺便聊了其在CSRF中的作用

  10. 后端怎么让浏览器中的Cookie过期

  11. CSS动画,transitionanimation,哪一个性能更好

  12. Koa和Express的区别,以及Koa中间件的原理

  13. Vue的v-model的原理,Vue实例是怎么拿到data属性的

  14. Hash和History模式的区别,原理

  15. React的Fiber的原理,知道怎么实现的吗,是否了解Hook的实现原理

  16. 聊了一下Redux和React-Redux

  17. 给定一个字符串,输出该字符串所有排列的可能。如输入“abc”,输出“abc,acb,bca,bac,cab,cba”。

    function fullpermutate(str) {  var result = [];  return result;}
  18. 多行字符串转二维数组

    const str=`
    1 21 3

    4 5 6
    7 8 9
    `
    [
    ['1', '12', '3'],
    ['4', '5', '6'],
    ['7', '8', '9'],
    ]
  19. 获得页面所有节点数

  20. 有什么问我的吗

字节跳动 二面

  1. 聊了一下项目

  2. 算法题。判断堆栈的出栈顺序是否合理。

    validStack(inArr, outArr)
  3. 两个同域的页面之间的通信。postMessage,storage(之前没了解过,原来这个可以监听的?)

  4. 如何统计用户的浏览时长,要考虑到用户会切换页面,缩放页面等。多个点进行上报时,如何区分这些数据来自于同一个会话?

    https://yq.aliyun.com/articles/635301

  5. 实现一个sleep方法

  6. 函数防抖,函数节流

  7. HTTP和Websocket的联系

  8. 重排,重绘,合成层

  9. 了解过puppeteer吗

算法比较拉跨...

字节跳动 三面

  1. 自我介绍

  2. 聊项目的一些东西,难点啥的,解决方案。

  3. 写代码。倒计时 截止时间 2020年11月11日 0点

    显示 “剩余XX天XX时XX分XX秒”

    每秒刷新一次

  4. 怎么学习前端的,聊一下接下来的打算

字节跳动 HR面

基本都是聊家常了。