记录字节跳动前端面试,四轮技术面

一面

笔试题:多刷字节题库,多考js编程题,两道算法题,基本时lotcode简单中等题

1.如果后端传给前端一个很大的数,前端会怎么处理,该怎么处理?

分析:不能直接渲染,因为会使页面加载过慢,不利于用户体验。

方法:

  1. 采用懒加载+分页(前端维护懒加载的数据分发和分页)
  2. 使用虚拟滚动技术(目前vue3和react框架都支持了)

分析长列表思路:vue-virtual-scroller,渲染视口范围内的数据,遇到的场景可以说是在一些财务系统和金融系统中,项目要求是一次性返回所有的数据做实时记录,减少接口的请求,这时候我们常用的方案就是采用虚拟列表,描述一下具体方案就可以了

2.new的过程

  • 创建一个新对象
  • 使新对象的__proto__指向原函数的prototype
  • 改变this指向(指向新的obj)并执行该函数,执行结果保存起来作为result
  • 判断执行函数的结果是不是null或Undefined,如果是则返回之前的新对象,如果不是则返回result

// 手写一个new
    function myNew(fn, ...args) {
      // 创建一个空对象
      let obj = {}
      // 使空对象的隐式原型指向原函数的显式原型
      obj.__proto__ = fn.prototype
      // this指向obj
      let result = fn.apply(obj, args)
      // 返回
      return result instanceof Object ? result : obj
    }

3.浏览器的缓存机制(强缓存和协商缓存)

  • 强缓存 当请求资源的时,如果是之前请求过的并使用强缓存,那么在过期时间内将不会发送本次请求向服务器获取资源,而是直接从浏览器缓存中获取(不管资源是否改动)。过期了将重新从服务器获取,并再次强缓存。
  • 强缓存是利用http头中的ExpiresCache-Control两个字段来控制的,Cache-Control下,
  • max-age=xxx:过期时间单位秒;
  • 协商缓存 当请求资源时,如果是之前请求过的并使用协商缓存,还是发送请求到服务器,服务器通过逻辑判断确认资源没有修改返回304状态码,那么本次的资源则是从缓存中获取;如果经过判断确认资源被修改过,则重新发送资源到客户端,并且客户端更新缓存。
  • Last-Modified / If-Modified-Since

方案:

  • HTML: 协商缓存;

  • css、js、图片:强缓存,文件名带上hash。

使用缓存有下面的优点:

  • 减少冗余的数据传输
  • 减少服务器负担
  • 加快客户端加载网页的速度

4.用css3写一个环形进度条


5.一道关于promise的任务控制编程题


6.说说BFC是什么,能解决什么问题

块格式化上下文(Block Formatting Context)

通俗来讲:BFC是一个独立的布局环境,可以理解为一个容器,在这个容器中按照一定规则进行物品摆放,并且不会影响其它环境中的物品。如果一个元素符合触发BFC的条件,则BFC中的元素布局不受外部影响。

BFC:创建了一个独立的容器,容器内的元素布局不会受到外部容器的影响

创建BFC的条件:

根元素:body;

元素设置浮动:float除none以外的值;

元素设置绝对定位:position(absolute、fixed);

display值为:inline-block、table-cell、table-caption、flex等;

overflow值为:hidden、auto、scroll;

BFC的作用(解决的问题):解决margin的重叠问题,解决高度塌陷的问题(浮动的问题),创建自适应两栏布局

对CSS工程化的理解:

CSS工程化是为了解决以下问题:

1.宏观设计:CSS代码如何组织、如何拆分、模块结构怎样设计?

2.编码优化:怎样写出更好的CSS?

3.构建:如何处理我的CSS,才能让它的打包结果最优?

4.可维护性:代码写完了,如何最小化它后续的变更成本?如何确保任何一个同事都能轻松接手?

解决:

预处理器:Less、Sass等;

重要的工程化插件:PostCss;

Webpack loader等。

css-loader:导入CSS模块,对CSS代码进行编译处理;

style-loader:创建style标签,把CSS内容写入标签。

script标签中的defer和async属性:

defer和async属性都是去异步加载外部的JS脚本文件,它们都不会阻塞页面的解析,其区别如下:

defer属性是等到文档解析完成后脚本才会执行;async属性下载完成后立即执行,执行过程中页面处理会停止。

如果同时指定了两个属性,则会遵从async属性而忽略defer属性。

小结

将脚本放在 前面就可以了,如果有依赖的则按照顺序放好。如果一定要放在head标签里面,最好是加defer属性。

DOCTYPE(⽂档类型)的作⽤:

DOCTYPE是HTML5中一种标准通用标记语言的文档类型声明,它的目的是告诉浏览器(解析器)应该以什么样(html或xhtml)的文档类型定义来解析文档,不同的渲染模式会影响浏览器对CSS代码甚⾄JavaScript脚本的解析。它必须声明在HTML⽂档的第⼀⾏。

TCP的三次握手和四次挥手

TCP:

建立一个TCP连接时,三次握手主要是确认双方的接受能力和发送能力是否正常。

首先,客户端会向服务端发送一个SYN报文,当服务端接受到报文后,服务端会返回一个自身的SYN,同时会把客户端的JSN+1作为ACK的值,表示自己已经接收到客户端的SYN,客户端接受到服务端的值后,会再此返回类似的值给服务端,告知服务端它接受成功。

四次挥手:

面试流程
自我介绍然后说一个印象深刻的项目。。。

面试pc端多的项目的话,可以介绍,某某系统管理,该系统主要运用的技术栈是vue3,typeScirpt,vueuse,且vite加webpack并行开发,该项目主要是B端的集成管理系统,里面模块主要有采销订单管理,人事管理,财务系统等,我参与了项目工程化的建设,比如进行代码统一的规范,制作相应技术文档的输出,使新进来的员工能够更快的熟悉项目结构和输出更优雅的代码,封装过公司常用的组件库,支持自定义样式换肤,国际化,权限管理(除了人员等级的权限外,还有支持用户信息铭感词和按钮的权限),大文件上传,公共复杂table表单的封装。

小程序和app的话,可以接受某个例子。
1.浏览器是怎么加载一个HTML的(解析dom,css,js过程。。。)

  1. 解析HTML构成DOM树
  2. 解析CSS构成CSSOM树
  3. 合并DOM树和CSSOM树为render树
  4. 进行回流,确定各DOM的尺寸、位置
  5. 进行重绘,绘制页面的像素信息
  6. 将信息发送给GPU,GPU将页面绘制到屏幕上

解释:

  1. CSS和HTML的加载是异步的,二者互不干扰
  2. CSS的加载会阻塞DOM的渲染,因为必须等DOM树和CSSOM树合并为渲染树之后,才能进行DOM的渲染
  3. JS阻塞DOM解析:defer async 以及js放置的位置

  4. 如果script标签内不带defer/async,那么浏览器在解析到script标签时会停止DOM的解析,一直等到script标签的加载与执行完成后,再进行之后的DOM解析。

    如果添加defer标签,则script标签的加载不阻塞DOM加载,并在DOM加载完成后按照引入的顺序执行。

    如果添加async标签,则script标签的加载也不阻塞DOM加载,但是在加载完之后立马执行,不能保证执行的顺序。
     

2.vue-router实现的原理

vue-router实现了再不跳转页面的情况下更新视图,也就是只有一个页面。

可以讲解 哈希和history之间的区别,怎么做到跳转页面不刷新.

哈希#后面的内容不会传给服务端,也就是说不会重新刷新页面,并且路由切换的时候也不会重新加载页面,底层原理就是window.onhashchange

history 添加了pushState()replaceState()方法,以及 onpopstate 事件。但原理和 hash 方式是相同的。

以及router-link和router-view的使用


3.回流重绘,为什么用transform写动画不用position top left

重绘:改变色彩(不影响布局)

回流:浏览器为了重新渲染部分或者全部的文档而重新计算文档中元素的位置和几何构造的过程(影响周围元素和dom树)

可以优化优化回流与重绘

1:用transform 代替 top,left ,margin-top, margin-left… 这些位移属性

2:用opacity 代替 visibility,但是要同时有translate3d 或 translateZ 这些可以创建的图层的属性存在才可以阻止回流,建议:opacity 加上 transform: translateZ/3d 这个属性之后便不会发生回流和重绘了

3:不要使用 js 代码对dom 元素设置多条样式,选择用一个 className 代替之。

4.if...else...多层嵌套怎么解决

如果嵌套不深的话,一般会用三元表达式,如果多if判断,使用switch case 方法也是一种优雅的写法,
5.编程题:n维数组转换成1维数组,比如:[1,[2,3],[[4],[5,6]]]变成[1,2,3,4,5,6 ]

oldArr.flat(Infinity)  使用 flat() 拉平数组过程中,会移除数组的空项:

当考虑es6的兼容问题是,可以采用循环递归的方法

while(arr.some(Array.isArray)){
arr = [].concat(...arr)
}

二面:
前端负责人面,自我介绍然后聊项目经验(一定要讲一些出彩的项目,什么难点,如何突破),聊了些工作经历(为什么想换工作,以前的工作有什么收获,自身的缺点)。。。
技术题问的不多
1.写一个EventEmitter

一个简单的观察者模式应有以下成员:

subscribes 一个数组
subscribe() 将订阅添加到数组里
unsubscribe() 把订阅从数组中移除
publish() 迭代数组,调用订阅时的方法

var Jack = {
    subscribers: {
        'any': []
    },
	//添加订阅
    subscribe: function (type = 'any', fn) {
        if (!this.subscribers[type]) {
            this.subscribers[type] = [];
        }
        this.subscribers[type].push(fn); //将订阅方法保存在数组里
    },
	//退订
    unsubscribe: function (type = 'any', fn) {
        this.subscribers[type] =
            this.subscribers[type].filter(function (item) { 
                return item !== fn;
            }); //将退订的方法从数组中移除
    },
	//发布订阅
    publish: function (type = 'any', ...args) {
        this.subscribers[type].forEach(function (item) { 
            item(...args);	//根据不同的类型调用相应的方法
        });
    }
};


三面:
主管面,介绍工作经历,聊项目亮点balabala
1.编程题,在一个无序数组中找到第二大的数

简介的写法就是排序从大到小,然后读取第二个

let maxSecond = arr.sort((a,b)=>{b-a}).[1]
2.项目设计题,写一个***大战(写出类和属性方法,不需要实现)
3.***大战的各个动画是怎么动起来的(游戏引擎怎么运作)
4.当浏览器地址栏输入一个url到页面展现,这个过程?
5.https过程
6.http和tcp的关系
四面:
北京交叉面,主要是聊项目(有亮点的项目,涉及架构的项目等),工作中做了什么,未来职业规划是什么,面试官最后还给了一定的建议。

你可能感兴趣的:(面试,职场和发展)