字节前端二面凉凉记录
字节前端二面凉凉记录
协商缓存
使用协商缓存策略时,会先向服务器发送一个请求,如果资源没有发生修改,则返回一个 304 状态,让浏览器使用本地的缓存副本。如果资源发生了修改,则返回修改后的资源。
JavaScript 事件循环相关
console.log(1);
setTimeout(function () {
console.log(2);
}, 0);
new Promise((resolve) => {
console.log(3);
resolve();
}).then(() => {
console.log(4);
});
console.log(5);
//正确答案
1;
3;
5;
4;
undefined;
2;
解析:
- script 是一个宏任务,按照顺序执行这些代码,先打印 1;
- 遇到定时器 steTimeout,它是一个宏任务,放入宏任务队列;
- 首先进入 Promise,执行该构造函数中的代码,打印 3;
- 碰到 resolve 函数, 将 Promise 的状态改变为 resolve, 并将结果保存下来;
- 碰到 Promise.then 这个微任务,将它放入微任务队列;
- 继续往下走,输出 5;
- 执行.then() 输出 4
- 接着执行 resolve 输出 undefined
- 最后执行定时器(宏任务)输出 2
- 这里面试官问了我顺带问了我 Event Loop 事件流
原型链
判断数组的几种方式
//通过原型链做判断
obj.__proto__ === Array.prototype;
//通过 ES6 的 Array.isArray()做判断
Array.isArrray(obj);
//通过 instanceof 做判断
obj instanceof Array;
//通过 Array.prototype.isPrototypeOf
Array.prototype.isPrototypeOf(obj);
//通过 Object.prototype.toString.call()做判断
Object.prototype.toString.call(obj).slice(8, -1) === "Array";
手写:reduce 实现 map
/**
* 用数组的 reduce 方法实现数组的 map
*/
Array.prototype.Mmap = function (fn, thisArg) {
const result = [];
this.reduce((prev, curr, index, array) => {
result[index] = fn.call(thisArg, array[index], index, array);
}, 0);
return result;
};
解析
arr.reduce((previousValue, currentValue, currentIndex, array) => {}, initialValue?)
reduce 接收两个参数,第一个参数为函数,指定了每次迭代调用的函数,函数的返回值为下一次迭代的 previousValue;第二个参数为初始值,是可选的。
若不指定初始值,那么第一次迭代的 previousValue 为 arr[[0], currentValue 为 arr[1], currentIndex 为 1,
若指定初始值,那么第一次迭代的 previousValue 为 initialValue, currentValue 为 arr[0], currentIndex 为 0
arr.map(function callback(currentValue[, index[, array]]) { }[, thisArg])
其中第二个参数为 thisArg, 可选的,表示执行 callback 时的 this。
注意,如果 callback 为箭头函数时,里面的 this 指向外层代码块,(非严格模式下为 window),此时指定 thisArg 无效
PS : 这里没写好,原因有三,1:对 map 函数理解不深,项目使用都只是传一个参数,2:对 reduce 使用较少,3:考虑时间过长。
手写:使定时器没回调
console.log(0);
await delay(1000);
console.log(1);
const delay = (time) => new Promies((resolve) => setTimeout(resolve, time));
浏览器过程
浏览器第一次加载资源,服务器返回 200,浏览器从服务器下载资源文件,并缓存资源文件与 response header,以供下次加载时对比使用;
下一次加载资源时,由于强制缓存优先级较高,先比较当前时间与上一次返回 200 时的时间差,如果没有超过 cache-control 设置的 max-age,则没有过期,并命中强缓存,直接从本地读取资源。如果浏览器不支持 HTTP1.1,则使用 expires 头判断是否过期;
如果资源已过期,则表明强制缓存没有被命中,则开始协商缓存,向服务器发送带有 If-None-Match 和 If-Modified-Since 的请求;
服务器收到请求后,优先根据 Etag 的值判断被请求的文件有没有做修改,Etag 值一致则没有修改,命中协商缓存,返回 304;如果不一致则有改动,直接返回新的资源文件带上新的 Etag 值并返回 200;
如果服务器收到的请求没有 Etag 值,则将 If-Modified-Since 和被请求文件的最后修改时间做比对,一致则命中协商缓存,返回 304;不一致则返回新的 last-modified 和文件并返回 200
浏览器强缓存,协商缓存
强缓存
使用强缓存策略时,如果缓存资源有效,则直接使用缓存资源,不必再向服务器发起请求。
强缓存策略可以通过两种方式来设置,分别是 http 头信息中的 Expires 属性和 Cache-Control 属性。
协商缓存
如果命中强制缓存,我们无需发起新的请求,直接使用缓存内容,如果没有命中强制缓存,如果设置了协商缓存,这个时候协商缓存就会发挥作用了。
命中协商缓存的条件有两个:
- max-age=xxx 过期了
- 值为 no-store
使用协商缓存策略时,会先向服务器发送一个请求,如果资源没有发生修改,则返回一个 304 状态,让浏览器使用本地的缓存副本。如果资源发生了修改,则返回修改后的资源。
HTML
基于 DOM 画一个扇形,提出方案
- CSS3 中的 clip (面试官说要考虑兼容性)
- Canvas 或者 svg 去实现 (面试官说要用 HTML 中 DOM 来考虑)
- HTML5 中进度条老修改样式达到目的 (面试官说还有没有其他的)
面试官给出的答案:先画一个圆,然后通过 CSS3 中 border-radius 属性去定位到圆上。