关于面试:2020年裸辞后面试记录笔记

3次阅读

共计 8638 个字符,预计需要花费 22 分钟才能阅读完成。

在裸辞了四个月后,山月在除夕前找工作,面试了几个大小公司,记录上面试题。

本文地址: https://q.shanyue.tech/interv…

01 如何实现选中复制的性能

<blockquote>
更多形容: 在一些博客零碎,如掘金的博客中,能够复制代码,它是如何实现的
</blockquote>

在 Issue 或者我的网站中交换与探讨: 01 如何实现选中复制的性能

它个别能够应用第三方库 clipboard.js 来实现,源码很简略,能够读一读

次要有两个要点

  1. 选中: Selection API
  2. 复制: document.execCommand

选中: Selection API

选中次要利用了 Selection API

选中的代码如下

const selection = window.getSelection();
const range = document.createRange();

range.selectNodeContents(element);
selection.removeAllRanges();
selection.addRange(range);

selectedText = selection.toString();

勾销选中的代码如下

window.getSelection().removeAllRanges();

它有现成的第三方库能够应用: select.js

复制: execCommand

复制就比较简单了,execCommand

document.exec('copy')

02 随着 http2 的倒退,前端性能优化中的哪些传统计划能够被代替

在 Issue 或者我的网站中交换与探讨: 02 随着 http2 的倒退,前端性能优化中的哪些传统计划能够被代替

  1. 雪碧图
  2. 资源文件合并

03 既然 http 是无状态协定,那它是如何放弃登录状态

在 Issue 或者我的网站中交换与探讨: 03 既然 http 是无状态协定,那它是如何放弃登录状态

通过 cookie 或者 Authorization header 来传递凭证,在服务端进行认证

04 http 响应头中的 Date 与 Last-Modified 有什么不同,网站部署时须要留神什么

在 Issue 或者我的网站中交换与探讨: 04 http 响应头中的 Date 与 Last-Modified 有什么不同,网站部署时须要留神什么

  • Date: 报文在源服务器的产生工夫,由此可查看报文已缓存了多久工夫
  • Last-Modified: 源服务器上资源的上次批改工夫

LM-Factor 与它俩无关。

简而言之,一个动态资源没有设置 Cache-Control 时会以这两个响应头来设置强制缓存工夫:(Date - LastModified) * n,而非间接进行协商缓存。在波及到 CDN 时,体现更为显著,体现在更新代码部署后,界面没有更新。

05 对于 JSON,以下代码输入什么

<blockquote>

更多形容:

const obj = {
  a: 3,
  b: 4,
  c: null,
  d: undefined,
  get e () {}
}

console.log(JSON.stringify(obj))

</blockquote>

在 Issue 或者我的网站中交换与探讨: 05 对于 JSON,以下代码输入什么

const obj = {
  a: 3,
  b: 4,
  c: null,
  d: undefined,
  get e () {}
}

console.log(JSON.stringify(obj))

输入什么?

{"a":3,"b":4,"c":null}

对其中的 undefinedfunction 将在 JSON.stringify 时会疏忽掉

06 如何删除一个 cookie

在 Issue 或者我的网站中交换与探讨: 06 如何删除一个 cookie

通过把该 cookie 的过期工夫改为过来时即可删除胜利,具体操作的话能够通过操作两个字段来实现

  1. max-age: 将要过期的最大秒数,设置为 -1 即可删除
  2. expires: 将要过期的相对工夫,存储到 cookies 中须要通过 date.toUTCString() 解决,设置为过期工夫即可删除

很显著,max-age 更为简略

// max-age 设置为 -1 即可胜利
document.cookie = 'a=3; max-age=-1'
> document.cookie
< ""> document.cookie ='a=3'<"a=3"

> document.cookie
< "a=3"

// 把该字段的 max-age 设置为 -1
> document.cookie = 'a=3; max-age=-1'
< "a=3; max-age=-1"

// 删除胜利
> document.cookie
< ""

07 有没有应用过 css variable,它解决了哪些问题

在 Issue 或者我的网站中交换与探讨: 07 有没有应用过 css variable,它解决了哪些问题

@Cicelychen 赞!而且它与 less/sass 相比,更加灵便,因为它很容易通过 JS 来管制。依据它来做主题切换几乎得心应手。

08 no-cache 与 no-store 的区别是什么

在 Issue 或者我的网站中交换与探讨: 08 no-cache 与 no-store 的区别是什么

no-cacheno-store 用作管制缓存,被服务器通过响应头 Cache-Control 传递给客户端

no-store

永远都不要在客户端存储资源,每次永远都要从原始服务器获取资源

no-cache

能够在客户端存储资源,但每次都 必须去服务器做新鲜度校验,来决定从服务器获取最新资源 (200) 还是从客户端读取缓存 (304),即所谓的协商缓存

当服务器资源返回 304 时与那些 HTTP 响应头无关

个别状况下对于 index.html 或者古代构建环境下不加 hash 的动态资源都须要设置 Cache-Control: no-cache,用来强制每次在服务器端的新鲜度校验。

相当于以下响应头

Cache-Control: max-age=0, must-revalidate

相干问题

  • 【Q434】当服务器资源返回 304 时与那些 HTTP 响应头无关
  • 【Q079】简述 HTTP 的缓存机制

09 如何判断以后环境时挪动端还是 PC 端

在 Issue 或者我的网站中交换与探讨: 09 如何判断以后环境时挪动端还是 PC 端

判断 navigator.userAgent,对于 Android/iPhone 能够匹配以下正则

const appleIphone = /iPhone/i;
const appleIpod = /iPod/i;
const appleTablet = /iPad/i;
const androidPhone = /\bAndroid(?:.+)Mobile\b/i; // Match 'Android' AND 'Mobile'
const androidTablet = /Android/i;

当然,不要反复造轮子,举荐一个库: https://github.com/kaimallea/…

import isMobile from 'ismobilejs'

const mobile = isMobile()

10 http2 中的首部压缩的实现原理是什么

在 Issue 或者我的网站中交换与探讨: 10 http2 中的首部压缩的实现原理是什么

HPACK 协定,其中原理是 哈夫曼编码 索引表 (看来罕用的数据结构及算法要有所理解),以下内容摘自 谷歌开发者文档:http2

每个 HTTP 传输都承载一组标头,这些标头阐明了传输的资源及其属性。在 HTTP/1.x 中,此元数据始终以纯文本模式,通常会给每个传输减少 500–800 字节的开销。如果应用 HTTP Cookie,减少的开销有时会达到上千字节。(请参阅测量和控制协议开销。)为了缩小此开销和晋升性能,HTTP/2 应用 HPACK 压缩格局压缩申请和响应标头元数据,这种格局采纳两种简略然而弱小的技术:

  1. 这种格局反对通过动态霍夫曼代码对传输的标头字段进行编码,从而减小了各个传输的大小。
  2. 这种格局要求客户端和服务器同时保护和更新一个蕴含之前见过的标头字段的索引列表(换句话说,它能够建设一个共享的压缩上下文),此列表随后会用作参考,对之前传输的值进行无效编码。

实际出真知,通过 wireshark 抓包剖析 http2 的报文对了解 http2 收益颇多。

你要有常识,你就得加入改革事实的实际。你要晓得梨子的味道,你就得改革梨子,亲口吃一吃。你要晓得原子的组织同性质,你就得履行物理学和化学的试验,改革原子的状况。你要晓得反动的实践和办法,你就得加入反动。

以下是对于抓包信息的截图

http2 通过 Settings 帧设置 header table size,进行首部压缩

http2 通过首部压缩后,:method 伪标头在索引表中的 Index 为 2

对于 罕用的标头会存储在动态索引表固定的地位,详见 https://httpwg.org/specs/rfc7…

11 简述 node/v8 中的垃圾回收机制

在 Issue 或者我的网站中交换与探讨: 11 简述 node/v8 中的垃圾回收机制

v8 中的垃圾回收机制分为三种

  1. Scavenge,工作在新生代,把 from space 中的存活对象移至 to space
  2. Mark-Sweep,标记革除。新生代的某些对象因为适度沉闷会被移至老生代,此时对老生代中活对象进行标记,并清理死对象
  3. Mark-Compact,标记整顿。

相干链接

  1. 支流的垃圾回收机制都有哪些?
  2. 各种编程语言的实现都采纳了哪些垃圾回收算法

12 如何删除我的项目中没有应用到的 package

在 Issue 或者我的网站中交换与探讨: 12 如何删除我的项目中没有应用到的 package

能够采纳 depcheck 来实现这件事

$ npm install depcheck -g

$ depcheck
Unused dependencies
* underscore
Unused devDependencies
* jasmine
Missing dependencies
* lodash

13 简述下 css specificity

在 Issue 或者我的网站中交换与探讨: 13 简述下 css specificity

css specificity 即 css 中对于选择器的权重,以下三种类型的选择器顺次降落

  1. id 选择器,如 #app
  2. classattributepseudo-classes 选择器,如 .header[type="radio"]:hover
  3. type 标签选择器和伪元素选择器,如 h1p::before

其中通配符选择器 *,组合选择器 + ~ >,否定伪类选择器 :not() 对优先级无影响

另有内联款式 <div class="foo" style="color: red;"></div>!important(最高) 具备更高的权重

:not 的优先级影响 – codepen 能够看出 :not 对选择器的优先级无任何影响

14 在浏览器中如何监听剪切板中内容

在 Issue 或者我的网站中交换与探讨: 14 在浏览器中如何监听剪切板中内容

通过 Clipboard API 能够获取剪切板中内容,但须要获取到 clipboard-read 的权限,以下是对于读取剪贴板内容的代码:

// 是否可能有读取剪贴板的权限
// result.state == "granted" || result.state == "prompt"
const result = await navigator.permissions.query({name: "clipboard-read"})

// 获取剪贴板内容
const text = await navigator.clipboard.readText()

注: 该办法在 devtools 中不失效

相干问题:【Q019】如何实现选中复制的性能

15 如何防止 CDN 为 PC 端缓存挪动端页面

在 Issue 或者我的网站中交换与探讨: 15 如何防止 CDN 为 PC 端缓存挪动端页面

如果 PC 端和挪动端是一套代码则不会呈现这个问题。这个问题呈现在 PC 端和挪动端是两套代码,却共用一个域名。

应用 nginx 配置如下,依据 UA 判断是否挪动端,而走不同的逻辑 (判断 UA 是否挪动端容易出问题)

location / {
    // 默认 PC 端
    root /usr/local/website/web;
    
    # 判断 UA,拜访挪动端
    if ($http_user_agent ~* "(Android|webOS|iPhone|iPad|BlackBerry)" ){root /usr/local/website/mobile;}
 
    index index.html index.htm;
}

解决方案通常应用 Vary 响应头,来管制 CDN 对不同申请头的缓存。

此处能够应用 Vary: User-Agent,代表如果 User-Agent 不一样,则从新发动申请,而非从缓存中读取页面

Vary: User-Agent

当然,User-Agent 切实过多,此时缓存生效就会过多。

简答

应用 Vary: User-Agent,依据 UA 进行缓存。

Vary: User-Agent

但最好不要呈现这种状况,PC 端和挪动端如果是两套代码,倡议用两个域名,理由如下

  1. nginx 判断是否挪动端容易出错
  2. 对缓存不敌对

16 简略介绍 requestIdleCallback 及应用场景

在 Issue 或者我的网站中交换与探讨: 16 简略介绍 requestIdleCallback 及应用场景

requestIdleCallback 保护一个队列,将在浏览器闲暇工夫内执行。它属于 Background Tasks API,你能够应用 setTimeout 来模仿实现

window.requestIdleCallback = window.requestIdleCallback || function(handler) {let startTime = Date.now();
 
  return setTimeout(function() {
    handler({
      didTimeout: false,
      timeRemaining: function() {return Math.max(0, 50.0 - (Date.now() - startTime));
      }
    });
  }, 1);
}

以上实现过于简单以及细节化,也能够像 swr 一样做一个简略的模仿实现,以下代码见 https://github.com/vercel/swr…

const rIC = window['requestIdleCallback'] || (f => setTimeout(f, 1))

rIC 中执行工作时须要留神以下几点:

  1. 执行重计算而非紧急任务
  2. 闲暇回调执行工夫应该小于 50ms,最好更少
  3. 闲暇回调中不要操作 DOM,因为它原本就是利用的重拍重绘后的间隙闲暇工夫,从新操作 DOM 又会造成重拍重绘

React 的工夫分片便是基于相似 rIC 而实现,然而因为 rIC 的兼容性及 50ms 晦涩问题,React 自制了一个实现: scheduler

use-swr 中进行资源的 revalidate 时,也是通过 rIC 来进步性能

参考

强烈推荐 MDN 与 w3c 上的两篇介绍

  • Background Tasks API – MDN
  • requestIdleCallback – W3C

17 在 js 中如何实现继承

在 Issue 或者我的网站中交换与探讨: 17 在 js 中如何实现继承

有以下两种办法可实现继承

class/extends

class Animal {constructor (name) {this.name = name}

  hello () {console.log('hello')
  }
}

class Dog extends Animal {constructor (name, say) {super(name)
    this.say = say
  }
}

function/new

function Animal (name) {this.name = name}

Animal.prototype.hello = () => {console.log('hello')
}

function Dog (name, say) {
  // 01 继承属性
  Animal.call(this, name)
  this.say = say
}

// 02 通过连贯原型链实现继承
Dog.prototype = Object.create(Animal.prototype)

// 03 再加上 constructor
Dog.prototype.constructor = Dog
// Reflect.defineProperty(Dog.prototype, "constructor", {
//  value: Dog,
//  enumerable: false, // 不可枚举
//  writable: true
// })

18 https 中证书的格式化信息有哪些

在 Issue 或者我的网站中交换与探讨: 18 https 中证书的格式化信息有哪些

在 TLS 握手过程中,服务器端须要给客户端提供证书,X.509 就是证书的规范格局。

以下是 github 的证书在 Mac 上显示的内容,可见:

  1. 序列号
  2. Subject Name
  3. Issuer Name
  4. 电子签名
  5. 签名算法
  6. 公钥
  7. 扩大

相干链接

  • What Is an X.509 Certificate?

19 在 TLS 层如何优化网站性能

在 Issue 或者我的网站中交换与探讨: 19 在 TLS 层如何优化网站性能

  1. OSCP Stapling
  2. TLS 1.3

20 实现一个函数用来解析 URL 的 querystring

<blockquote>

更多形容:

示例,如

const url = 'https://shanyue.tech?a=3&b=4&c=5'

// 解析后失去 qs 如下
const qs = {
  a: 3,
  b: 4,
  c: 5
}

镜像问题:【Q440】实现一个函数用来对 URL 的 querystring 进行编码

</blockquote>

在 Issue 或者我的网站中交换与探讨: 20 实现一个函数用来解析 URL 的 querystring

对于路由中解析 querystring,无论前端开发还是后端开发都无时无刻在应用这项性能,即便简直没有人手动解析过它。这里来实现一个简略粗犷的解析函数

  1. 如何应用正则解析 qs
  2. 如何正确本义汉字
  3. 如何正确处理数组
  4. 如何解决各种简单的嵌套对象

对于如何实现简单嵌套对象,边界条件过多,强烈推荐一个 npm 库 qs

为此总结出以下用例用以查看解析函数的正确性

// {}
'https://shanyue.tech' 

// {a: ''}'https://shanyue.tech?a'// {name:' 山月 '}'https://shanyue.tech?name=%E5%B1%B1%E6%9C%88'// {name:' 山月 ', a: 3}'https://shanyue.tech?name=%E5%B1%B1%E6%9C%88&a=3'// {name:' 山月 ', a: [3, 4]}'https://shanyue.tech?name=%E5%B1%B1%E6%9C%88&a=3&a=4'// {name:' 山月 ', a: 3}'https://shanyue.tech?name=%E5%B1%B1%E6%9C%88&a=3#hash'// {name:'1+1=2'}'https://shanyue.tech?name=1%2B1%3D2' 

纯碎应用 javascript 实现解析函数,而不利用浏览器 DOM 个性 API,代码如下所示,细节在正文中体现

function parse(url) {// 一、夹杂在 ? 与 # 之前的字符就是 qs,应用 /\?([^/?#:]+)#?/ 正则来抽取
  // 应用正则从 URL 中解析出 querystring
  // 二、通过 Optional Chain 来防止空值谬误
  const queryString = url.match(/\?([^/?#:]+)#?/)?.[1]

  if (!queryString) {return {} }

  queryObj = queryString.split('&').reduce((params, block) => {
    // 三、如果未赋值,则默认为空字符串
    const [_k, _v = ''] = block.split('=')
    // 四、通过 decodeURIComponent 来转义字符,切记不可呈现在最结尾,以防 ?tag=test&title=1%2B1%3D2 出错
    const k = decodeURIComponent(_k)
    const v = decodeURIComponent(_v)

    if (params[k] !== undefined) {
      // 解决 key 呈现屡次的状况,设置为数组
      params[k] = [].concat(params[k], v)
    } else {params[k] = v
    }
    return params
  }, {})
  return queryObj
}

如果引入浏览器个性 API,问题就简略很多迎刃而解,所波及到的 API 有两个,这里不做开展

  1. new URL(url)
  2. new URLSearchParams(paramsString)

21 如何实现一个数组洗牌函数 shuffle

在 Issue 或者我的网站中交换与探讨: 21 如何实现一个数组洗牌函数 shuffle

const shuffle = (list) => list.sort((x, y) => Math.random() - 0.5)

面试邀请

最初附上我的集体网站,如果有不错的面试机会能够与我分割

日问

欢送关注集体网站: 互联网大厂面试每日一题,内含大厂内推机会、面经大全及若干面试题,每天学习五分钟,一年进入大厂中。

  • 大厂前端面试题大全
  • 大厂内推

博客

欢送关注 GitHub 山月行博客: shfshanyue/blog,内含我在理论工作中碰到的问题、对于业务的思考及在全栈方向上的学习

  • 有可能你并不需要服务器
  • 前端工程化系列
  • Node 进阶系列
正文完
 0