前端基础面试题

290 阅读14分钟

说一说cookie sessionStorage localStorage 区别

  • 研究方向:存储位置、存储大小、生命周期、写入方式、数据共享、发送请求是否携带、应用场景
  • 详细
    • 存储位置:都属于浏览器存储,存储在本地
    • 存储大小:cookie 4kb 其他 5M
    • 生命周期:cookie 服务端写入时候就设置好的。session~ 关闭当前页面自动清空。local~ 除非手动清除,否则一直存在。
    • 写入方式:cookie 服务端写入 其他 前端写入
    • 数据共享:都遵循同源原则,session~还限制必须是同一页面
    • 请求携带:cookie 请求会自动携带 其他 不携带
    • 应用场景:cookie 一般用于存储登录验证信息,session~ 可以用来检测用户是否刷新进入页面,如恢复播放进度条,local~ 常用于存储不易变动的数据,减轻服务器的压力

闭包

  • 闭包形成的原理:作用域链,当前作用域可以访问上级作用域中的变量
  • 闭包解决的问题:能够让函数作用域中的变量在函数执行结束之后不被销毁,同时在函数外部能够访问函数内部的变量
  • 闭包带来的问题:由于垃圾回收器不会将闭包中的变量销毁,于是就造成了内存泄漏,内存泄漏累计多了,就容易导致内存溢出
  • 闭包的应用:能够模仿块级作用域,能够实现柯里化,Vue中数据响应式Observer中使用闭包等
  • 闭包存在的意义:延长变量的生命周期 创建私有环境

promise

  • promise的作用:promise是异步微任务,解决了异步多嵌套回调的问题,让代码的可读性更高,更容易维护
  • promise的使用:promise是ES6提供的一个构造函数,可以使用promise构造器new 一个实例,接收一个函数作为参数,这个函数有两个参数,分别是两个函数 resolve和 reject
  • promise的特点:对象的状态不受外界影响 一共有3个状态:pending fulfilled rejected,状态的变化只有两种情况:pending ->fulfilled pending ->rejected,一旦状态改变就不会再变,任何时候都可以的到这个结果
  • .then .catch .all .any .race 等

跨域

  • 跨域:当页面中的某个接口请求的地址和当前页面的协议、域名、端口其中有一项不同,就说该接口跨域了
  • 跨域限制的原因:浏览器为了保证网页的安全,提出的同源协议策略
  • 跨域解决方案:
    • cors:目前做常用的一种解决方案,通过设置后端允许跨域实现,'Access -Control -Allow -Origin':'*'
    • node中间件、nginx反向代理:跨域限制的时候浏览器不能跨域访问服务器,node中间件和nginx反向代理,都是让请求发送给代理服务器,然后代理服务器再向后端服务器发送请求,服务器之间不存在同源策略
    • JSONP:利用script 标签可以跨域访问资源,将回调函数作为参数拼接在url中。后端收到请求,调用该回调函数,并将数据作为参数返回回去
    • postmessage:H5新增API,通过发送和接收API实现跨域通信

BFC

  • 块级格式化上下文、
  • 独立的渲染区域、
  • 不会影响边界以外的元素、
  • 形成BFC的条件:float、position、overflow、display等
  • 属于同一个BFC的两个相邻的box的margin会发生重叠

Vuex

  • 组成:state、actions、mutations、getters、module、
  • state:用于存储公共管理的数据
  • actions:action提交的是mutation,而不是直接更改状态,action可以包含任意异步操作 通过store.dispatch触发
  • mutations:定义改变state数据的方法,不要在里面执行异步操作,会导致数据无法跟踪 通过store.commit调用
  • getters:可以认为是sotre的计算属性,getter的返回值会根据他的依赖被缓存起来,且只有当他的依赖发生了改变才会被重1. 新计算 通过store.getters调用
  • module:将store分割成模块
  • 其他:mapState、mapMutations、mapAction、mapGetters等

vue2.0 双向绑定的原理

  • 通过数据劫持 结合发布者 -订阅者模式的方法来实现数据的响应式
  • 通过Object.definePrototype 来劫持数据的getter、setter,当数据发生变化时发送消息给订阅者,订阅者收到消息进项响应的处理。

map 和 forEach 区别

  • map有返回值,可以开辟新空间,return出来一个length河源数组一致的数组。 forEach默认无返回值
  • map的处理速度比forEach块,而且返回一个新的数组,方便链式调用其他的数组方法

事件循环 Event loop,宏任务/微任务

  • 事件轮询:解决javascript单线程对于一步操作的一些缺陷,让javascript做到既是单线程,又不会阻塞的核心机制,用来协调各种事件、用户交互、脚本渲染、UI渲染、网络请求等一种机制。
  • 执行js代码的时候,遇见同步任务,直接推入调用栈中执行,遇到异步任务,将该任务挂起,等到异步任务有返回之后推入到任务队列中,当调用栈的所有同步任务全部执行完成,将任务队列中的任务按顺序一个一个的推入并执行,重复这一系列的操作行为。
  • 异步任务又分为宏任务和微任务:
    • 宏任务:任务队列中的任务成为宏任务,每个宏任务都包含一个微任务队列。
    • 微任务:等宏任务中的主要功能都完成后,渲染引擎不着急去执行下一个宏任务,而是执行当前宏任务的微任务。
  • 当执行站中的同步任务执行完后,就会去任务队列中拿一个宏任务放到执行栈中执行,执行完该任务中的所有微任务,再到任务队列中拿宏任务,即一个宏任务、所有微任务、渲染 如此循环。

keep-alive

  • 缓存组件,提升性能,避免重复加载一些不需要经常变动且内容较多的组件
  • include exclude max
  • activated进入时触发 deactivated退出时触发

defer async

  • 遇到script 会暂停文档解析,直接加载并执行脚本
  • 加上async 属性会并行加载脚本,加载完成后立即 暂停文档解析 并执行
  • 加上defer 属性会并行加载脚本,加载完成后,会等到文档全部解析完成,再去执行脚本
  • js引擎和GUI渲染线程互斥

computed 和 watch区别

  • computed的值有缓存、触发条件是依赖值发生更改
  • watch无缓存支持异步、监听数据变化
  • 标准回答:
    • computed:是计算属性,依赖其他属性值,并且computed的值有缓存,只有它依赖的属性值发生变化,下一次获取时才会重新计算
    • watch:更多的是观察的作用,支持异步,类似于某些数据的监听回调,每当监听的数据发生变化时都会执行回调进行后续操作,通常用于开销较大的操作

new 发生了什么

  • 宏观的来说,new创建了一个新的实例化对象
  • 内部实现:
    • 创建一个新的对象
    • 为这个对象的原型指向构造函数的prototype
    • 将这个对象作为函数的this上下文,并执行
    • 如果执行结果没有返回对象,则返回这个this
  • new关键字后面的构造函数不能是箭头函数

输入url发生了什么

DNS解析、TCP握手、HTTP缓存、重定向、服务器状态码、渲染引擎和js引擎互斥、渲染过程、浏览器进程、网络进程、渲染进程等

伪数组

  • 伪数组的类型不是Array,而是Object,可以使用length属性查看长度,也可以使用[index]获取某个元素,但是不能使用数组的其他方法,也不能改变长度,可以使用for in遍历
  • 转换为真数组:Array.prototype.slice.call(),Array.from(),[].slice.call()

前后端实时通讯

  • 轮询、长轮询、iframe流、WebSocket、SSE

服务端渲染

  • 客户端渲染的问题:
    • 由于页面显示需要拉取js文件,首屏加载比较慢
    • 由于搜索引擎爬虫只认识html结构的内容,而不能识别JS代码内容,所以对SEO不友好

diff算法

  • 虚拟dom是真实dom的一种抽象,利用js对象反映真实的dom
  • 新老虚拟dom之间精细化比较
  • 父节点不是同一节点 暴力删除旧的,插入新的 同一节点:选择器相同key相同
  • 只会同层比较,不会跨层比较 如果跨层暴力删除旧的,插入新的

webpack

  • webpack本身只处理 js文件
  • 5大核心概念:entry(入口),output(出口),loader(加载器),plugin(插件),mode(模式)
loader
  • 处理css scss less
  • 处理图片 将小于一定大小的图片转换为base64 (base64 是字符串 优点:减少请求 缺点:体积变大 小图影响不大,大图得不偿失)
  • 处理其他资源 字体图标 map3 map4等
提升打包构建速度
  • source -map:便于调试
  • HMR:热模块替换
  • oneOf:每个文件只能被一个loader配置处理 提高性能
  • include/exclude:筛选执行配置的文件
  • Cache(缓存):开启bable和enlint,首次打包速度不受影响,提升之后的打包速度
  • Thead:多进程打包,开启电脑的多个进程同时干一件事,速度更快
减少代码体积
  • Tree Shaking:减少代码体积,只打包用到的代码
  • 模块引入 而非 注入
  • 图片压缩:有损/无损
优化运行速度
  • 代码分割(code split)
  • 按需加载,动态导入
  • preload/prefetch:preload:浏览器立即加载,prefetch:浏览器空闲加载
  • runtimeChunk:保存各模块之间的依赖关系,如A模块发生更改,不会更改B模块包,而是改变存放其依赖关系的文件
  • Core -js:专门处理js 兼容性问题
  • PWA:离线体验
  • Bable 处理兼容性问题
  • Eslint 处理代码规范
  • 提取各类文件
  • css link引入
  • html js 生产模式默认压缩

排序

  • 冒泡排序
  • 快速排序
  • 插入排序
  • 等10种

垃圾回收机制

  • 垃圾回收策略
  • 标记清除算法
    • 缺点:内存碎片化、分配速度慢
    • 解决方法:标记整理算法
  • 引用计数算法
    • 缺点:循环引用导致无法回收

xss csrf

  • xss 预防:
    • httpOnly:在cookie中设置HttpOnly 属性后,js脚本将无法读取到cookie信息
    • 输入过滤:输入格式检查
    • 转义HTML
    • 白名单
  • csrf 预防:
    • 验证码 强交互 用户体验不好
    • referer:请求来源限制
    • token:token验证是公认最合适的方案

js继承

  • 原型链继承
  • 借用构造函数继承
  • 组合继承
  • 原型式继承
  • 寄生式继承
  • 寄生组合式继承

nextTick

  • 作用:在下次DOM更新结束之后,执行延迟回调,拿到更新后的DOM相关信息
  • 异步更新策略:避免重复计算和不必要的DOM操作,在下一个事件循环的时候刷新队列,并执行已去重的任务,更新视图
  • 实现:
    • 环境判断:主要是判断用哪个宏任务或微任务,因为宏任务消耗的时间是大于微任务的,所以优先使用微任务
    • promise -> MutationObserver -> setImmediate -> setTimeout

OSI 7层网络模型 TCP/IP 5层模型

osi
  • 起源:为解决各家公司之间设备互通问题/阻碍互联网发展问题,提出的标准,并非实现
  • 应用层:各种应用软件
  • 表示层:数据格式标识,基本压缩加密功能
  • 会话层:控制应用程序之间的会话能力
  • 传输层:端到端传输数据的基本功能,TCP、UDP
  • 网络层:定义IP编址,定义路由功能,不同设备的数据转发
  • 数据链路层:定义数据的基本格式,如何传输,如何标识,如MAC地址
  • 物理层:底层数据传输,如网线,网卡标准
  • 越靠上 越接近软件
  • 越靠下 越接近硬件
tcp/ip
  • 应用层
  • 传输层
  • 网络层
  • 数据链路层
  • 物理层

http 缓存机制

  • 强缓存
    • Expirse http1.0:表示过期时间 缺点:存在修改本地时间或与服务器时间不一致 导致的 判断失误
    • cache -control http1.1:相对时间 弥补了Expirse缺陷
  • 协商缓存
    • last -modified:表示文件最后修改时间 缺点:时间为秒级 或存在判断失误
    • Etag:文件唯一标识,修改过就会发生变化 弥补了last -modified缺陷

https 加密方式

  • 对称加密
  • 非对称加密

浏览器单线程/多线程 js单线程/多线程 为什么

  • 浏览器:GUI渲染线程、JS引擎线程、定时器触发线程、浏览器事件线程、网络线程、EventLoop轮询处理线程等
  • js 单线程

typeof null 结果, 为什么

  • 结果 object
  • 因为在js中,不同的对象都是用二进制存储的,如果二进制前三位都是0,系统会自动判断为object类型,而null的二进制全是0,所以输出object

http

  • 1.0:每次请求都需要重新建立tcp连接,请求完后立即断开与服务器连接,这很大程度造成了性能上的缺陷,http1.0 被抱怨最多的就是连接无法复用
  • 1.1:引入了长链接keep -alive,相较与1.0减少了连接和关闭的延迟,提高了效率,但是若干个请求还是需要串联排队处理,一旦某个请求超时,后面的就会被阻塞,也就是常说的队头阻塞
  • 2.x:
    • 新的二进制格式传输,即0和1的组合,而非文本传输
    • 多路复用:一个连接可有有多个请求,且混杂在一起根据requestid来区分不同的请求,提高了连接利用率,降低了延迟
    • header头部压缩,通讯双方各自缓存了一份header请求表头,避免了重复的header传输,且缩小了包的体积
    • 服务端推送,可以服务端主动向客户端push消息

DNS的优化与应用

  • DNS缓存/DNS负载均衡
  • CDN加速

如何减少重排和重绘

  • 最小化重绘和重排:样式集中改变,使用添加新类名方式
  • 批量操作DOM:利用document.createDocumentFragment()来添加节点,处理完之后再插入到实际DOM中去
  • 使用absolute或fixed使元素脱离文档流

如何终止ajax请求

  • 原生XHR
    •  var xhr = new XMLHttpRequest();
       xhr.abort();
      
  • jquery
    •  var jp = $.ajax({
           type:"get",
           url:"https://api.github.com/",
           dataType:"json",
           success:function(data){
               console.log(data);
           },
           error:function(err){
               console.log(err);
           }
       })
       jp.abort();
      
  • axios
    •  var CancelToken = axios.CancelToken;
       var source = CancelToken.source();
       source.cancel('Operation canceled by the user.');
      

javascript设计模式

  • 工厂模式
  • 单体模式
  • 模块模式
  • 代理模式
  • 职责链模式
  • 命令模式
  • 模板方法模式
  • 策略模式
  • 发布 -订阅模式
  • 中介者模式

设计模式

  • 创建型设计模式 5
    • 单例模式
      • 保证一个类只有一个实例,并提供一个全局访问点
      • 实际场景:弹框、模态框
    • 工厂模式
  • 结构型设计模式 7
    • 装饰者模式
    • 代理模式
  • 行为型设计模式 11
    • 发布订阅模式
  • 设计模式可以让你用前人总结的经典场景来分析实现某些功能时需要什么角色如何合理地设置接口、提高系统各个层次的独立性、降低耦合度等。然而,这也不是绝对的。不论是设计模式、还是开发框架,都是为了有效开发而出现的,但常常出现“杀鸡用牛刀”的情况,所以学的时候最好要多对比,从不同角度理解与测试,不能照搬书中的内容,这不是设计模式的精髓。

Loader和Plugin的区别

  • loader:用一句话描述,让webpack拥有加载和解析非javascript的能力
  • Plugin:扩展webpack的功能,让webpack具有更多灵活性

瀑布流

  • multi -column
  • grid布局
  • flex布局

position

  • static
  • relative
  • absolute
  • fixed
  • sticky

懒加载

  • 可视窗口大小:body.clientHeight
  • 滚动条高度:body.scrollTop
  • 元素高度:offsetHeight

commonjs es6模块

  • commonjs模块输出的是一个值的拷贝,ES6模块输出的是值的引用
  • commonjs模块是运行时加载,ES6模块是编译时输出接口
  • commonjs是单个值导出,ES6可以导出多个

TCP/UDP

  • TCP面向连接,UDP面向无连接
  • TCP可靠,UDP不可靠 可靠:传输无差错、不丢失、不重复、按序到达
  • TCP面向字节流,UDP面向报文
  • TCP 1对1,UDP 1对1、1对多
  • TCP首部开销较大20字节,UDP 8字节

常见的BOM属性对象方法

  • location
  • history
  • Navigator

TypeScript与javascript优劣势

  • ts优势
    • 静态输入:在开发人员编写脚本时检测错误
    • 更好的团队协作
    • 更强的生产力
  • js优势
    • 人气:社区资源
    • 学习曲线
    • 灵活性

hash模式和history模式如何跳转

  • hash:通过监听浏览器的onhashchange()事件变化,查找对应的路由规则
  • history:利用H5的history中新增的两个api pushState、replcaeState 和onpopstate监听Url 变化

axios和ajax

  • axios 是基于promise的HTTP库,可以用在浏览器和node.js中
  • ajax 是对原生XHR的封装,为了达到跨域的目的,增添了对JSONP的支持

flex布局

  • 主轴 交叉轴
  • flex-direction:定义主轴方向
  • flex-wrap:是否换行
  • justify-content:主轴排列
  • align-items:交叉轴排列
  • align-content:多根交叉轴排列

三次握手 四次挥手

  • TCP 是面向连接的协议,也就是说,在收发数据前,必须和对方建立可靠的连接
  • 三次握手其实就是建立TCP连接时,客户端可服务器端总共发送3个包,进行三次握手的主要作用就是为 了确保双方的接收和发送能力是否正常
  • 报文
    • SYN:位置1表示 建立连接
    • ACK:位置1表示 确认连接
    • FIN:位置1表示 释放连接
    • seq:报文序列号
  • 三次握手
    • 第一次:由客户端向服务器发送报文,这个报文的SYN位置一,代表请求建立连接,并包含seq报文序列号,

    • 第二次:服务器收到报文后会知道客户端请求建立连接,于是向客户端发送确认消息报,SYN置1表示建立连接,ACK置一,并且ack设置为第一次握手中的seq+1。 在服务器发送报文后,服务器方不知道自己的报文是否发送成功,因此此时需要第三次。

    • 第三次:客户端发送报文,并且ACK位置1,表示客户端已经收到服务器端的确认报文了。 在三次握手结束后,双方都知道了可以发送和接受到对方的消息,此时连接成功建立,接下来双方就可以进行数据的发送了。

  • 为什么需要三次握手,两次不行吗
    • 三次握手的目的,是为了让客户端和服务器双方都能确认自己和对方的发送接收能力正常
  • SYN攻击
    • 一种典型的DoS/DDoS攻击
  • 半关闭特性
    • TCP提供了连接的一端在结束它的发送后还能接收来自另一端数据的能力

HTTP2.0 为什么首部压缩

  • 1.x的header很多时候都是重复多余的,导致宽带浪费

进程和线程的区别

  • 进程是资源分配的最小单位,线程是资源调度的最小单位
  • 进程有自己独立的地址空间,线程是共享进程中的数据
  • CPU切换一个线程比进程开销小
  • 线程之间通讯更方便
  • 多进程程序更安全,生命力更强
  • 进程对资源保护要求高,开销大,效率相对较低,线程资源保护要求不高,但开销小,效率高,可频繁切换

setTimeout实际延迟时间

  • 延迟时间被限制为最小4 ms,要在现代浏览器中实现0毫秒延迟的定时器,可以借助 window.postMessage()

tcp,udp区别

  • 是否连接、是否可靠、连接对象个数、传输方式、首部开销、适用场景
  • 是否连接:tcp是面向连接,udp是无连接的
  • 是否可靠:tcp是可靠连接,udp是不可靠的
  • 连接对象个数:tcp一对一,udp一对一、一对多、多对一、多对多
  • 传输方式:tcp是面向字节流传输,udp是面向报文传输
  • 首部开销:tcp首部最小20字节最大60字节,udp首部开销8字节
  • 适用场景:tcp文件传输等可靠传输应用,udp ip电话、视频会议、直播等

xss,csrf防范手段

  • xss:
    • 编码:对用户输入进行HTML Entity编码
    • 过滤:过滤事件、自动触发等属性,溢出style属性、script节点、iframe节点等
    • 白名单
  • csrf:
    • 验证http referer字段:referer字段记录了请求的来源地址
    • 验证码:关键页面操作加上验证码 - 对用户不友好
    • token验证:原理是用攻击者无法获取的验证信息

Promise.all手写

v-model 语法糖 具体绑定那些属性

  • 默认绑定子组件value属性
  • :value="value" @input="$emit('input',value)"
    

前端高并发

  • 出发点:减少请求,过滤请求,答案等同于提升性能

  • css speites(雪碧图)

  • 压缩图片 base64

  • js css 压缩

  • 防抖、节流

  • 适当运用缓存

  • 限定某些高频操作

  • 离线体验

  • 需根据场景进行差异化分析

    • 合并:代码合并到一定程度,其弊端就会逐步放大,如首屏加载
    • 压缩:需考虑代码可读性,如线上问题排查,还有压缩产物的兼容性
    • 缓存:缓存时间越长,数据的准确性就越差

es6 新特性

  • let const
  • 箭头函数
  • Set Map
  • 解构...
  • 对象key value 同名可省略
  • Promise
  • 字符串模板
  • 模块化
  • 函数参数默认值

vue父子组件加载顺序,为什么

  • 父beforecreate->父created->子beforecreate->子created->子mounted->父mounted

  • 父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->父mounted

  • 父beforeUpdate->子beforeUpdate->子updated->父updated

  • 父beforeDestroy->子beforeDestroy->子destroyed->父destroyed

  • 理解:

    • 当父组件执行完beforeMount挂载开始后,会依次执行子组件中的钩子,直到全部子组件mounted挂载到实例上,父组件才会进入mounted钩子
    • 父组件先于子组件created,而子组件先于父组件mounted