总结一下前端面试官会经常问到的一些面试题 :
目录
请说明 px, em, rem, vw, vh, rpx 等单位的特性
JS 中什么是基本数据类型和引用数据类型?各数据类型是如何存储的?
computed 、watch 和 filters 的区别 ?
一阶段 ( HTML5 + CSS3 ) :
隐藏页面中某个元素的办法 ? 区别 ?
( 0 ) 设置 width、height 属性为 0
将元素的
width
,height
,margin
,padding
和border
等影响元素盒模型的属性设置成 0 ,如果元素内有子元素或内容,还应该设置其overflow: hidden
来隐藏其子元素.hiddenBox { width: 0; height: 0; margin: 0; padding: 0; border: 0; overflow: hidden; }
特点:元素不可见,不占据页面空间,无法响应点击事件
( 1 ) 将元素设置为
display: none;
后,元素在页面上将彻底消失元素本身占有的空间就会被其他元素占有,也就是说它会导致浏览器的 重排( 回流 ) 和 重绘
消失后,自身绑定的事件不会触发,也不会有过渡效果
特点:元素不可见,不占据页面空间,无法响应点击事件
( 2 ) 从页面上仅仅是隐藏该元素,DOM 结构均会存在,只是当时在一个不可见的状态
不会触发重排,但是会触发 重绘
特点:元素不可见,占据页面空间,无法响应点击事件
( 3 )
opacity
属性表示元素的 透明度 ,将元素的透明度设置为 0 后,在我们用户眼中,元素也是 隐藏 的不会引发重排,一般情况下也会引发 重绘
特点:改变元素透明度,元素不可见,占据页面空间,可以响应点击事件
( 4 )
特点:元素不可见,不影响页面布局
请说明 px, em, rem, vw, vh, rpx 等单位的特性
什么是 BFC ?
盒子模型总共分为几类 ? 区别是啥 ?
二阶段 ( JavaScript ) :
节流 和 防抖 ? + 手写
节流 :
N 秒内只运行一次,若在 N 秒内 重复触发,只有 一次生效
防抖 :
N 秒后在执行该事件,若在 N 秒内被 重复触发,则 重新计时
// ------------------------ 节流 , 时间戳版 function throttle(fn, wait) { let previous = 0 return function () { let now = Date.now() let _this = this let args = arguments if (now - previous > wait) { fn.apply(_this, arguments) previous = now } } } // ---------------------- 节流 , 定时器版 function throttle2(fn, wait) { let timer return function () { let _this = this let args = arguments if (!timer) { timer = setTimeout(() => { timer = null fn.apply(_this, arguments) }, wait); } } }
// -------------------------------- 防抖函数 function debounce(func, delay) { let timeout return function () { let arg = arguments if (timeout) clearTimeout(timeout) timeout = setTimeout(() => { func(arg) }, delay); } } // ------------------------------- 立即执行防抖函数 function debounce2(fn, delay) { let timer return function () { let args = arguments if (timer) clearTimeout(timer) let callNow = !timer timer = setTimeout(() => { timer = null }, delay); if (callNow) { fn(args) } } } // -------------------------------- 立即执行防抖函数 + 普通防抖 function debounce3(fn, delay, immediate) { let timer return function () { let args = arguments let _this = this if (timer) clearTimeout(timer) if (immediate) { let callNow = !timer timer = setTimeout(() => { timer = null }, delay); if (callNow) { fn.apply(_this, args) } } else { timeout = setTimeout(() => { func.apply(_this, arguments) }, delay); } } }
从浏览器输入 url 后都经历了什么 ?
=> 先进行 DNS 域名解析 ,先查看 本地 hosts 文件 ,
查看有没有当前 域名 对应的 ip 地址 , 若 有 直接 发起 请求 ,
没有的话会在 本地域名服务器 去查找,该查找属于 递归查找 ,
如果 本地域名服务器 没查找到,会从 根域名服务器 查找,该过程属于 迭代查找 ,
根域名 会告诉你从哪个与服务器查找,最后查找到对应的 ip 地址后 ,
把对应 规则 保存到 本地的 hosts 文件 中 。=> 如果想 加速 以上及之后的 http 请求过程的话可以使用 缓存服务器 CDN ,
CDN 过程如下 :
用户输入 url 地址后,本地 DNS 会解析 url 地址,
不过会把最终解析权交给 CNAME 指向的 CDN 的 DNS 服务器 。
CDN 的 DNS 服务器 会返回给 浏览器 一个 全局负载均衡 IP 。
用户会根据 全局负载均衡 IP 去请求 全局负载均衡 服务器 。
全局负载均衡 服务器 会根据用户的 IP 地址,url 地址,
会告诉用户一个 区域负载均衡 设备,让用户去请求它 。
区域负载均衡 服务器 会为用户选择一个离用户较近的最优的 缓存服务器 ,并把 IP 地址给到用户 。
用户想缓存服务器发送请求,如果请求不到想要的资源的话,会一层层向上一级查找,直到查找到为止 。=> 进行 http 请求,三次握手 四次挥手 建立 断开 连接
=> 服务器处理,可能返回 304 也可能返回 200
返回 304 说明 客户端缓存 可用,直接使用 客户端缓存 即可,该过程属于 协商缓存
返回 200 的话会同时返回对应的 数据=> 客户端自上而下执行代码
其中遇到 CSS 加载的时候,CSS 不会阻塞 DOM 树的解析,但是会阻塞 DOM 树的渲染,并且 CSS 会阻塞下面的 JS 的执行
然后是 JS 加载,JS 加载会影响 DOM 的解析,之所以会影响,是因为 JS 可能会删除添加节点,如果先解析后加载的话,DOM 树还得重新解析,性能比较差。 如果不想阻塞 DOM 树的解析的话,可以给 script 添加一个 defer 或者 async 的标签。
defer:不会阻塞 DOM 解析,等 DOM 解析完 之后在运行,在 DOMContentloaed 之前
async: 不会阻塞 DOM 解析,等该 资源下载完成 之后 立刻运行
进行 DOM 渲染 和 Render 树渲染
获取 html 并解析为 Dom 树
解析 css 并形成一个 cssom( css树 )
将 cssom 和 dom 合并成渲染树( render树 )
进行布局( layout )
进行绘制( painting )
回流重绘
=> 回流必将引起重绘,重绘不一定引起回流
JS 中什么是基本数据类型和引用数据类型?各数据类型是如何存储的?
箭头函数与普通函数的区别 ?
1. 箭头函数 没有 prototype ( 原型 ) ,所以箭头函数本身 没有 this 指向
2. 箭头函数 的 this 在定义的时候继承自外层第一个普通函数的 this 指向
3. 如果箭头函数外层没有普通函数,严格模式和非严格模式下 ,
它的 this 都会指向 window ( 全局对象 )
4. 箭头函数 本身的 this 指向不能改变,但可以修改它要继承的对象的 this
5. 箭头函数的 this 指向全局,使用 arguments 会报未声明的错误
6. 箭头函数的 this 指向普通函数时 , 它的 argumens 继承于该普通函数
7. 使用 new 调用箭头函数会报错,因为 箭头函数没有 constructor
8. 箭头函数 不支持 new.target
9. 箭头函数 不支持重命名函数参数 , 普通函数的函数参数支持重命名
10. 箭头函数 相对于普通函数语法更 简洁优雅
Get 和 Post 的区别 ?
=> 冪等 / 不冪等( 可缓存 / 不可缓存 )
get 请求是冪等的,所以 get 请求的数据是可以缓存的
而 post 请求是不冪等的,查询对数据是有副作用的,是不可缓存的
=> 传参
get 传参,参数是在 url 中的
准确的说 get 传参也可以放到 body 中,只不过不推荐使用
post 传参,参数是在请求体中
准确的说 post 传参也可以放到 url 中,只不过不推荐使用
=> 参数长度
get 参数长度有限,是较小的
准确来说,get 在 url 传参的时候是很小的
post 传参长度不受限制
=> 发送数据
post 传参发送两个请求包,一个是 请求头 ,一个是 请求体 ,请求头 发送后 服务器 进行验证,要是验证通过的话就会给客户端发送一个 100-continue 的 状态码,然后就会发送请求体
=> 字符编码
get 在 url 上传输的时候只允许 ASCII 编码=> 安全性
get 较 不安全
post 较为 安全
准确的说两者都不安全,都是明文传输的,在路过公网的时候都会被访问到,不管是 url 还是 header 还是 body ,都会被访问到,要想做到安全,就需要使用 https
闭包
简述下 Promise 对象
Promise 是异步编程的一种解决方案,比传统的解决方案(回调函数和事件)更合理更强大。 所谓 Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件 (通常是一个异步操作)的结果。 从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。 Promise 对象有以下2个特点: 1.对象的状态不受外界影响。Promise 对象代表一个异步操作,有三种状态: Pending (进行中)、Resolved (已完成) 和 Rejected (已失败)。 只有异步操作的 结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。 这也是 Promise 这个名字的由来,它的英语意思就是 “承诺” ,表示其他手段无法改变。 2.一旦状态改变,就不会再变,任何时候都可以得到这个结果。 Promise 对象的状态改变,只有两种可能: 从 Pending 变为 Resolved ;从 Pending 变为 Rejected。 只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果。 就算改变已经发生了,你再对 Promise 对象添加回调函数,也会立即得到这个结果。 这与事件( Event )完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。 有了 Promise 对象,就可以把异步操作以同步操作的流程表达出来,避免了层层嵌套的 回调函数。 此外,Promise 对象提供了统一的接口,使得控制异步操作更加容易。
原型和原型链
三阶段 ( Vue ) :
Vue 中的 nextTick
高频面试题 ! !
computed 、watch 和 filters 的区别 ?
计算属性 computed 和 过滤器 filters 有什么区别 ?
filters 与 computed
相同点:都必须有 返回值 , 且都可以 绑定数据
不同点:filters 可以 传参,但是不可以访问 this ,可以多个过滤。
只有 过滤器 传参改变就会触发。不存在缓存
computed 不可以 传参,可以访问 this ,针对的是一个变量的操作。
当其中的数据改变就会触发。存在缓存
filters 一般用于 数据格式化
computed 一般是需要针对多个数据进行操作watch 有参数,分别是 新值 ( newVal ) 和 旧值 ( oldVal ) 。不需要返回值,可以访问 this ,
也是监听一个数据,当数据改变就会触发。
watch 一般用于 监听改变 。computed 和 filters 注重结果 。
改变数据(页面上使用的数据)会触发过滤器,改变对应的数据才会触发 计算 / 观察
$route 和 $router 的区别
$route 用来获取 路由信息 的 ,它是 路由信息 的一个 对象 ,里面包含路由的一些 基本信息,包括 name 、meta 、path 、hash 、query 、params 、fullPath 、matched 、redirectedFrom 等 。
$router 主要是用来 操作路由 的,它是 VueRouter 的 实例 ,包含了一些路由的 跳转 方法 ,钩子函数 等
v-if 和 v-show 的区别
1、手段:v-if 是动态的向 DOM 树 添加 或者 删除 DOM元素 ;v-show 是通过设置 DOM 元素的 display 样式属性 控制 显示 和 隐藏 。
2、编译过程:v-if 切换有一个 局部编译 / 卸载 的过程, 切换过程中合适地 销毁 和 重建 内部的事件监听和子组件;v-show 只是简单的基于 css 切换。
3、编译条件:v-if 是惰性的,如果初始条件为假,则什么也不做;只有在条件第一次变为真时才开始 局部编译( 编译被缓存?编译被缓存后,然后再切换的时候进行局部卸载 ); v-show 是在任何条件下(首次条件是否为真)都被编译,然后被缓存,而且 DOM 元素保留
4、性能消耗:v-if 有更高的 切换消耗 ;v-show 有更高的 初始渲染消耗 使用场景:v-if 适合运营条件不太可能改变;v-show 适合 频繁切换
5、相同点: v-show 都可以动态控制着 DOM 元素的 显示 隐藏 不同点: v-if 的显示隐藏是将 DOM 元素 整个添加或删除,v-show 的显示隐藏是为 DOM 元素添加 css 的样式 display,设置 none 或者是 block ,DOM 元素还是存在的
6、在渲染多个元素的时候,可以把一个 元素作为包装元素,并使用 v-if 进行条件判断,最终的渲染不会包含这个元素,v-show 是不支持 语法
Vue2.0 与 Vue3.0 的 区别 ?
一、Vue 3.0 有 六大亮点
- 性能比 vue2.x 快 1.2~2 倍
- 支持 tree-shaking,按需编译,体积比 vue2.x 更小
- 支持组合 API
- 更好的支持 TS
- 更先进的 组件
二、性能比 vue2.x 快 1.2~2倍 如何实现的呢
1.diff 算法更快
vue2.0 是需要全局去比较每个节点的,若发现有节点发生变化后,就去更新该节点
vue3.0 是在创建虚拟 dom 中,会根据 DOM 的的内容会不会发生内容变化,添加静态标记, 谁有 flag!比较谁 。
2、静态提升
vue2 中无论元素是否参与更新,每次都会重新创建,然后再渲染 , vue3 中对于不参与更新的元素,会做静态提升,只被创建一次,在渲染时直接复用即可
3、事件侦听缓存
默认情况下,onclick 为动态绑定,所以每次都会追踪它的变化,但是因为是同一函数,没有必要追踪变化,直接缓存复用即可
在之前会添加静态标记8 会把点击事件当做动态属性 会进行 diff 算法比较, 但是在事件监听缓存之后就没有静态标记了,就会进行 缓存复用
三、为什么 vue3.0 体积比 vue2.x 小
在 vue3.0 中创建 vue 项目 除了 vue-cli ,webpack 外还有 一种创建方法是 Vite , Vite是作者开发的一款有意取代 webpack 的工具,其实现原理是利用 ES6 的 import 会发送请求去加载文件的特性,拦截这些请求,做一些预编译,省去 webpack 冗长的打包时间
四、vue3.0 组合 API
3.说一说 vue3.0 的组合 API 跟之前 vue2.0 在完成业务逻辑上的区别:
在 vue2.0 中: 主要是往 data 和 method 里面添加内容,一个业务逻辑需要什么 data 和method 就往里面添加,而组合 API 就是 有一个自己的方法,里面有自己专注的 data 和method 。
4.再说一下组合 API 的本质是什么: 首先 composition API( 组合 API ) 和 Option API( vue2.0 中的 data 和 method )可以共用 composition API( 组合 API )本质就是把内容添加到 Option API 中进行使用
五、ref 和 reactive 的简单理解
1. ref 和 reactive 都是 vue3 的监听数据的方法,本质是 proxy
2.ref 基本类型复杂类型都可以监听 ( 我们一般用 ref 监听基本类型 ),reactive 只能监听对象( arr,json )
3. ref 底层还是 reactive
六、对生命周期的监听( ref 获取属性 )
七、proxy 响应式本质
博主最近在北京 , 很快也要面试找工作啦 ,
所以此条博文会时不时进行更新的 ,
欢迎大家收藏 + 关注哟 ~
感谢大家的支持 ! ! !