2021年魔都20+公司前端面经

674 阅读9分钟

从2月底到现在,我面试了超过20家上海各种各样的互联网公司。

按照公司整理了一下面试题。

叮咚买菜(一面挂)

  • 水平垂直居中方式

  • 只用一个div实现关闭按钮

    • 通过伪元素,::before 实现一横,::after 实现一横,border 做一个圆圈;
    • 或者使用 unicode 码实现 x
  • 箭头函数(箭头函数有没有arguments)

  • 父组件中定义一个子组件,子组件中有useEffect(,[]),父组件更新5次,子组件useEffect会执行几次,怎么让它只执行一次?

  • useEffect函数回调的返回值的作用

  • 深拷贝,JSON.parse能不能保存正则

  • class component和hook component的差别是什么?

  • react的性能优化/pureComponent

  • 组件懒加载

  • 首屏优化的方案

  • 如果实现一个弹窗组件只需要import一次,就可以在项目各处使用

  • react fiber

  • 斐波那契数列防止溢出

美团(一面挂)

console.log(1);

setTimeout(() => {

  console.log(2);

  Promise.resolve().then(() => {

    console.log(3)

  });

});

new Promise((resolve, reject) => {

  console.log(4)

  resolve(5)

}).then((data) => {

  console.log(data);

  Promise.resolve().then(() => {

    console.log(6)

  }).then(() => {

    console.log(7)

    setTimeout(() => {

      console.log(8)

    }, 0);

  });

})

setTimeout(() => {

  console.log(9);

})

console.log(10);

以下代码存在什么问题?

props

const c = this.state.a + this.props.b

this.setState({
    a: c
})

计算三个数组的差并交集合,要考虑数组数量扩展

const a = [1, 2, 3, 4, 5, 6]

const b = [1, 2, 4, 6, 7, 8]

const c = [1, 3, 5, 7, 8, 9]

交集:[1]

并集:[1, 2, 3, 4, 5, 6, 7, 8, 9]

差集:[9]

angular怎么实现双向数据绑定

js继承实现的方式

首页白屏优化

缓存使用

react setState是不是异步的

this.setState((state, props) => ({
  counter: state.counter + props.increment
}));

react 虚拟DOM

DOM diff怎么做的

echarts可视化,一个图表点击,当前图标高亮,让其他图标不高亮

proxy

字节(一面挂)

CSS

  1. css实现垂直水平居中
  2. css盒子模型/标准盒子和怪异盒子差别
  3. css实现三角形
  4. rem/em/vh/wh的差别
  5. calc/support/@media

JS

  1. 熟悉的ES6属性(讲了解构,async,await)
  2. generator babel之后是什么样子
  3. promise.all、race
  4. 实现一下防抖节流函数

HTTP

  1. 缓存
  2. 为什么有同源策略(回答csrf攻击等)
  3. 跨域方案
  4. HTTP2.0讲一下

算法题

无序数组找第K大个元素

哈罗出行

function Foo(){
	getName = function(){ alert(1); }
  return this;
}

Foo.getName = function(){ alert(2);}
Foo.prototype.getName = function() { alert(3);};
var gettName = function(){alert(4);};
function getName(){alert(5);}
//以下输出什么
Foo.getName();
getName();
Foo().getName();
getName();
new Foo.getName();
new Foo().getNmae();
new new Foo().getName();

喜马拉雅

手写Array.reduce

多次bind能否生效

实现eventEmiter(观察者模式)

手写排序

首屏优化

HTTP缓存

HTTP缓存的优先级

AMD和CMD的差别

小红书

无序数组找第K大个元素,尽可能多方案

[a,b,c]排列组合有多少种,顺序不敏感,ab和ba是一种

首屏性能优化

前端缓存

SSR

爬虫

事件循环

美团

手写JS继承

两列布局,左边固定200px,右边自适应

echarts问题,如何设置

setState,直接引用this.state的问题,以及解决方法

模块加载,AMD和CMD的差别

事件循环

首屏加载优化

弹窗组件怎么设计

计算三个数组和差集,并集和交集

携程

手写JS几种继承方式,指明优缺点

宏任务:两个代码输出是否相同

//代码1
<script>
console.log(a);
</script>
<script>
console.log('a');
</script>
//代码 2
<script>
console.log(a);
console.log('a');
</script>

考察包装类

var a = 12;
a.x = 2;
console.log(a.x);

算法题:

20. 有效的括号

1. 两数之和

3. 无重复字符的最长子串

CSS

实现透明度为0.6的蒙层,蒙层内文字颜色为#fff,蒙层包含淡入淡出动画

三栏布局,左右边固定200px,中间自适应宽度,尽可能多种写法

未知宽高元素垂直水平居中,尽可能多种写法

跨域如何携带cookie

事件循环宏任务会不会互相干扰,js代码和渲染是不是在同一个线程调度?

redux和react-redux的实现原理

百度

手写图片懒加载

route路由原理/hashChange和history

如何做单元测试

H5调试手机代理

数组扁平化,[1,2,3,[4,5,6]]转成[1,2,3,4,5,6]

手写promise.all

position fix失效场景

rem,em,vh,vw的区别

实现0.1+0.2===0.3的方法

tree层次遍历反转

途虎

angular依赖注入和控制反转

flutter三棵树

虚拟滚动实现

事件循环

promise.all手写

300m大文件网络传输优化

网络层中在哪一层知道文件是否传输结束?

特赞

var/let/const区别

实现let,let的babel转换

实现一个toast组件

puredependency和dependency

设计一个toast组件

let var const的对比

babel如何实现ES6的let

箭头函数和普通函数对比

Leetcode

  • 实现reduce
  • 生成1000个6位不重复的验证码,并且相邻数字不可以是重复的
  • 生成1000个6位验证码,不重复,并且相邻数字不能重复
  • 实现Array.prototype.reduce,函数入参:reduce(arr,fn,start);
  • react和angular的区别
  • 设计模式
  • switchMap/mergeMap/concatMap的差别
  • 设计一个推荐搜索的组件(用到switchMap去取消订阅)

食亨

虚拟滚动滚动怎么计算要展示的数据信息

手写节流

tree dfs

垂直水平居中

div的style中,设置width和height,并且加了important,如何修改div的宽高

首屏优化

BFC

水平垂直居中

两列布局,左边定宽

margin塌陷怎么解决

div设置style的宽高和important,怎么写class可以修改其宽高

虚拟滚动的数组数据怎么计算

防抖节流

计算多叉树的最大深度

react diff算法

微软上海(一面挂)

业务场景设计:

列表可以进行增删,列表中item顺序可以拖拽,但是每次更新的时候,表示顺序的order必须是唯一的,如果被使用过更新会报错。

interface Item {
    id: string;
    order: number; // int32
    }
    
    interface DisplayItem {
    id: string;
    }
    
    function ajax(options: any): Promise<any> {
    /**
    * It's not necessary to implement this.
    * Usage:
    * const promise = ajax({
    * method: ...,
    * url: ...,
    * data: { ... }
    * });
    */
    throw "Not implemented";
    }
    
    function save(groupId: string, displayItems: DisplayItem[], oldItems: Item[]): Promise<any> {
    /**
    * `displayItems` are ordered by the display order.
    * `oldItems` are in ascending order by the `order` property.
    *
    * PUT https://example.com/api/groups/{groupId}/items/{itemId}
    * { "order": ... }
    */
    function updateGroupItem(itemInfo){
        // TODO
    }
    function createGroupItem(itemInfo):Promise<any>{

    }
    // create old Item map
    let oldItemMap = {};
    let orderMap = {};
    oldItems.forEach((cur,idx)=>{
        oldItemMap[cur.id] = {
            curItem:cur,
            isDeleted:true,
        }
        orderMap[cur.order] = idx;
    }); 
    let newUniqueOrderMap = {};
    Object.keys(orderMap).forEach(cur=>{
        let nums = Number(cur);
        while(orderMap[nums] !== undefined && newUniqueOrderMap[nums]){
            nums = nums - 1000;
        }
        newUniqueOrderMap[nums];
    });
    let newUniqueOrderArr = Object.keys(newUniqueOrderMap);
    displayItems.forEach((dis,idx)=>{
        let old = oldItemMap[dis.id];
        if(!old){
            const order = newUniqueOrderArr[idx];
            // TODO
            createGroupItem({
                id:dis.id,
                order
            })
        } else{
            // 遍历过无须删除
            old.isDeleted = false;
            if(orderMap[old.curItem.order] !== idx){
                const order = newUniqueOrderArr[idx];
                // 更新items
                // TODO
                updateGroupItem({
                    id:dis.id,
                    order
                })
            }
        }
    })
    const deleted = Object.keys(oldItemMap).filter(cur=>oldItemMap[cur].isDeleted);
    deleted.forEach(cur=>{
        
    })
    throw "Not implemented";
    }

才历

ssr的优点和缺点

首页白屏的优化机制

缓存机制,协商缓存和强制缓存的作用,html/js/css文件应该怎么设置缓存方式

react class component,父子组件中,父组件props变化后,子组件的声明周期如何调用

分包加载如何实现/原理和应用,怎么配

虚拟滚动的实现原理以及虚拟滚动的滚动白屏和缓慢像素加载怎么优化

观察者模式

设计实现api请求可以无痛刷新token

云扩

HTTPS的SSL层如何实现

HTTP跨域

CORS跨域怎么实现

GET/post/delete都会进行跨域的option请求吗?一般来说get不会

React和Angular的区别

虚拟滚动

识货

声明提升,那个优先级高

this的指向,优先级,

call,apply的实现,

new的实现,

实现深拷贝,有哪些问题,怎么避免

算法题 传入数字返回平方根

react单项数据流的优缺点

hooks的eslint规则,为什么有这个规则

什么是fiber架构

事件循环eventloop

实现一个promise

eventloop过程

js原型链

js继承

跨域问题

jsonp有什么问题

最近一个做过比较有技术难点的项目

flex布局问题

多行文本省略怎么实现

css伪类的了解

有5个元素,第二行所有间距相等,第一行如图

设计模式的了解

编码原则的了解

https加密过程

蚂蚁保险

/**
* 题目:实现一个Throttle
* 在移动开发中会有触发比较频繁的事件,比如抢购时用户快速点击一个按钮,用户滚动屏幕引起图片的懒加载等;
* 请完成下面函数 throttle:
*/
// method为传入方法,delay为延迟时间;
function throttle (method,delay) {
    // do your work
    let start = null;
    let timeout = null;
    return function(...args){
      let context = this;
        if(!start) {
          start = +new Date();
      }
      let current = +new Date();
      if(!timeout){
          timeout = setTimeout(()=>{
           start = current;
           timeout = -1;
             method.apply(context,args);
          },delay);
      }
      if(current - start>=delay){
        if(timeout && timeout != -1){
            clearTimeout(timeout);
        }
        start = current;
        method.apply(context,args);
      } 
    }
  }
  //使得:
  const method = () => console.log('x')
  const warppedMethod = throttle(method, 3000);
  // 在3s, 6s之后打印 'x'
  warppedMethod();
  warppedMethod();
  setTimeout(() => {
    warppedMethod();
  }, 2000);
  setTimeout(() => {
    warppedMethod();
  }, 5000);
  
  //题目:实现一个函数,可以将数组转化为树状数据结构
  // 入参格式参考:
  const arr = [
    { id: 1, name: 'i1' },
    { id: 2, name: 'i2', parentId: 1 },
    { id: 4, name: 'i4', parentId: 3 },
    { id: 3, name: 'i3', parentId: 2 },
    { id: 8, name: 'i8', parentId: 7 }
  ];
  /* 可以将数组转化为树状数据结构,要求程序具有侦测错误输入的能力*/
  function buildTree(arr) {
    /**
     * 此处写代码逻辑
     */
    let idMap = {};
    let childrenMap = {};
    let head = [];
    arr.forEach(cur=>{
        if(!idMap[cur.id]){
        idMap[cur.id] = cur;
      }   
      if(cur.parentId !== undefined ){
        if(!childrenMap[cur.parentId]){
          childrenMap[cur.parentId] = new Set();
        } else {
          childrenMap[cur.parentId].add(cur);
        }
      } else {
            head.push(cur);
      }
    });
    if(!head || !head.length){
        throw Error('Level 0 does not exist');
    }
    function getTree(values){
      values.forEach(cur=>{
        let children = childrenMap[cur.id];
        if(children){
            cur.children = Array.prototype.slice(children);
  //         在tree中被引用过标记为-1
            for(let i=0;i<children.length;i++){
              idMap[children.get(i)] = -1;
          }
          getTree(cur.children);
          idMap[cur.id] = -1;
  //         children被使用过的id设置为-1
          childrenMap[cur.id] = -1;
        } 
      })
    }
    
    getTree(head);
    let idUsed = Object.keys(idMap).filter(k=>idMap[k] !== -1);
    let childUsed = Object.keys(childrenMap).filter(k=>childrenMap[k] !== -1);
  //   在tree中没有被引用的id,或者父节点不存在的id
    if(idUsed.length || childUsed.length) {
        console.log(idUsed.concat(childUsed));
    }
    return head;
  
  }
  
  /**
  * 题目:lastPromise实现
  * 业务需求中,经常有 只需要最后一次请求的结果(比如搜索)编写一个高阶函数,传递旧请求方法(执行后返回 promise),返回一个新方法。
  * 连续触发时,若上一次 promise 执行未结束则直接废弃,只有最后一次 promise 会触发then/reject。
  */
  
  /**
  * 只有最后一次promise会then与reject
  * @param {function} promiseFunction
  * promiseFunction 示例: () => fetch('data')
  */
  function lastPromise(promiseFunction) {
    const cbs = [];
    const promiseMap = {};
    return new Promise((resolve, reject) => {
      cbs.push(resolve);
      const p = promiseFunction();
      promiseMap[p] = resolve;
      p.then(()=>{
          if (cbs.indexOf(resolve) !== cbs.length -1) {
            return;
          }
            resolve()
      })
      
    });
      
    //todo
  }
  // 示例
  let count = 1;
  let promiseFunction = () =>
    new Promise(rs =>
      window.setTimeout(() => {
        rs(count++);
      })
    );
  let lastFn = lastPromise(promiseFunction);
  lastFn().then(console.log); // 无输出
  lastFn().then(console.log); // 无输出
  lastFn().then(console.log); // 3
  
  (args = [{1,2,4}]) => {
        let copy = cloneDeep(args);
    copy[0].5 = xxxx;
    return copy;
    } 
  
    问了react-visualized
    问了immutable.js

tree BFS非递归怎么解决

tree DFS非递归怎么解决