# 实习面经

# 腾讯 WXG 一面

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

  1. 自我介绍。

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

  3. 浏览器的渲染原理。

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

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

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

    详细的构建过程 (opens new window)

  4. Script标签对浏览器的阻塞问题。参考 (opens new window)

    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;
    }
    

    网上搜到了一个讲这个的,还挺实用的 (opens new window)

    块级元素中,当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是什么?

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

  4. 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来进行异步的错误捕捉。

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

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

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

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

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

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

  2. 找出数组中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 (opens new window)] Output: 3

    Example 2:

    Input: [3,4,-1,1 (opens new window)] Output: 2

    Example 3:

    Input: [7,8,9,11,12 (opens new window)] Output: 1

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

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

    不会,哭了。

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

  11. 有什么想问的吗?

    问自己的不足。

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

# 美团 一面

  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面

基本都是聊家常了。

上次更新时间: 8/24/2020, 9:01:54 AM