前端八股文

724 阅读10分钟

1. JS

数据类型

number、string、boolean、null、undefined、symbol、bigint、object

Promise

  1. 对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)
  2. 一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected

有如下方法:

  1. Promise.prototype.then()
    1. then方法的第一个参数是resolved状态的回调函数,第二个参数是rejected状态的回调函数,它们都是可选的
    2. then方法返回的是一个新的Promise实例(注意,不是原来那个Promise实例)
  2. Promise.prototype.catch()
    1. Promise.prototype.catch()方法是.then(null, rejection)或.then(undefined, rejection)的别名,用于指定发生错误时的回调函数
    2. catch方法返回的是一个新的Promise实例
  3. Promise.prototype.finally()
    1. finally()方法用于指定不管 Promise 对象最后状态如何,都会执行的操作。该方法是 ES2018 引入标准的
    2. finally方法没有返回值(undefined)
  4. Promise.all()
    1. Promise.all()方法用于将多个 Promise 实例,包装成一个新的 Promise 实例
    2. 以这段代码为例:const p = Promise.all([p1, p2, p3]),p的状态由p1、p2、p3决定,分成两种情况:
      1. 只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数
      2. 只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数
  5. Promise.race()
    1. Promise.race()方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例
    2. 以这段代码为例:const p = Promise.race([p1, p2, p3]);
      1. 只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给p的回调函数
      2. Promise.race()方法的参数与Promise.all()方法一样,如果不是 Promise 实例,就会先调用下面讲到的Promise.resolve()方法,将参数转为 Promise 实例,再进一步处理
  6. Promise.allSettled()
    1. ES2020 引入了Promise.allSettled()方法,用来确定一组异步操作是否都结束了(不管成功或失败)。所以,它的名字叫做”Settled“,包含了”fulfilled“和”rejected“两种情况
    2. 以这段代码为例:const p = Promise.allSettled([p1, p2, p3]),等所有异步操作完成后,会返回一个Promise对象,该对象携带一个结果数组,每个元素内容如下:
      1. 成功:{ status: 'fulfilled', value: 'zhangsan' }
      2. 失败:{ status: 'rejected', reason: 'wangwu' }
  7. Promise.any()
    1. ES2021 引入了Promise.any()方法。该方法接受一组 Promise 实例作为参数,包装成一个新的 Promise 实例返回
    2. 只要参数实例有一个变成fulfilled状态,包装实例就会变成fulfilled状态;如果所有参数实例都变成rejected状态,包装实例就会变成rejected状态
    3. Promise.any()跟Promise.race()方法很像,只有一点不同,就是Promise.any()不会因为某个 Promise 变成rejected状态而结束,必须等到所有参数 Promise 变成rejected状态才会结束
  8. Promise.resolve()
    1. 有时需要将现有对象转为 Promise 对象,Promise.resolve()方法就起到这个作用
    2. Promise.resolve()方法的参数分成四种情况:详情请点击标题跳转查看
  9. Promise.reject()
    1. Promise.reject(reason)方法也会返回一个新的 Promise 实例,该实例的状态为rejected

宏任务与微任务

参考链接:juejin.cn/post/684490…

执行顺序:主线程 > 微任务 > 宏任务

属于微任务(micro task)的有:Promise.prototype.(then, catch, finally)、process.nextTick、MutationObserver

属于宏任务(macro task)的有:setTimeout、setInterval、setImmediate、I/O

注:Promise回调函数中的部分属于主线程

防抖节流【性能优化】

参考链接:segmentfault.com/a/119000001…

防抖(debounce):

对于短时间内连续触发的事件(例如滚动事件),防抖的含义就是让某个时间期限(如上面的1000毫秒)内,事件处理函数只执行一次。代码如下:

function debounce(fn, delay) {
   let timer = null; // 借助了闭包
   return function() {
      if (timer) clearTimeout(timer);
      timer = setTimeout(fn, delay);
   }
}

闭包指的是那些引用了另一个函数作用域中变量的函数,通常是在嵌套函数中实现的(来自红宝书)

节流(throttle):

如果短时间内大量触发同一事件,那么在函数执行一次之后,该函数在指定的时间期限内不再工作,直至过了这段时间才重新生效

function throttle(fn, delay) {
   let valid = true;   // 是否处于工作状态
   return function() {
      if (!valid) return false;   // 休息时间,暂不工作
      valid = false;  // 工作时间,在间隔期状态设为无效
      setTimeout(() => {
         fn();
         valid = true;
      }, delay);
   }
}

请注意,节流函数并不止上面这种实现方案。例如可以完全不借助setTimeout,可以把状态位换成时间戳,然后利用时间戳差值是否大于指定间隔时间来做判定。也可以直接将setTimeout的返回的标记当做判断条件-判断当前定时器是否存在,如果存在表示还在冷却,并且在执行fn之后消除定时器表示激活,原理都一样

使用时间戳作为判断条件:

function throttle(fn, delay) {
   let timestamp = 0;
   return function() {
      const now = Date.now();
      if (now - timestamp <= delay) return false;
      timestamp = now;
      setTimeout(fn, delay);
   };
}

使用setTimeout的返回的标记当做判断条件:

function throttle(fn, delay) {
   let timer = null;
   return function() {
      if (timer) return false;
      timer = setTimeout(() => {
         fn();
         timer = null;
      }, delay);
   };
}

应用场景:

  1. 搜索框input事件,例如要支持输入实时搜索可以使用节流方案
  2. 页面resize事件,常见于需要做页面适配的时候。需要根据最终呈现的页面情况进行dom渲染(这种情形一般是使用防抖,因为只需要判断最后一次的变化情况)

XSS 和 CSRF【安全】

  • XSS(Cross Site Scripting)跨站脚本攻击:页面渲染的数据中包含可运行的脚本;
  • CSRF(Cross Site Request Forgy)跨站请求伪造:在第三方网站向本网站发起请求;

2. CSS

BFC

参考链接:zhuanlan.zhihu.com/p/25321647

BFC 即 Block Formatting Contexts (块级格式化上下文),它属于上述定位方案的普通流

具有 BFC 特性的元素可以看作是隔离了的独立容器,容器里面的元素不会在布局上影响到外面的元素,并且 BFC 具有普通容器所没有的一些特性。

触发 BFC:

  • body 根元素;
  • 浮动元素:float 除 none 以外的值;
  • 绝对定位元素:position (absolute、fixed);
  • display 为 inline-block、table-cells、flex;
  • overflow 除了 visible 以外的值 (hidden、auto、scroll);

效果:

  • 同一个 BFC 中的元素之间下外边距会发生折叠,如果想要避免外边距的重叠,可以将其放在不同的 BFC 容器中(避免元素外边距合并);
  • BFC 可以包含浮动的元素(清除浮动);
  • BFC 可以阻止元素被浮动元素覆盖(这个方法可以用来实现两列自适应布局,效果不错,这时候左边的宽度固定,右边的内容自适应宽度);

3. 计算机基础

计算机网络体系结构

OSI(Open System Interconnection Model,开放式系统互联模型) 的七层协议、TCP/IP 的四层协议、五层协议。

学习计算机网络时我们一般采用折中的办法,也就是中和 OSI 和 TCP/IP 的优点,采用一种只有五层协议的体系结构。

snailclimb.gitee.io/javaguide/#…

应用层有哪些协议

常见的:HTTP、DNS、FTP、SMTP(Simple Mail Transfer Protocol,简单邮件传输协议) 等。

HTTP 请求方式

根据 HTTP 标准,HTTP 请求可以使用多种请求方法。

HTTP1.0 定义了三种请求方法: GET, POST 和 HEAD方法。

HTTP1.1 新增了六种请求方法:OPTIONS、PUT、PATCH、DELETE、TRACE 和 CONNECT 方法。

序号方法描述
1GET请求指定的页面信息,并返回实体主体。
2HEAD类似于 GET 请求,只不过返回的响应中没有具体的内容,用于获取报头
3POST向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST 请求可能会导致新的资源的建立和/或已有资源的修改。
4PUT从客户端向服务器传送的数据取代指定的文档的内容。
5DELETE请求服务器删除指定的页面。
6CONNECTHTTP/1.1 协议中预留给能够将连接改为管道方式的代理服务器。
7OPTIONS允许客户端查看服务器的性能。
8TRACE回显服务器收到的请求,主要用于测试或诊断。
9PATCH是对 PUT 方法的补充,用来对已知资源进行局部更新 。

HTTP2.0 大幅度的提高了 web 性能,在 HTTP1.1 完全语义兼容的基础上,进一步减少了网络的延迟:二进制分帧、首部压缩、多路复用、请求优先级、服务器推送。

浏览器输入 URL 的解析过程

  1. 根据域名到 DNS 中找到 IP;

  2. 根据IP建立 TCP 连接(三次握手);

  3. 连接建立成功发起 http 请求;

  4. 服务器响应 http 请求;

  5. 浏览器解析 HTML 代码并请求 html 中的静态资源(js, css);

  6. 关闭 TCP 连接(四次挥手);

  7. 浏览器渲染页面

GET 和 POST 的区别(都要遵循 HTTP 规范)

  • 数据存放位置不同:GET 请求的数据会附在 URL 之后,而 POST请求的数据放置在 HTTP 包的包体中。
  • 安全性不同:POST 的安全性要比 GET 的安全性高。
  • 资源消耗:GET 和 POST 还有一个重大区别,简单的说:GET 产生一个 TCP 数据包;POST 产生两个 TCP 数据包。对于 GET 方式的请求,浏览器会把 http header 和 data 一并发送出去,服务器响应 200(返回数据);而对于 POST,浏览器先发送 header,服务器响应 100 continue,浏览器再发送 data,服务器响应 200 ok(返回数据)。

注意:

  • GET 请求中,URL 不存在参数上限的问题,HTTP 协议规范没有对 URL 长度进行限制。这个限制是特定浏览器服务器对它的限制。所以 POST 也是没有大小长度限制的,HTTP 协议规范也没有进行大小限制。起限制作用的是服务器的处理能力。

状态码

参考链接:www.runoob.com/http/http-s…

跨域

参考链接:segmentfault.com/a/119000000…

什么是跨域?

只要协议、域名、端口有任何一个不同,都被当作是不同的域。

CORS

CORS 是一个W3C 标准,全称是"跨域资源共享"(Cross-origin resource sharing)。

它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。

浏览器缓存

参考链接:blog.csdn.net/z591102/art…

cookie 和 session

localStorage 和 sessionStorage

强缓存和协商缓存

参考链接:blog.csdn.net/goutinga/ar…

4. Vue & React

Vue组件传值的方式

  1. 路由传参;
  2. 子组件向父组件传值;
  3. 父组件向子组件传值;
  4. 路由总线($bus);
  5. 本地存储,LocalStorage、SessionStorage、Vuex

虚拟 DOM 和 diff 算法

虚拟DOM就是为了解决浏览器性能问题而被设计出来的。如前,若一次操作中有10次更新DOM的动作,虚拟DOM不会立即操作DOM,而是将这10次更新的diff内容保存到本地一个JS对象中,最终将这个JS对象一次性attch到DOM树上,再进行后续操作,避免大量无谓的计算量。**所以,**用JS对象模拟DOM节点的好处是,页面的更新可以先全部反映在JS对象(虚拟DOM)上,操作内存中的JS对象的速度显然要更快,等更新完成后,再将最终的JS对象映射成真实的DOM,交由浏览器去绘制。

5. 案例

  1. SSO:单例登录(Single Sign-On)

6. 了解岗位

  1. 待遇(工资、公积金缴纳额度)
  2. 工作地点,工作时间,工作作息(加班是否有加班费)