最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 面试中的题目记录

    正文概述 掘金(shanyue)   2021-01-04   406

    山月最近裸辞了四个月,元旦前后找工作,面试了几个大小公司,记录下面试题

    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 的发展,前端性能优化中的哪些传统方案可以被替代

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

    03 既然 http 是无状态协议,那它是如何保持登录状态

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

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

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

    LM-Factor 与它俩有关。

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

    05 关于 JSON,以下代码输出什么

    通过把该 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,它解决了哪些问题

    @Cicelychen 赞!而且它与 less/sass 相比,更加灵活,因为它很容易通过 JS 来控制。根据它来做主题切换简直得心应手。

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

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

    no-store

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

    no-cache

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

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

    相当于以下响应头

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

    相关问题

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

    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;
    

    当然,不要重复造轮子,推荐一个库: github.com/kaimallea/i…

    import isMobile from 'ismobilejs'
    
    const mobile = isMobile()
    

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

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

    实践出真知,通过 wireshark 抓包分析 http2 的报文对理解 http2 收益颇多。

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

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

    面试中的题目记录

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

    面试中的题目记录

    关于常用的标头会存储在静态索引表固定的位置,详见 httpwg.org/specs/rfc75…

    面试中的题目记录

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

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

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

    相关链接

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

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

    可以采用 depcheck 来完成这件事

    $ npm install depcheck -g
    
    $ depcheck
    Unused dependencies
    * underscore
    Unused devDependencies
    * jasmine
    Missing dependencies
    * lodash
    

    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(最高) 具有更高的权重

    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()
    

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

    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 及使用场景

    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 一样做一个简单的模拟实现,以下代码见 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 中如何实现继承

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

    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 中证书的格式化信息有哪些

    在 TLS 握手过程中,服务器端需要给客户端提供证书,X.509 就是证书的标准格式。

    面试中的题目记录

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

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

    相关链接

    • What Is an X.509 Certificate?

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

    1. OSCP Stapling
    2. TLS 1.3

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

    关于路由中解析 querystring,无论前端开发还是后端开发都无时无刻在使用这项功能,即使几乎没有人手动解析过它。这里来实现一个简单粗暴的解析函数

    1. 如何使用正则解析 qs
    2. 如何正确转义汉字
    3. 如何正确处理数组
    4. 如何处理各种复杂的嵌套对象

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

    // {}
    '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

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

    日问


    博客


    起源地下载网 » 面试中的题目记录

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元