字节跳动面试题

字节跳动面试题,2019年,记录下来

一、add(1)(2)(3)

释义:高阶函数(接收函数作为参数传递或者将函数作为返回值输出的函数,满足一条即可),常见的Array.map,Array.filter,Array.reduce
答案:这是一道常见的面试题,主要考察闭包和函数的toString方法吧,网上给出的结果如下:

1
2
3
4
5
6
7
8
9
10
function add(a) {
function sum(b) {
a += b;
return sum;
}
sum.toString = function() {
return a;
}
return sum;
}

分析:然后执行 add(1)(2)(3)(4)(5)… 参数可以无限多个,最终返回的类似 f 15这种。查阅了很多文档,这题貌似也没有多个解决办法,就像1+1只能等于2这样子。
问题:但如果非要抬杠的话,不妨执行下下面的代码(直接输出的是一个function,要想输出数字,需要加toString())

1
2
3
4
5
var res = add(1)(2)(3)(4)(5)
console.log(typeof res) // 输出"function"
res = add(1)(2)(3)(4)(5).toString()
console.log(res === 15)
console.log(typeof res) // 输出"number

扩展:怎么实现 add(1)(2)(3)() = 6?
答案:既然最后一次执行没参数,那可以不用上面的方法写(主要是没彻底搞清楚上面方法的原理)。思路是判断arguments是否有值,有的话返回函数,没有的话返回累加的结果。

1
2
3
4
5
6
7
8
9
10
11
12
function add2(a) {
a = a || 0;
function sum(b) {
b = b || 0;
a += b;
return arguments.length ? sum : a;
}
return sum;
}
var res = add2(1)(2)(3)(4)(5)();
console.log(res) // 15
console.log(typeof res) // "number"

相关:

二、BFC

BFC概念:BFC是块级格式上下文,是页面盒模型布局中的一种 CSS 渲染模式,相当于一个独立的容器,里面的元素和外部的元素相互不影响
BFC特性:

  • 内部box会在垂直方向,一个接一个地放置
  • Box垂直方向的距离由margin决定,在一个BFC中,两个相邻的块级盒子的垂直外边距会产生折叠
  • 在BFC中,每一个盒子的左外边缘(margin-left)会触碰到容器的左边缘(border-left)(对于从右到左的格式来说,则触碰到右边缘)
  • 形成了BFC的区域不会与float box重叠
  • 计算BFC高度时,浮动元素也参与计算

BFC主要作用:

  • 清除浮动
  • 防止统一BFC容器中的相邻元素之间外边距重叠问题

更多释义参照 https://developer.mozilla.org/zh-CN/docs/Web/Guide/CSS/Block_formatting_context https://www.cnblogs.com/chen-cong/p/7862832.html

三、协商缓存、强制缓存

强制缓存:就是给资源设置个过期时间,客户端每次请求资源时都会看是否过期;只有在过期才会去询问服务器

1.cache-control: max-age=xxxx,public

  • 客户端和代理服务器都可以缓存该资源;
  • 客户端在xxx秒的有效期内,如果有请求该资源的需求的话就直接读取缓存,statu code:200
  • 如果用户做了刷新操作,就向服务器发起http请求
    2.cache-control: max-age=xxxx,private
  • 只让客户端可以缓存该资源;代理服务器不缓存
  • 客户端在xxx秒内直接读取缓存,statu code:200
    3.cache-control: max-age=xxxx,immutable
  • 客户端在xxx秒的有效期内,如果有请求该资源的需求的话就直接读取缓存,statu code:200
  • 即使用户做了刷新操作,也不向服务器发起http请求
    4.cache-control: no-cache
  • 跳过设置强缓存,但是不妨碍设置协商缓存;
  • 一般如果你做了强缓存,只有在强缓存失效了才走协商缓存的,设置了no-cache就不会走强缓存了,每次请求都回询问服务端。
    5.cache-control: no-store
  • 不缓存,这个会让客户端、服务器都不缓存,也就没有所谓的强缓存、协商缓存了。
协商缓存:

解释:每次请求返回来response header中的etag和last-modified,在下次请求时在request header(对应if-none-matched 和 if-modified-since)就把这两个带上,服务端把你带过来的标识进行对比,然后判断资源是否更改了,如果更改就直接返回新的资源,和更新对应的response header的标识etag、last-modified。
协商缓存过程:

  • 发请求–>看资源是否过期–>过期–>请求服务器–>服务器对比资源是否真的过期–>没过期–>返回304状态码–>客户端用缓存的老资源
  • 发请求–>看资源是否过期–>过期–>请求服务器–>服务器对比资源是否真的过期–>过期–>返回200状态码–>客户端如第一次接收该资源一样,记下它的cache-control中的max-age、etag、last-modified等

1.etag
文件hash,每个文件有一个,改动文件了就变了,每个文件唯一,就像用webpack打包的时候,每个资源都会有这个东西
2.last-modified
文件的修改时间(精确到秒)

  • etag较last-modified优势:(1.一些文件也许会周期性的更改,但实际内容并没改变,此时不需要重新请求;2.某些文件更改非常频繁,比如1s内改了10次,此时last-modified是无法判断的;3.某些服务器不能精确得到文件的最后修改时间)

四、盒模型

1.标准盒模型:元素占用宽度 = width + padding + border + margin
2.IE盒模型:元素占用宽度 = width(包含了padding和border) + margin

  • 设置元素的box-sizing: border-box能强制使用IE盒模型(也称怪异模式)

五、简单实现VUE的双向绑定

六、写一个Event类,可以on和emit事件

七、实现快速排序

八、以下代码输出啥?

1
2
3
4
5
for(var i = 0; i < 6; i++) {
setTimeout(function(){
console.log(new Date(), i);
})
}
8.1 如果想让上面代码中的i分别输出 1 2 3 4 5 ,该怎么改?
8.2 如果想让上面代码隔1s输出一次,怎样改?
8.3 用promise实现8.2的需求?
8.4 用async await实现8.2的需求?

九、说说事件循环机制?

十、说说VUE里虚拟dom的原理?

坚持原创技术分享,您的支持将鼓励我继续创作!