前端面试需要准备的点(自己整理的,不断刷新)

457 阅读11分钟

1、基础知识(html,css,js)

html5,css3,es6+的用法(可以简要作为参考)
js中的一些重要的基本概念,比如:this、闭包、原型链

2、一些基本概念

2.1 盒子模型

参考盒子模型

2.2 sessionStorage,localstorage,session和cookie

参考链接

2.3 MVC,MVVM的区别

参考链接

2.4 事件循环机制、宏任务、微任务

理解堆栈
参考链接

2.5 预检请求(options)

参考链接

2.6 包含块与absolute定位

参考谈论

2.7 浏览器缓存

参考链接

2.8 正向代理与反向代理

参考链接

2.9 白屏时间和首屏时间

参考链接

2.10 React和Vue的比较

相同点

  1. 都是用了VirtualDOM。
  2. 都提供了响应式和组件化的视图组件。
  3. 都将注意力集中保持在核心库,而将其他功能如路由和全局状态管理交给相关库。
    不同点
  4. React中,当某组件的状态发生改变时,它会以该组件为根,重新渲染整个组件子树,而在Vue中,组件的依赖是在渲染的过程中自动追踪的,所以系统能准确知晓哪个组件确实需要被重新渲染。
  5. Vue的路由库和状态管理库都由官方维护支持且与核心库同步更新,而React选择把这些问题交给社区维护,因此生态更丰富。
  6. Vue-cli脚手架可进行配置
  7. react整体是函数式的思想,把组件设计成纯组件,状态和逻辑通过参数传入,所以在react中,是单向数据流;vue的思想是响应式的,也就是基于是数据可变的,通过对每一个属性建立Watcher来监听,当属性变化的时候,响应式的更新对应的虚拟dom。

2.11 变量提升

参考

2.12 堆栈深入了解

参考

2.13 严格模式

1、严格模式中禁止使用with语句(因为with语句无法在编译时就确定,属性到底归属哪个对象)
2、严格模式中,所有的变量都要先声明(a=1报错,需要var a=1)
3、严格模式中,调用一个函数(不是方法)的this指向undefined而不是window
参考阮一峰

2.14 for in,Object.keys,for of 的区别

参考

2.15 Cookie详解以及SameSite

参考

2.16 HTTP1.0 HTTP 1.1 HTTP 2.0主要区别

参考

2.17 遍历JS对象的属性

(1)for...in
for...in循环遍历对象自身的和继承的可枚举属性(不含Symbol属性)。
(2)Object.keys(obj)
Object.keys返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含Symbol属性)。
(3)Object.getOwnPropertyNames(obj)
Object.getOwnPropertyNames返回一个数组,包含对象自身的所有属性(不含Symbol属性,但是包括不可枚举属性)。
(4)Object.getOwnPropertySymbols(obj)
Object.getOwnPropertySymbols返回一个数组,包含对象自身的所有Symbol属性。
(5)Reflect.ownKeys(obj) Reflect.ownKeys返回一个数组,包含对象自身的所有属性,不管是属性名是Symbol或字符串,也不管是否可枚举。

2.18 ajax、axios、fetch

ajax、axios、fetch之间优缺点重点对比
Jquery ajax, Axios, Fetch区别之我见
fetch与axios的区别(fetch的真正用法)

2.19 内存泄漏

参考
常见的 Javascript 内存泄露以及规避方法:
1、意外的全局变量 ---文件开头添加 'use strict'
2、被遗漏的定时器(setTimeout)和回调函数(eg.addEventListener) ---clearTimeout&&removeEventListener
3、闭包
4、ES6的WeakSetWeakMap对于值的引用都是不计入垃圾回收机制的,可以避免内存泄漏

3、性能提升

需要总结性能相关的优化(可以参考雅虎性能优化军规)

较少文件体积(压缩js,css),使用Gzip压缩
尽量减少http请求,避免无效请求,部分信息可以进行缓存,没必要每次都发送请求获取
js脚本尽量置于index.html的底部,脚本阻止了页面的平行下载,优先加载CSS
使用内容分发网络(CDN,用户与你网站服务器的接近程度会影响响应时间的长短)
不要在HTML中缩放图像(eg.100×100 像素而不是把一个500×500 像素的图片缩小使用)
雪碧图

4、常见安全问题

XSS(Cross-Site Scripting,跨站脚本攻击),CSRF(Cross-site request forgery,跨站请求伪造)等,可以参考:
www.jianshu.com/p/a38e280ed…
tech.meituan.com/2018/09/27/…
XSS 利用的是用户对指定网站的信任
CSRF 利用的是网站对用户网页浏览器的信任

4.1.1 XSS的危害

攻击者可以利用XSS漏洞来窃取包括用户身份信息在内的各种敏感信息、修改Web页面以欺骗用户,甚至控制受害者浏览器,或者和其他漏洞结合起来形成蠕虫攻击,等等

4.1.2 XSS的防范

特殊字符的encode,对部分用户输入的地方进行限制(白名单/黑名单),CSP

4.1.3 XSS攻击原理分析与防御技术

参考

4.2.1 CSRF的危害

攻击者利用我们的身份发送恶意请求(比如转账等)

4.2.2 CSRF的防范

1、提交 method=Post 判断referer
HTTP请求中有一个referer的报文头,用来指明当前流量的来源参考页
2、利用token(后端生成的一个唯一的登陆态),传给前端保存在前端,每次前端请求时都会携带着Token,后端会先去解析这个Token,看看是不是后台给我们的,已经是否登陆超时,如果校验通过了,才会同意接口请求

4.2.3 CSRF如何发送跨域的Cookie

浅谈CSRF攻击方式
CSRF如何发送跨域的Cookie的?
cookie一般用于保存信息,你向同一个服务器发请求时会带上浏览器保存的对于那个服务器的cookie,而不管你从哪个网站发请求。 所以后端需要设置Access-Control-Allow-Origin,浏览器会看你的访问网站是否是被允许的域,如果允许就发请求并能获得数据, 如果不受允许那么能发请求但是js脚本无法获取返回的数据(你仍然能在NetWork中看到返回)。 CSRF攻击是源于WEB的隐式身份验证机制!WEB的身份验证机制虽然可以保证一个请求是来自于某个用户的浏览器,但却无法保证该请求是用户批准发送的!

5、Vue的使用以及相关的源码、原理

5.1、对象的变化侦测

见7.2

5.2、数组的变化侦测

数组的变化侦测是通过创建拦截器去覆盖数组原型来进行的。只对需要侦测变化的数组使用__proto__来覆盖原型(不污染全局)。和对象的变化侦测相比,除了使用依赖的位置不一样(数组中把依赖保存在Observe实例,Object是在defineReactive中),其他基本类似,也是defineReactive将数组中的每个元素转换成响应式的并侦测变化。【push pop shift unshift sort splice reverse】

5.3、虚拟DOM

5.4、diff算法

juejin.cn/post/684490…

5.5、编译解析

5.6、Vue的生命周期

5.7、vuex的工作原理

本质就是将我们传入的state作为一个隐藏的vue组件的data,也就是说,我们的commit操作,本质上其实是修改这个组件的data值,结合computed的原理,修改被defineReactive代理的对象值后,会将其收集到的依赖的watcher中的dirty设置为true,等到下一次访问该watcher中的值后重新获取最新值。
这样就能解释了为什么vuex中的state的对象属性必须提前定义好,如果该state中途增加一个属性,因为该属性没有被defineReactive,所以其依赖系统没有检测到,自然不能更新。
可以参考:www.jianshu.com/p/d95a7b8af…

5.8、vuex的使用场景(和storage区别)

vuex采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
1.区别:vuex存储在内存,localstorage(本地存储)则以文件的方式存储在本地,永久保存;sessionstorage( 会话存储 ) ,临时保存。localStorage和sessionStorage只能存储字符串类型,对于复杂的对象可以使用ECMAScript提供的JSON对象的stringify和parse来处理。
2.应用场景:vuex用于组件之间的传值,localstorage,sessionstorage则主要用于不同页面之间的传值。
3.永久性:当刷新页面(这里的刷新页面指的是 --> F5刷新,属于清除内存了)时vuex存储的值会丢失,sessionstorage页面关闭后就清除掉了,localstorage不会。

5.9、vue-router的原理

hash模式、history模式
可以参考:
zhangmingemma.github.io/2018/10/16/…
www.jianshu.com/p/4295aec31…

5.10、Vue性能优化方法

路由懒加载
keep-alive缓存页面
使用v-show复用DOM
v-for 遍历避免同时使用 v-if
事件的销毁
图片懒加载
第三方插件按需引入
无状态的组件标记为函数式组件
SSR
参考

6、LeetCode刷题

掌握树、链表、队列等基本数据结构,掌握DSF、BSF、动态规划、回溯等基本算法
可以参考:
juejin.cn/post/684490…
labuladong.gitbook.io/algo/

7、梳理项目中遇到的困难以及解决

7.1、基于Vue开发的项目需要用到可视化图编辑器,目前业界(国内吧)比较火的是阿里的G6,但是官方的G6 Editor已经不再维护,并且其已提出G6 Editor不可进行商用,而GGEditor是阿里基于React的产品,目前没有官方的Vue版本G6编辑器,所以只能先啃一下官方文档(稍微吐槽下语雀上的官方文档不是很好,比如很难搜索、有些属性例子不够充分),然后稍微找了点别人写的研究了下,最后自己写了个。
7.2、开始使用Vue进行开发的时候,遇到一个现在看来很幼稚的问题:我在一个对象上面添加了一个属性,但是这个属性在页面上并不能显示出来,后来查了下才知道Vue的变化侦测原理:对象的响应式原理是将对象通过Object.defineProperty在属性上添加setter/getter来追踪变化,获取数据触发getter,设置数据触发setter,数据发生变化向Dep中的依赖(Watcher)发送通知,Watcher收到通知向外界发送通知,变化通知到外界之后可能触发视图更新、回调函数等。正是这样的原理,setter/getter只能追踪一个数据是否被修改,不能追踪新属性的添加,也不能追踪删除属性。使用Vue.set规避这样的问题。

8、行业最新知识

8.1 Vue3新特性

更快更小更易维护
TypeScript 重写,内置 typing,对ts支持更好
Object.defineProperty -> Proxy(将原本对对象属性的操作变为对整个对象的操作,颗粒度变大)
虚拟DOM重构(将vdom的操作颗粒度变小,每次触发更新不再以组件为单位进行遍历,更新性能由与模版整体大小相关提升为与动态内容的数量相关)
Tree-shaking(原理:全局的API只能通过命名的导出才能使用,比如Vue.nextTick,Vue.set等,这样最终打包的时候未使用的API就会被shaking掉)
参考1
参考2

8.2 大前端(其实也不是什么新鲜玩意了)

参考

8.3 微前端

这方面美团等已经有实践了
产生背景:工程膨胀、开发维护难
实现:按照业务线进行了路由级别的拆分。基座工程:用于管理子工程的路由切换、注册子工程的路由和全局Store层、提供全局库和复用层。子工程:用于开发子业务线业务代码,一个子工程对应一个子业务线,并且包含三端代码和复用层代码。

8.4 serveless

8.5 webassembly

8.6 pwa(Progressive Web Apps(渐进式Web应用程序))

一个 PWA 应用首先是一个网页, 可以通过 Web 技术编写出一个网页应用. 随后添加上 App Manifest 和 Service Worker 来实现 PWA 的安装和离线等功能。
解决了哪些问题:
可以添加至主屏幕,点击主屏幕图标可以实现启动动画以及隐藏地址栏
实现离线缓存功能,即使用户手机没有网络,依然可以使用一些离线功能
实现了消息推送
基准:
可靠(Reliable) 即使在不稳定的网络环境下,也能瞬间加载并展现
快速响应(Fast) 快速响应,并且有平滑的动画响应用户的操作
粘性(Engaging) 像设备上的原生应用,具有沉浸式的用户体验,用户可以添加到桌面
PWA背后不是一种新的技术,而是集合当前多种web技术的一种集合,分别利用各自的功能来完成渐进式的整体需求:
App Manifest
Service Worker(关键)--实现离线缓存
Notifications API
Push API
参考

9、会手写一些函数实现

9.1 节流(throttle)与防抖(debounce)

9.2 深拷贝

参考

function deepClone(source) {
  // 递归终止条件
  if (!source || typeof source !== 'object') {
    return source;
  }
  var targetObj = source.constructor === Array ? [] : {};
  for (var key in source) {
    if (Object.prototype.hasOwnProperty.call(source, key) {
      if (source[key] && typeof source[key] === 'object') {
        targetObj[key] = deepClone(source[key]);
      } else {
        targetObj[key] = source[key];
      }
    }
  }
  return targetObj;
}

var object1 = {arr: [1, 2, 3], obj: {key: 'value' }, func: function(){return 1;}};

// 深拷贝
var newObj= deepClone(object1);
// 改变原对象属性
object1.arr.push(4);

console.log(object1.arr); // [1, 2, 3, 4]
console.log(newObj.arr); // [1, 2, 3]

9.3 applay,call,bind

this、apply、call、bind
介绍、使用场景、手写

9.4 Promise

参考可能是目前最易理解的手写promise

10、待补充

浏览器的深入了解: juejin.cn/post/684490…