深圳某海外直播公司

1. CommonJS和ES6模块的区别

  • CommonJS模块是运行时加载,ES6 Modules是编译时输出接口
  • CommonJS输出是值的拷贝;ES6 Modules输出的是值的引用,被输出模块的内部的改变会影响引用的改变
  • CommonJs导入的模块路径可以是一个表达式,因为它使用的是require()方法;而ES6 Modules只能是字符串
  • CommonJS this指向当前模块,ES6 Modules this指向undefined
  • 且ES6 Modules中没有这些顶层变量:arguments、require、module、exports、__filename、__dirname

关于第一个差异,是因为CommonJS 加载的是一个对象(即module.exports属性),该对象只有在脚本运行完才会生成。而 ES6 模块不是对象,它的对外接口只是一种静态定义,在代码静态解析阶段就会生成。

2. 模块的异步加载

模块的异步加载可以使用AMD或者CMD规范。

3. 开发一个模块要考虑哪些问题?

封闭开放式原则、安全性

4. 实现一个一组异步请求按顺序执行你有哪些方法?

  • 利用reduce,初始值传入一个Promise.resolve(),之后往里面不停的叠加.then()
  • 利用forEach,本质和reduce原理相同
  • 还可以用ES9中的for...await...of来实现。

5. Promise.all()是并发的还是串行的?

并发的。不过Promise.all().then()结果中数组的顺序和Promise.all()接收到的数组顺序一致。

6. 平时写过哪些正则表达式

  • 之前有用过用正则去除输入框的首尾空格,正则表达式为:var trimReg = /(^\s+)|(\s+$)/g;不过后来由于Vue中有一个修饰符.trim,使用起来更方便(如v-model.trim="msg")就用这种方式多一些;再或者也可以用ES10新出的trimStart和trimEnd来去除首尾空格。
  • 用于校验手机号的正则:var phoneReg = /^1[3456789]\d{9}$/g
  • 用正则写一个根据name获取cookie中的值的方法:
    function getCookie(name) {
      var match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]*)'));
      if (match) return unescape(match[2]);
    }

7. 正则里的非如何实现的

^要是放在[]里的话就表示"除了^后面的内容都能匹配",也就是非的意思。

例如:

(除了l,其它都变成了"帅")

    var str = 'lindaidai';
    console.log(str.replace(/[^l]/g, '帅'));
    // l帅帅帅帅帅帅帅帅

反之,如果是不在[]里的话则表示开头匹配:

(只有l变成了"帅")

    var str = 'lindaidai';
    console.log(str.replace(/^l/g, '帅'));

8. webpack几种hash的实现原理

  • hash是跟整个项目的构建相关,只要项目里有文件更改,整个项目构建的hash值都会更改,并且全部文件都共用相同的hash值。(粒度整个项目)
  • chunkhash是根据不同的入口进行依赖文件解析,构建对应的chunk(模块),生成对应的hash值。只有被修改的chunk(模块)在重新构建之后才会生成新的hash值,不会影响其它的chunk。(粒度entry的每个入口文件)
  • contenthash是跟每个生成的文件有关,每个文件都有一个唯一的hash值。当要构建的文件内容发生改变时,就会生成新的hash值,且该文件的改变并不会影响和它同一个模块下的其它文件。(粒度每个文件的内容)

9. webpack如果使用了hash命名,那是每次都会重写生成hash吗

这个问题在上一个问题中已经说明了,要看webpack的配置。

有三种情况:

  • 如果是hash的话,是和整个项目有关的,有一处文件发生更改则所有文件的hash值都会发生改变且它们共用一个hash值;
  • 如果是chunkhash的话,只和entry的每个入口文件有关,也就是同一个chunk下的文件有所改动该chunk下的文件的hash值就会发生改变
  • 如果是contenthash的话,和每个生成的文件有关,只有当要构建的文件内容发生改变时才会给该文件生成新的hash值,并不会影响其它文件。

10. webpack中如何处理图片的?

在webpack中有两种处理图片的loader:

  • file-loader:解决CSS等中引入图片的路径问题;(解决通过url,import/require()等引入图片的问题)
  • url-loader:当图片小于设置的limit参数值时,url-loader将图片进行base64编码(当项目中有很多图片,通过url-loader进行base64编码后会减少http请求数量,提高性能),大于limit参数值,则使用file-loader拷贝图片并输出到编译目录中;

11. 说一下回流和重绘

1. 回流:

触发条件:

当我们对 DOM 结构的修改引发 DOM 几何尺寸变化的时候,会发生回流的过程。

例如以下操作会触发回流:

  • 一个 DOM 元素的几何属性变化,常见的几何属性有width、height、padding、margin、left、top、border 等等, 这个很好理解。
  • 使 DOM 节点发生增减或者移动。
  • 读写 offset族、scroll族和client族属性的时候,浏览器为了获取这些值,需要进行回流操作。
  • 调用 window.getComputedStyle 方法。

回流过程:由于DOM的结构发生了改变,所以需要从生成DOM这一步开始,重新经过样式计算、生成布局树、建立图层树、再到生成绘制列表以及之后的显示器显示这整一个渲染过程走一遍,开销是非常大的

2. 重绘:

触发条件:

当 DOM 的修改导致了样式的变化,并且没有影响几何属性的时候,会导致重绘(repaint)。

重绘过程 :由于没有导致 DOM 几何属性的变化,因此元素的位置信息不需要更新,所以当发生重绘的时候,会跳过生存布局树和建立图层树的阶段,直接到生成绘制列表,然后继续进行分块、生成位图等后面一系列操作。

如何避免触发回流和重绘:

  • 避免频繁使用 style,而是采用修改class的方式。
  • 将动画效果应用到position属性为absolute或fixed的元素上。
  • 也可以先为元素设置display: none,操作结束后再把它显示出来。因为在display属性为none的元素上进行的DOM操作不会引发回流和重绘
  • 使用createDocumentFragment进行批量的 DOM 操作。
  • 对于 resize、scroll 等进行防抖/节流处理。
  • 避免频繁读取会引发回流/重绘的属性,如果确实需要多次使用,就用一个变量缓存起来。
  • 利用 CSS3 的transform、opacity、filter这些属性可以实现合成的效果,也就是GPU加速。

12. 盒模型及如何转换

  • box-sizing: content-box(W3C盒模型,又名标准盒模型):元素的宽高大小表现为内容的大小。
  • box-sizing: border-box(IE盒模型,又名怪异盒模型):元素的宽高表现为内容 + 内边距 + 边框的大小。背景会延伸到边框的外沿。

13. 实现水平垂直居中的几种方式

Flex布局(子元素是块级元素)

    .box {
      display: flex;
      width: 100px;
      height: 100px;
      background-color: pink;
    }
    
    .box-center{
      margin: auto;
      background-color: greenyellow;
    }

Flex布局

    .box {
      display: flex;
      width: 100px;
      height: 100px;
      background-color: pink;
      justify-content: center;
      align-items: center;
    }
    
    .box-center{
      background-color: greenyellow;
    }

绝对定位实现(定位元素定宽定高)

    .box {
      position: relative;
      height: 100px;
      width: 100px;
      background-color: pink;
    }
    
    .box-center{
      position: absolute;
      left: 0;
      right: 0;
      bottom: 0;
      top: 0;
      margin: auto;
      width: 50px;
      height: 50px;
      background-color: greenyellow;
    }

14. flex的兼容性怎样

简单回答:

IE6~9不支持,IE10~11部分支持flex的2012版,但是需要-ms-前缀。

其它的主流浏览器包括安卓和IOS基本上都支持了。

详细回答:

  • IE10部分支持2012,需要-ms-前缀
  • Android4.1/4.2-4.3部分支持2009 ,需要-webkit-前缀
  • Safari7/7.1/8部分支持2012, 需要-webkit-前缀
  • IOS Safari7.0-7.1/8.1-8.3部分支持2012,需要-webkit-前缀

15. 你知道到哪里查看兼容性吗

可以到Can I use上去查看

16. 移动端中css你是使用什么单位

比较常用的:

  • em:定义字体大小时以父级的字体大小为基准;定义长度单位时以当前字体大小为基准。例父级font-size: 14px,则子级font-size: 1em;为font-size: 14px;;若定义长度时,子级的字体大小如果为14px,则子级width: 2em;为width: 24px。
  • rem:以根元素的字体大小为基准。例如html的font-size: 14px,则子级1rem = 14px。 %:以父级的宽度为基准。例父级width: 200px,则子级width: 50%;height:50%;为width: 100px;height: 100px;
  • vwvh:基于视口的宽度和高度(视口不包括浏览器的地址栏工具栏和状态栏)。例如视口宽度为1000px,则60vw = 600px;
  • vminvmax:vmin为当前vw 和vh中较小的一个值;vmax为较大的一个值。例如视口宽度375px,视口高度812px,则100vmin = 375px;,100vmax = 812px;

不常用的:

ex和ch:ex以字符"x"的高度为基准;例如1ex表示和字符"x"一样长。ch以数字"0"的宽度为基准;例如2ch表示和2个数字"0"一样长。

移动端布局总结:

  • 移动端布局的方式主要使用rem和flex,可以结合各自的优点,比如flex布局很灵活,但是字体的大小不好控制,我们可以使用rem和媒体查询控制字体的大小,媒体查询视口的大小,然后不同的上视口大小下设置设置html的font-size。
  • 可单独制作移动端页面也可响应式pc端移动端共用一个页面。没有好坏,视情况而定,因势利导

17. rem和em的区别

em:

定义字体大小时以父级的字体大小为基准;定义长度单位时以当前字体大小为基准。例父级font-size: 14px,则子级font-size: 1em;为font-size: 14px;;若定义长度时,子级的字体大小如果为14px,则子级width: 2em;为width: 24px。

rem:

以根元素的字体大小为基准。例如html的font-size: 14px,则子级1rem = 14px。

18. 在移动端中怎样初始化根元素的字体大小

一个简易版的初始化根元素字体大小。

页面开头处引入下面这段代码,用于动态计算font-size:

(假设你需要的1rem = 20px)

    (function () {
      var html = document.documentElement;
      function onWindowResize() {
        html.style.fontSize = html.getBoundingClientRect().width / 20 + 'px';
      }
      window.addEventListener('resize', onWindowResize);
      onWindowResize();
    })();
  • document.documentElement:获取document的根元素
  • html.getBoundingClientRect().width:获取html的宽度(窗口的宽度)
  • 监听window的resize事件

一般还需要配合一个meta头:

    <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-sacle=1.0, maximum-scale=1.0, user-scalable=no" />

19. 移动端中不同手机html默认的字体大小都是一样的吗

如果没有人为取改变根元素字体大小的话,默认是1rem = 16px;根元素默认的字体大小是16px。

20. 你做过哪些动画效果

实话实说没太做过。

21. 如果让你实现一个一直旋转的动画你会如何做

css代码:

    <style>
      .box {
        width: 100px;
        height: 100px;
        background-color: red;
        animation: spin 2s linear infinite;
      }
      @keyframes spin {
        from { transform: rotate(0deg) }
        to { transform: rotate(360deg) }
      }
    </style>

html代码:

    <div class="box"></div>

22. animation介绍一下

    animation: name duration timing-function delay iteration-count direction;
  • animation-name 规定需要绑定到选择器的 keyframe 名称。(mymove)
  • animation-duration 规定完成动画所花费的时间,以秒或毫秒计。(2s)
  • animation-timing-function 规定动画的速度曲线。(ease|linear|ease-in|cubic-bezier(n,n,n,n))
  • animation-delay 规定在动画开始之前的延迟。(2s)
  • animation-iteration-count 规定动画应该播放的次数。(n | infinite) n次/无限
  • animation-direction 规定是否应该轮流反向播放动画。(normal | alternate) 正常/反向

23. animation有一个steps()功能符知道吗

一句话介绍:steps()功能符可以让动画不连续。

  • 地位和作用:和贝塞尔曲线(cubic-bezier()修饰符)一样,都可以作为animation的第三个属性值。
  • 和贝塞尔曲线的区别:贝塞尔曲线像是滑梯且有4个关键字(参数),而steps像是楼梯坡道且只有number和position两个关键字。
    steps(number, position)
  • number: 数值,表示把动画分成了多少段
  • position: 表示动画是从时间段的开头连续还是末尾连续。支持start和end两个关键字,含义分别如下:
    • start`:表示直接开始。
    • end`:表示戛然而止。是默认值。

24. 用过哪些移动端的调试工具

  • Chrome浏览器 -> more tools -> Remote devices -> chrome://inspect/#devices
  • Mac + IOS + Safari

25. 说一下原型链

26. 详细说一下instanceof

27. V8的垃圾回收是发生在什么时候?

V8引擎帮助我们实现了自动的垃圾回收管理,利用浏览器渲染页面的空闲时间进行垃圾回收。

28. 具体说一下垃圾回收机制

栈内存的回收:

栈内存调用栈上下文切换后就被回收,比较简单。

堆内存的回收:

V8的堆内存分为新生代内存和老生代内存,新生代内存是临时分配的内存,存在时间短,老生代内存存在时间长。

新生代内存回收机制:

新生代内存容量小,64位系统下仅有32M。新生代内存分为From、To两部分,进行垃圾回收时,先扫描From,将非存活对象回收,将存活对象顺序复制到To中,之后调换From/To,等待下一次回收

老生代内存回收机制

  • 晋升:如果新生代的变量经过多次回收依然存在,那么就会被放入老生代内存中
  • 标记清除:老生代内存会先遍历所有对象并打上标记,然后对正在使用或被强引用的对象取消标记,回收被标记的对象
  • 整理内存碎片:把对象挪到内存的一端

29. 在项目中如何把http的请求换成https

由于我在项目中是会对axios做一层封装,所以每次请求的域名也是写在配置文件中,有一个baseURL字段专门用于存储它,所以只要改这个字段就可以达到替换所有请求http为https了。

当然后面我也有了解到:

利用meta标签把http请求换为https:

    <meta http-equiv ="Content-Security-Policy" content="upgrade-insecure-requests">

30. 知道meta标签有把http换成https的功能吗?

参考上一题👆。

31. http请求可以怎么拦截

在浏览器和服务器进行传输的时候,可以被nginx代理所拦截,也可以被网关拦截。

32. https的加密方式

  • HTTPS主要是采用对称密钥加密和非对称密钥加密组合而成的混合加密机制进行传输。
  • 也就是发送密文的一方用"对方的公钥"进行加密处理"对称的密钥",然后对方在收到之后使用自己的私钥进行解密得到"对称的密钥",这在确保双发交换的密钥是安全的前提下使用对称密钥方式进行通信。

33. 混合加密的好处

  • 对称密钥加密和非对称密钥加密都有它们各种的优缺点,而混合加密机制就是将两者结合利用它们各自的优点来进行加密传输。
  • 比如既然对称密钥的优点是加解密效率快,那么在客户端与服务端确定了连接之后就可以用它来进行加密传输。不过前提是得解决双方都能安全的拿到这把对称密钥。这时候就可以利用非对称密钥加密来传输这把对称密钥,因为我们知道非对称密钥加密的优点就是能保证传输的内容是安全的。
  • 所以它的好处是即保证了对称密钥能在双方之间安全的传输,又能使用对称加密方式进行通信,这比单纯的使用非对称加密通信快了很多。以此来解决了HTTP中内容可能被窃听的问题

其它HTTP相关的问题:

如:

  • HTTPS的工作流程
  • 混合加密机制的好处
  • 数字签名
  • ECDHE握手和RSA握手
  • 向前安全性

34. 浏览器如何验证服务器的身份

  • 这道题主要可以从数字签名和数字证书上来答。
  • 当时我答的时候就把证书的颁发流程、HTTPS数字证书的验证过程完整的说了一遍就算过了。

35. ETag首部字段说一下

这个无非就是配合If-None-Match来达到一个协商缓存的作用。值为服务器某个资源的唯一标识。

36. 你们的token一般是存放在哪里的

Token其实就是访问资源的凭证。

一般是用户通过用户名和密码登录成功之后,服务器将登陆凭证做数字签名,加密之后得到的字符串作为token。 它在用户登录成功之后会返回给客户端,客户端主要有这么几种存储方式:

  • 存储在localStorage中,每次调用接口的时候都把它当成一个字段传给后台
  • 存储在cookie中,让它自动发送,不过缺点就是不能跨域
  • 拿到之后存储在localStorage中,每次调用接口的时候放在HTTP请求头的Authorization字段里

37. token会不会被伪造?

38. redis中一般用来存什么

用户登录成功之后的一些信息

39. 前后端如何验证一个用户是否下线了

40. CSP白名单知道吗?

41. nginx有配置过吗?

只会配置一些跨域方面的问题。

    events {
        worker_connections  1024;
    }
    http {
        include       mime.types;
        default_type  application/octet-stream;
        sendfile        on;
        keepalive_timeout  65;
        server {
            listen       80;
            server_name  localhost;
            location / {
                proxy_pass  http://localhost:8887;
                add_header  Access-Control-Allow-Origin *;
            }
        }
    }

利用ngnix跨域的关键就是在配置文件中设置server项,然后设置其中的location属性,proxy_pass:需要代理的服务器地址,add_header:给响应报文中添加首部字段,例如Access- Control-Allow-Origin设置为*,即允许所有的请求源请求

42. 反向代理知道吗?

我们将请求发送到服务器,然后服务器对我们的请求进行转发,我们只需要和代理服务器进行通信就好。所以对于客户端来说,是感知不到服务器的。

43. 有用过抓包工具吗?

44. 你平常用的电脑是Mac吗?

(...默默的点头)

45. Fiddler有用过吗?

唔...知道...

46. Vue的diff算法

47. Vue中computed和methods的区别

48. 例如要获取当前时间你会放到computed还是methods里?

放在methods中,因为computed会有惰性,并不能知道new Date()的改变。

49. 你们的权限功能是怎么做的?

50. 那你在判断权限的时候是用的字符串匹配还是位运算?

和面试官扯了一堆我数据权限判断的具体过程,其中可能有多个权限:并的情况000011110001&000011110002,或的情况000011110001|000011110002,以及如何做的权限匹配。最后面试官:

"所以那还是用的字符串匹配咯?" 尬...我比较low...用的字符串匹配... (哇,真的绝了...1个小时20分钟50多道题,答的我口渴😂,不过也可以看出有很多移动端的我都没有答上来,面试官也表示理解,毕竟我主要是以PC端为主,所以竟然也算是过了,很感谢这位面试官细心的帮我分析一些问题)

Last Updated:
Contributors: leeguooooo