前端面经整理

Posted 365/24/60

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了前端面经整理相关的知识,希望对你有一定的参考价值。

节流、防抖

防抖
<div>
    <input type="text" id="input">
</div>
<script>
    listenInput = ()=>{
      console.log(\'输入结束,调用接口\');
    }
    function debounce(fn , wait){
      let start = Date.now() , end , st
      return ()=>{
        end = Date.now()
        if(end - start < wait){
          clearTimeout(st)
          st = setTimeout(() => {
            fn()
          }, wait);
        }else{
          st = setTimeout(() => {
            fn()
          }, wait);
        }
        start = Date.now()
      }
    }
    let input = document.querySelector(\'#input\')
    input.oninput = debounce(listenInput , 1000)
</script>
节流
<div>
    <input type="text" id="input">
</div>
<script>
    listenClick = ()=>{
      console.log(\'移动\');
    }
    function throttling(fn , wait){
      // 节流
      let start = Date.now() , end
      return ()=>{
        end =  Date.now()
        if(end-start>=wait){
          fn()
          start = Date.now()
        }
      }
    }
    document.onmousemove = throttling(listenClick ,1000)
</script>

排序算法

快速排序
let quickSort = function(arr){
      let low = 1 , high = arr.length-1 , key = arr[0]
      while(high > low){
          if( arr[low] > key ){
              let temp = arr[high]
              arr[high--] = arr[low]
              arr[low] = temp
          }else{
              arr[low-1] = arr[low++]
          }
       }
       arr[low] = key
       low > 0 && quickSort(arr.slice(0 , low))
       low < arr.length-1 && quickSort(arr.slice(low+1))
}
二分查找
let binarySearch = function(arr, num){
      let low = 0 , high = arr.length , mid
      while(high > low){
          mid = Math.floor((low+ high)/2)
          if(arr[mid] === num ){
              return mid
          }else if(arr[mid] > num){
              high = mid-1
          }else{
              low = mid +1
          }
       }
       return -1
}
归并排序
let mergeSort = function(arr){
      if(arr.length === 1){
          return arr
      }else if(arr.length > 1){
          let mid = Math.floor(arr.length / 2)
          let arrL = mergeSort(arr.slice(0 , mid))
          let arrR = mergeSort(arr.slice(mid))
          let llen = arrL.length , rlen = arrR.length , ret = [] , l = 0 , r = 0
          while(llen > l && rlen > r ){
                 if(arrL[l] > arrR[r]){
                     ret.push(arrR[r++])
                 }else{
                     ret.push(arrL[l++])
                 }
          }
          if(l < llen || r < rlen){
                 ret = ret.concat(l < llen ? arrL.slice(l) : arrR.slice(r))
          }
          return ret
	}
}

https实现原理

http存在的问题:
  • 通信使用明文
  • 无法证明报文的完整性,可能被篡改信息
  • 不验证对方的身份,可能伪装
对称/非对称加密的特点
对称/非对称加密的特点:
  • 对称加密:加密和解密使用同一个密钥
    • 密钥可能落入他人之手,失去加密的意义
  • 非对称加密:私有密钥、公开密钥(任何人获得)
    • 黑客窃取到公开密钥,解密交流信息
    • 公钥不包含身份信息,存在中间人攻击
    • 加密、解密过程消耗时间大,效率低
解决内容可能被窃听:
  • 交换密钥(后续会话)使用非对称加密,客户端使用服务器的公开密钥 加密 会话密钥 发送给 服务器
  • 后续会话使用 会话密钥 加密通话
数字签名特点:
  • 能确定发送方的身份
  • 确定信息的完整性,确认未被篡改
生成数字签名:
如何证明公钥是服务器的 => 证书颁发机构(Certificate Authority,CA),CA 生成服务器的公钥的数字签名(证书),而客户端内置受信任的CA的证书(CA的公钥)
数字证书:确定发送方只会是真正的发送方发送过(即公钥未被截取),服务器公钥是该服务器的
  • 服务器的运营人员向第三方机构CA提交公钥、组织信息、个人信息(域名)等信息并申请认证
  • CA通过线上、线下等多种手段验证申请者提供信息的真实性
  • 如信息审核通过,CA会向申请者签发认证文件-证书,包含:
    • 明文部分:申请者(服务器)公钥、申请者的组织信息和个人信息、签发机构 CA的信息、有效时间、证书序列号等信息的明文
    • 签名部分:明文=散列函数=>CA私钥加密=>签名
  • 客户端 Client 向服务器 Server 发出请求时,Server 返回证书文件
  • 客户端使用对应的 CA 公钥解密签名数据,确定是否合法,合法则该服务器的公钥是值得信赖的
HTTPS工作流程:

前端攻击有哪些? 如何防范

XSS攻击本质:恶意代码未经过滤,与网站正常的代码混在一起,而浏览器是无法辨认哪些脚本是恶意的导致恶意脚本被执行

XSS:其实我简称CSS,Cross-Site Scripting,跨站脚本攻击 根据攻击来源分类:
  • 反射型XSS:
    • 攻击者构造出特殊的url,其中包含恶意代码(需要用户主动点击,往往装扮的很诱人)
    • 用户打开带有恶意代码的url时,网站服务端将恶意代码从url取出,拼接在html中返回给用户
    • 浏览器接受到之后立即执行,可以窃取用户数据
  • DOM型XSS:
    • 前端不严谨,使用 .innerHTML、.outerHTML、.appendChild、document.write() 等API
    • 同上,构造除了恶意的DOM片段,被插入了
恶意DOM片段:
<a href="#" onclick="doAttack()">
     click me
     <script type="text/javascript">
        function doAttack() {
            while (true) {
                alert(\'u are under attack\');
            }
        }
     </script>
</a>
+ 存储型XSS: + 攻击者将恶意代码提交到目标网站的数据库中 + 用户打开目标网站时,网站服务端将恶意代码从数据库取出,拼接在 HTML 中返回给浏览器 + 同上
XSS攻击防范
冷兵器时代:(无间道之处处防范)
  • 反射型XSS:
app.get(\'/welcome\', function(req, res) {
    //对查询参数进行编码,避免反射型 XSS攻击
    res.send(`${encodeURIComponent(req.query.type)}`); 
});
  • DOM型XSS:
    • 对于url链接(例如图片的src属性),那么直接使用 encodeURIComponent 来转义
    • 非url,我们可以这样进行编码:
function encodeHtml(str) {
    if(!str) return \'\';
    return str.replace(/"/g, \'&quot;\')
            .replace(/\'/g, \'&apos;\')
            .replace(/</g, \'&lt;\')
            .replace(/>/g, \'&gt;\')
            .replace(/&/g, \'&amp\');
}
  • 存储型XSS:
    • 前端数据传递给服务器之前,先转义/过滤
    • 服务器接收到数据,在存储到数据库之前,进行转义/过滤
    • 前端接收到服务器传递过来的数据,在展示到页面前,先进行转义/过滤
CSP:Content-Security-Policy(二向箔划痕打击)
  • 如何使用: Content-Security-Policy: default-src \'self\' //想要所有内容均来自站点的同一个源 (不包括其子域名):

CSRF攻击:跨站请求伪造,攻击者诱导受害者进入第三方网站,在第三方网站中,向被攻击网站发送跨站请求。利用受害者在被攻击网站已经获取的注册凭证,绕过后台的用户验证,达到冒充用户对被攻击的网站执行某项操作的目的。

CSRF:Cross-Site Request Forgery,(伪装者之披着羊皮的狼)
  • 受害者登录A站点,并保留了登录凭证(Cookie
  • 攻击者诱导受害者访问了站点B
  • 站点B向站点A发送了一个请求,浏览器会默认携带站点A的Cookie信息
  • 站点A接收到请求后,对请求进行验证,并确认是受害者的凭证,误以为是无辜的受害者发送的请求
  • 站点A以受害者的名义执行了站点B的请求
  • 攻击完成,攻击者在受害者不知情的情况下,冒充受害者完成了攻击
CSRF攻击防范
  • 添加验证码(体验不好,繁琐)
  • 可以要求所有的用户请求都携带一个CSRF攻击者无法获取到的Token。服务器通过校验请求是否携带正确的Token,来把正常的请求和攻击的请求区分开
    • 服务端给用户生成一个token,加密后传递给用户
    • 用户在提交请求时,需要携带这个token
    • 服务端验证token是否正确

点击劫持攻击:在一个Web页面中隐藏了一个透明的iframe,用外层假页面诱导用户点击,实际上是在隐藏的frame上触发了点击事件进行一些用户不知情的操作

性感荷官在线发牌...(好胆你就点) 攻击过程:
  • 攻击者构建了一个非常有吸引力的网页(跟前面有区别:攻击者构造的网页)
  • 将被攻击的页面放置在当前页面的 iframe 中
  • 使用样式将 iframe 叠加到非常有吸引力内容的上方
  • 将iframe设置为100%透明
  • 你被诱导点击了网页内容,你以为你点击的是***,而实际上,你成功被攻击了

攻击防范:

if (top.location !== window.location) {
    top.location = window.location;  }
  • 另外HTML5中 iframe的 sandbox 、IE中iframe的security 都可以限制iframe中的脚本执行

Web前端性能优化

网页内容

减少http请求:
  • CSS Sprites:雪碧图
  • 字体图标:
  • 需要请求的脚本和样式表合并起来,较少请求次数
减少 DNS 查询次数:
DNS 查询:浏览器缓存 => 操作系统缓存 => DNS查找
  • 使用 DNS 缓存
    • 缓存时间长,有利于重复利用
    • 缓存时间短:有利于及时检测目标站点 IP 更新
  • 将需要请求的内容放在同一个域名
    • 但会出现下载资源排队现象,一个网站使用 2~4个 域
避免页面跳转
缓存AJAX(Asynchronrous Javascript and XML)

--------------------------------------------------------

添加Expires头:提醒客户端可以缓存数据到一定时间
  • 初始形态:Expires: Fri, 18 Mar 2016 07:41:53 GMT
    • 要求服务求与客户端时钟严格同步:过期日期需要经常检查
  • HTTP1.1来临:Cache-Control: max-age=12345600
    • max-age、Expires同时存在,max-age 更顶,指定失效时间
  • ETags:Entity Tag,实体标签:一个特殊字符串来标识某个资源的“版本”。工作原理:
    • 客户端第一次请求资源:服务端响应:200,响应头部包含ETag的信息(ETag "6ab823201a4ece1:0")
    • 客户端再次请求该资源:请求头添加一行:If-None-Match "6ab823201a4ece1:0"
    • 此次,服务器会比对 ETag的值,如果没有变化,会返回 304状态码,响应体不需要包含任何实际内容
      • 浏览器得到304之后,直接使用本地缓存的版本
压缩组件:HTTP1.1之后
  • 客户端:表达自己接受的类型,Accept-Encoding: gzip,deflate
  • 服务器端:Content-Encoding: gzip

--------------------------------------------------------

延迟加载
  • 网页最初加载需要的最小内容集
    • 比较激进的做法是开发网页时确保没有JavaScript也能完成基本工作
    • 然后通过延迟加载完成一些高级的功能
提前加载
CDN:(Content Delivery Network)那日容分发网络,就近获取目标服务器的数据

https://juejin.cn/post/684490373633933
https://juejin.cn/post/6844904155077672968

以上是关于前端面经整理的主要内容,如果未能解决你的问题,请参考以下文章

每日面经美团点评前端开发Java工程师最新面经速递!

3天,把过去半年前端高频面试题整理全了(内含大佬面经)

前端片段整理

最新的前端大厂面经(详解答案)

熬夜肝完了,腾讯前端,Java,C++,Go面经汇总(全)

熬夜肝完了,腾讯前端,Java,C++,Go面经汇总(全)