【面试】字节飞书前端开发暑期实习

371 阅读5分钟

一面(视频面试)

问题

  1. 自我介绍
  2. 学过哪些计算机相关的基础课
  3. 问计网:tcp和udp属于那一层?(传输层)他们有什么区别用于什么场景?
  4. tcp是可靠的,为什么可靠?具体怎么判断重传报文?
  5. tcp拥塞控制的具体流程及相关参数
  6. tcp的三次握手及具体传输参数
  7. HTTP Method有哪些?
  8. GET、POST有什么区别?
  9. 除GET POST之外其他method的应用场景
  10. CSS优先级,伪类、伪元素的优先级
  11. 一个左边固定100px宽右边自适应的两栏布局怎么做?(flex、float、position)
  12. 重绘重排的定义、区别、关系;font-size增加会引起重绘还是重排?
  13. 关于项目:两个需求的具体实现逻辑,分别与防抖、Promise有关 ——> 写防抖、Promise.all源码
  14. 算法题:从数组中找出一组n个数使其和为target

参考答案(仅供参考)

tcp、udp

传输层协议:TCP协议、UDP协议

TCP和UDP的优缺点、区别、常用场景

TCP的可靠性传输是如何保证的

TCP的拥塞控制(详解)

关于三次握手和四次挥手,面试官想听到怎样的回答?

HTTP

HTTP常用方法:

  • GET:获取资源
  • POST:传输资源
  • PUT:更新资源
  • DELETE:删除资源
  • HEAD:获得报文首部
  • OPTIONS:询问支持

GET、POST区别:

  1. GET在浏览器回退时无害,而POST会再次提交请求
  2. GET产生的URL可以被收藏,POST不可
  3. GET请求会被浏览器主动缓存,而POST不会,除非手动设置
  4. GET请求只支持url编码,而POST支持多种编码方式
  5. GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留
  6. GET请求在url中传输的参数是有长度限制的,而POST没有限制
  7. 对参数的数据类型,GET只接收ASCII字符,而POST没有限制
  8. GET比POST更不安全,因为参数直接暴露在url中,所以不可用于传递敏感信息
  9. GET参数通过URL传递,POST放在Request body中

OPTIONS用于CORS

CORS(跨域资源共享 Cross-origin resource sharing)允许浏览器向跨域服务器发出XMLHttpRequest请求,从而克服跨域问题,它需要浏览器和服务器的同时支持。

浏览器端会自动向请求头添加origin字段,表明当前请求来源。 服务器端需要设置响应头的Access-Control-Allow-Methods,Access-Control-Allow-Headers,Access-Control-Allow-Origin等字段,指定允许的方法,头部,源等信息。 请求分为简单请求和非简单请求,非简单请求会先进行一次OPTION方法进行预检,看是否允许当前跨域请求。

简单请求: HEAD、GET、POST

同时HTTP的请求头信息不超出以下几种字段:

  • Accept
  • Accept-Language
  • Content-Language
  • Last-Event-ID
  • Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain

后端的响应头信息:

  • Access-Control-Allow-Origin:必须,它的值要么是请求时Origin字段的值,要么是一个*,表示接受任意域名的请求。
  • Access-Control-Allow-Credentials:该字段可选。它的值是一个布尔值,表示是否允许发送Cookie。
  • Access-Control-Expose-Headers:该字段可选。CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必须在Access-Control-Expose-Headers里面指定。

非简单请求: 除了简单请求之外的请求,在正式通信之前,非简单请求增加一次HTTP查询请求OPTIONS,称为"预检"请求(preflight)。

  • Access-Control-Request-Method:该字段是必须的,用来列出浏览器的CORS请求会用到哪些HTTP方法,上例是PUT。
  • Access-Control-Request-Headers:该字段是一个逗号分隔的字符串,指定浏览器CORS请求会额外发送的头信息字段,上例是X-Custom-Header。

如果浏览器否定了OPTIONS请求,会返回一个正常的HTTP回应,但是没有任何CORS相关的头信息字段。这时,浏览器就会认定,服务器不同意预检请求,因此触发一个错误,被XMLHttpRequest对象的onerror回调函数捕获。

CSS

选择器优先级(高 -> 低)

  • !important
  • 内联样式(1000)
  • ID选择器(0100)
  • 类选择器/属性选择器/伪类选择器(0010)
  • 元素选择器/伪元素选择器(0001)
  • 关系选择器/通配符选择器(0000)

高优先级的选择器对低优先级的有无限压制即不管有多少个低的加起来也永远无法超过高的

优先级一致的话则后定义的生效

三栏布局

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Layout</title>
    <style media="screen">
        html * {
            padding: 0;
            margin: 0;
        }
        .layout {
            margin-top: 10px;
        }
        .layout article div {
            min-height: 100px;
        }
    </style>
</head>
<body>
    <!-- 浮动解决方案 -->
    <section class="layout float">
        <style media="screen">
            .layout.float .left {
                width: 300px;
                float: left;
                background: red;
            }
            .layout.float .right {
                width: 300px;
                float: right;
                background: blue;
            }
            .layout.float .center {
                background: yellow;
            }
        </style>
        <article class="left-center-right">
            <div class="left"></div>
            <div class="right"></div>
            <div class="center">
                <h1>浮动解决方案</h1>
                1. center
                2. center
                3. center
            </div>
        </article>
    </section>

    <!-- 绝对定位解决方案 -->
    <section class="layout absolute">
        <style media="screen">
            .layout.absolute .left-center-right>div {
                position: absolute;
            }
            .layout.absolute .left {
                background: red;
                width: 300px;
                left: 0;
            }
            .layout.absolute .right {
                background: blue;
                width: 300px;
                right: 0;
            }
            .layout.absolute .center {
                background: yellow;
                left: 300px;
                right: 300px;
            }
        </style>
        <article class="left-center-right">
            <div class="left"></div>
            <div class="right"></div>
            <div class="center">
                <h1>绝对定位解决方案</h1>
                1.absolute
                2.absolute
                3.absolute
            </div>
        </article>
    </section>

    <!-- FlexBox解决方案 -->
    <section class="layout flexbox">
        <style media="screen">
            .layout.flexbox {
                margin-top: 120px;
            }
            .layout.flexbox .left-center-right {
                display: flex;
            }
            .layout.flexbox .left {
                flex: 0 0 300px;
                order: -1;
                background: red;
            }
            .layout.flexbox .right {
                flex: 0 0 300px;
                background: blue;
                order: 2;
            }
            .layout.flexbox .center {
                flex: 1;
                background: yellow;
            }
        </style>
        <article class="left-center-right">
            <div class="left"></div>
            <div class="right"></div>
            <div class="center">
                <h1>FlexBox解决方案</h1>
                1.flexbox
                2.flexbox
                3.flexbox
            </div>
        </article>
    </section>

    <!-- 表格布局解决方案 -->
    <section class="layout table">
        <style media="screen">
            .layout.table .left-center-right {
                display: table;
                width: 100%;
                height: 100px;
            }
            .layout.table .left-center-right>div {
                display: table-cell;
            }
            .layout.table .left {
                background: red;
                width: 300px;
            }
            .layout.table .center {
                background: yellow;
            }
            .layout.table .right {
                background: blue;
                width: 300px;
            }
        </style>
        <article class="left-center-right">
            <div class="left"></div>
            <div class="center">
                <h1>表格布局解决方案</h1>
                1.table
                2.table
                3.table
            </div>
            <div class="right"></div>
        </article>
    </section>

    <!-- 网格布局解决方案 -->
    <section class="layout grid">
        <style media="screen">
            .layout.grid .left-center-right {
                display: grid;
                grid-template-rows: 100px;
                grid-template-columns: 300px auto 300px;
            }
            .layout.grid .left {
                background: red;
            }
            .layout.grid .center {
                background: yellow;
            }
            .layout.grid .right {
                background: blue;
            }
        </style>
        <article class="left-center-right">
            <div class="left"></div>
            <div class="center">
                <h1>网格布局解决方案</h1>
                1.grid
                2.grid
                3.grid
            </div>
            <div class="right"></div>
        </article>
    </section>
</body>
</html>

重排(reflow)和重绘(repaint)

font-size 引起重排

源码

// 防抖函数
function debounce(func, time = 500) {
  let timer = null
  return function anonymous(... params) {
    clearTimeout(timer)
    timer = setTimeout(_ => {
      timer = null
      func.call(this, ...params)
    }, time)
  }
}

// Promise.all
function isPromise (val) {
  return typeof val.then === 'function'; 
}

Promise.all = function(promises) {
  return new Promise((resolve, reject) => {
    let arr = []; 
    let index = 0; 
    const processData = (key, data) => {
      arr[key] = data;
     if (++index === promises.length) {
       resolve(arr);
     }
    }
    for (let i = 0; i < promises.length; i++) {
      let result = promises[i];
      if(isPromise(result)) {
        result.then((data) => {
          processData(i ,data)
        }, reject)  
      } else {
        processData(i ,result)
      }
    }
  })
}

算法题

function getRes(data, n, sum) {
    let result;
    function solve(data, n, sum, res, start) {
        if(sum === 0 && n === 0) {
            result = res;
            return true;
        }
        if(n === 0 || start === data.length - 1 || sum < 0) {
            return false;
        }
        for(let i = start; i < data.length; i++) {
            res.push(data[i]);
            if (solve(data, n - 1, sum - data[i], res, i + 1)) {
                break;
            }
            res.pop();
        }
    }
    solve(data, n, sum, [], 0);
    return result ? result : null;
}

二面(视频面试)

问题

  1. 介绍自己的项目(要求简洁,突出难点)
  2. 我的需求基于Vue提供的运行中编译能力实现,问如果没有这种运行中编译的能力应该怎么实现
  3. 写一个类似于百度搜索的输入检索框,在输入文字后会联想相关的内容(注意:需要考虑每次检索请求返回的先后顺序)
// searchInput.vue
<template>
    <div>
        <input ref="input" @change="search">
        <ul v-if="optionList.length">
            <li v-for="item in optionList" :key="item.id">
                {{item.name}}
            </li>
        </ul>
    </div>
    
</template>

<script>
    export default {
        data(){
            return {
                optionList: [],
                version: 0,
                showVersion: 0,
            }
        },
        methods: {
            async search(){
                try {
                    let currVersion = this.version++;
                    const res = getData(this.$refs.input.value);
                    if(currVersion > this.showVersion) {
                        this.optionList = res;
                        this.showVersion = currVersion;
                    }
                } catch(err) {
                    console.error('获取数据失败');
                }
            }
        }
}    
</script>
  1. 有15瓶药水,其中一瓶有毒,用小白鼠测试一次,最少需要几只小白鼠(4只)
  2. 有一个城市人们更喜欢女孩子,如果生出男孩子就一直生直到出现女孩子停止生育,问该城市的男女比例(1:1)