前端面试必备技巧(二)重难点梳理

本文是前端面试必备的第二部分,深入探讨了ES6的常见用法,包括let和const、模板字符串、解构赋值等。接着,详细介绍了移动端H5的适配方案,如rem布局和flex布局。此外,文章详尽阐述了Vue框架的面试重点,如双向绑定原理、虚拟DOM、路由缓存和Vue与React的区别。同时,涵盖了模块化开发、请求封装与缓存策略、页面性能优化和浏览器缓存机制。最后,文章提到了HTTP与HTTPS的区别,以及HTTP2.0的优化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

针对面试中出镜率比较高的重难点知识梳理。

相比于第一篇 前端面试必备技巧,本篇文章更贴合今年的面试实际。第一篇比较全面,也比较基础,建议先看一遍上一篇再看本篇会更容易理解。

一、ES6常见用法

关于 ES6(泛指 ECMAScript 2015 及以后的版本)几乎是面试必问的,一般的问法是:“平常会使用 ES6 吗?列举几个 ES6 的用法”。

回答出来三四个就差不多了,但回答的每一个都要弄清楚,有的面试官会延伸着追问。

如果时间充足,还是建议看看 阮一峰的 ES6 入门教程

1.1 let 和 const

  • let 在块级作用域内有效,不会污染全局变量
  • const 一经声明不能改变。注意保证的是它指向的内存地址不能改变,如果是对象或者数组里面的属性或元素可以改变的。
  • 存在暂时性死区,不能变量提升。
  • 只能先声明再使用,且不能重复声明

1.2 字符模板

用作字符串拼接:你好,${name}

1.3 变量的解构赋值

  • let [a,b,c] = [1,2,3]
  • 交换变量的值:[a,b] = [b,a]
  • 提取 JSON 数据,获取服务器返回数据时有用:let {data, code} = res
  • 输入模块的指定方法:
const { SourceMapConsumer, SourceNode } = require("source-map");
  • 从函数返回多个值: 返回个数组或对象

1.4 扩展运算符

扩展运算符(spread)是三个点(...)。

  • 复制数组:let arr2 = […arr1]
  • 合并数组:[…arr1, …arr2, …arr3]

1.5 Promise

  • 成功调用 resolve,失败调用 reject
  • .then 获取结果,.catch 捕获异常。捕获异常还可通过 .then 的第二个参数
  • .finally 无论成功失败都一定会调用
  • 多个并发的请求,用 Promise.all()
    • 只有p1p2p3的状态都变成fulfilledp的状态才会变成fulfilled,此时p1p2p3的返回值组成一个数组,传递给p的回调函数。
    • 只要p1p2p3之中有一个被rejectedp的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。
let p = Promise.all([p1,p2,p3])
p.then(([res1, res2,res3]) => {};

Promise 示例:

new Promise(){
	if (/* 异步操作成功 */){
    resolve(value);
  } else {
    reject(error);
  }
}.then().catch().finally()

1.6 async await

async 函数是什么?一句话,它就是 Generator 函数的语法糖。
async 函数对 Generator 函数的改进:

  • 内置执行器,直接调用即可。Generator 还需要调用 next()才能执行
  • 更好的语义。asyncawait*yield 更好理解
  • 返回值是 Promise

1.7 箭头函数

箭头函数 () => {}this 是在定义函数时绑定的,不是在执行过程中绑定的。简单的说,函数在定义时,this 就继承了定义函数的对象。this 一旦确定以后不会改变。

普通函数的 this 指向的是调用它的对象。

二、移动端的 H5 兼容性和适配

常用的适配方案是 rem + flex 布局。

2.1 rem 适配

先在应用的入口设置基准字体大小,越早执行越好。如果设计图尺寸宽度是 750,就除以 7.5。具体的值根据实际情况来算。

document.documentElement.style.fontSize = document.documentElement.clientWidth / 7.5 + 'px';

设置完基准字体大小后,通过 SASS 的函数封装一个方法方便使用

@function px2rem($value){
  @return $value * 0.02rem
}

使用时直接调用封装好的函数即可,value 传 px 的值,方法会自动转换成 rem。

width: px2rem(100)

2.2 采用 flex 布局

flex 布局推荐 阮一峰的 Flex 布局教程:语法篇

三、Vue 相关问题

一般来说中小公司问框架会多一些,具体是 Vue 还是 React 根据公司所用技术栈而定。因为中小公司技术栈比较统一,很少出现同时用两种甚至三种框架的,且更注重干活的能力,所以框架的使用基本会占面试的一半时间。

大公司反而框架问的少,比较注重基础。他们的逻辑是考察你有没有这个能力,如果能力强用啥框架都能快速上手。

因为我对 React 不太熟,所以就只准备了 Vue 的一些问题。下面几个问题都是面试频率非常高的,一定要弄懂。

有一篇文章对 Vue 总结的比较全,这里也是摘录了几个答案。完整的内容看这里:30 道 Vue 面试题,内含详细讲解(涵盖入门到精通,自测 Vue 掌握程度

3.1 Vue双向绑定原理

如果问框架的话 Vue 肯定会问这个问题,把下面这一段话背下来就好。

Vue 主要通过以下 4 个步骤来实现数据双向绑定的:

  • 实现一个监听器 Observer:对数据对象进行遍历,包括子属性对象的属性,利用 Object.defineProperty() 对属性都加上 setter 和 getter。这样的话,给这个对象的某个值赋值,就会触发 setter,那么就能监听到了数据变化。
  • 实现一个解析器 Compile:解析 Vue 模板指令,将模板中的变量都替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,调用更新函数进行数据更新。
  • 实现一个订阅者 Watcher:Watcher 订阅者是 Observer 和 Compile 之间通信的桥梁 ,主要的任务是订阅 Observer 中的属性值变化的消息,当收到属性值变化的消息时,触发解析器 Compile 中对应的更新函数。
  • 实现一个订阅器 Dep:订阅器采用 发布-订阅 设计模式,用来收集订阅者 Watcher,对监听器 Observer 和 订阅者 Watcher 进行统一管理。

回答完这个问题有的面试官还会延伸问:Vue3 将会用 Proxy 替换 Object.defineProperty()proxy 有什么优点?

建议把 proxy 相关介绍 看一下,说出几个优点。

3.2 虚拟 Dom 实现原理

这个题的重要性仅次于 Vue 双向绑定原理,建议掌握

虚拟 DOM 的实现原理主要包括以下 3 部分:

  • 用 JavaScript 对象模拟真实 DOM 树,对真实 DOM 进行抽象;
  • diff 算法 — 比较两棵虚拟 DOM 树的差异;
  • pach 算法 — 将两个虚拟 DOM 对象的差异应用到真正的 DOM 树。

优点:

  • 保证性能下限: 框架的虚拟 DOM 需要适配任何上层 API 可能产生的操作,它的一些 DOM 操作的实现必须是普适的,所以它的性能并不是最优的;但是比起粗暴的 DOM 操作性能要好很多,因此框架的虚拟 DOM 至少可以保证在你不需要手动优化的情况下,依然可以提供还不错的性能,即保证性能的下限;
  • 无需手动操作 DOM: 我们不再需要手动去操作 DOM,只需要写好 View-Model 的代码逻辑,框架会根据虚拟 DOM 和 数据双向绑定,帮我们以可预期的方式更新视图,极大提高我们的开发效率;
  • 跨平台: 虚拟 DOM 本质上是 JavaScript 对象,而 DOM 与平台强相关,相比之下虚拟 DOM 可以进行更方便地跨平台操作,例如服务器渲染、weex 开发等等。

缺点:

  • 无法进行极致优化: 虽然虚拟 DOM + 合理的优化,足以应对绝大部分应用的性能需求,但在一些性能要求极高的应用中虚拟 DOM 无法进行针对性的极致优化。

深入剖析:Vue核心之虚拟DOM
https://juejin.im/post/5d36cc575188257aea108a74#heading-14

3.3 路由缓存

使用 <keep-alive> 可缓存路由。

它有 includeexclude 两个属性,分别表示包含或排除某些路由,值可以是字符串、数组或者正则表达式。

独有的生命周期方法:activiteddeactivited

3.4 路由跳转,name 和 path 跳转的区别

路由跳转的几种方式

// 字符串
this.$router.push('home')

// 命名的路由
this.$router.push({
   
  name: 'user',
  params: {
   userId: '123'}
})
//接收参数
this.userId = this.$route.params.userId

// 带查询参数,变成 /user?userId=123
this.$router.push({
   
  path: '/user',
  query: {
   userId: '123'}
})
//接收
this.userId = this.$route.query.userId;

name 和 path 跳转的区别在于

  • name 传参用 params,path 传参用 query。
  • 用 name 跳转后参数不会携带到 url 上,用 query 传参参数会携带到 url 上。

3.5 路由守卫

全局前置守卫

注意一定要调用 next(); ,否则钩子就不会被 resolved。


                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值