参考资料 前端面试宝典

首屏渲染优化

代码层面

  • 组件库的按需引入
  • 路由的异步加载
  • 使用服务端渲染SSR,直接由服务端返回渲染好的HTML
  • 事件防抖节流,减少事件处理次数
  • 减少DOM层级
  • 减少DOM渲染次数(批量渲染documengFragment,差量渲染Vue/React)

通信层面

  • 缓存网路数据在localStorage里或vuex/redux里,减少请求次数
  • 小图片直接使用base64以减少网络请求次数
  • 使用HTTP协议的强缓,服务端给更新频率低的数据一个较长的缓存时间(响应头Cache-Control:maxAge(3600247))
  • 从CDN或静态资源服务器去获取图片、js、css、图标字体等静态资源

打包层面

  • 对图片进行物理压缩,如在线压缩工具TinyPNG
  • 打包时对HTML,CSS,JS进行压缩处理
  • 开启Gzip压缩;
  • 合理分包,将第三方包、轮子包、业务代码包分开,这样在前端版本升级时,往往还需要更新业务代码包,而第三方包和轮子包由于内容未变导致hash未变,因此直接被服务端判断为304,从而直接使用本地缓存;
  • 打包时开启Tree-Shaking,摇掉无用代码,减少包体积;
  • 从HTML中抽离CSS文件,以便单独下载与缓存;

小程序的微信授权流程(用微信账号登录自家服务器)

  • 在小程序端wx.login()得到登录码code
  • 小程序请求自家的登录接口,携带登录码code
  • 自家服务器请求微信服务器,使用appid+appSecret+code换回session_key与openid
  • 自家服务器将session_key与openid重新换算为自家的登录信息(如token)
  • 小程序在后续请求自家服务器的过程中都携带该token,自家服务器就知道小程序端已经登录过了
    参考链接

Set与Map

  • ES6的新增数据结构
  • Set用于基础数据的去重,一些核心API如下:
// 对数组去重
cosnt mySet = new Set([3,1,4,1,5,9,2,6,5,3,5,8])// 转化回数组
const norepeatArr = [...mySet]mySet.add(value) //添加元素
mySet.has(value) //判断某元素是否存在
mySet.size //元素数量
  • Map用于键值对的便捷操作与查询,底层就是Object

const contacts = new Map()

//设置或覆盖key-value
contacts.set(‘Jessie’, {phone: “213-555-1234”, address: “123 N 1st Ave”})
contacts.has(‘Jessie’) //查询key是否存在
contacts.get(‘Hilary’) //查询key对应的value
contacts.delete(‘Raymond’) //删除key-value
contracts.size //查询键值对的数量

Promise与asycn,await的区别

  • await是promise.then的语法糖
//ajaxApi(url,parmas)的返回值是promise对象
//阻塞等待promise对象resolve数据出来
const data = await ajaxApi(url,parmas)
  • await关键字所在的函数必须声明为异步函数
async function fn(){//内含await}
async ()=>{//内含await}
const fn = async ()=>{//内含await}
  • promise.catch由await所在的代码块进行try-catch
async fn(){try{// ajaxApi(url,parmas)的返回值是promise对象// 如果promise毁约(reject),则错误信息由try-catch的catch获得const data = await ajaxApi(url,parmas)}catch(err){//此处的err即promise所reject出的错误信息hanleErr(err)}
}

HOC与RenderProps

答题要点

  • 两者都是React复用逻辑的主要方式,另外个主要方式是大名鼎鼎的天王【自定义Hook】
  • HOC的逻辑是子组件进去,父组件出来,父组件在直接渲染子组件之余,为子组件注入了新的props、新的生命周期、新的DOM事件监听、新的副作用…这一大堆东西即你想复用的数据与逻辑
  • RenderProps的逻辑是组件进去,怀了孕(Baby)的组件出来,Baby组件自带响应式数据与变化逻辑,即你想复用的数据与逻辑
  • 案例:以【实时显式鼠标移动位置】这一复用逻辑为例:

HOC案例

/* 子组件App进去 增强型的父组件XApp出来 */
const withMouse = (App) => {class XApp extends Component {constructor(props) {super(props);// 为子组件注入响应式数据x,ythis.state = {x: 0,y: 0,};}/* 鼠标移动动态修改状态x,y的值 */onMouseMove = (e) => {this.setState(() => ({x: e.pageX,y: e.pageY,}));};render() {// 在此以外做的一切事情都是增强// return <App {...this.props}></App>return (// 给子组件的顶层DOM添加鼠标移动监听器<div onMouseMove={this.onMouseMove}>{/* 为子组件注入响应式数据x,y */}{/* <Com name={props.name} x={this.state.x} y={this.state.y} /> */}<App {...this.props} {...this.state} /></div>);}}// 普通的App进来 增强型App出去// 增强1:在顶层DOM身上绑定了鼠标移动事件监听器// 增强2:注入了响应式数据x,y即鼠标实时移动到的位置return XApp;
};

RenderProps案例

import React, { Component } from 'react'/* 对鼠标移动的state与事件的封装提取 */
class Mouse extends Component {constructor(props) {super(props);// 老鼠baby自带响应式数据this.state = {x: 0,y: 0}}/* 在DOM事件中改变响应式数据 */onMouseMove = (e) => {this.setState({x: e.pageX,y: e.pageY})}render() {return (// 老鼠baby自带DOM事件监听——用以动态改变响应式数据<div onMouseMove={this.onMouseMove}>{/* 拿出我妈给我的renderFn(x,y)执行得到DOM */}{this.props.renderFn(this.state.x, this.state.y)}</div>)}
}class App extends Component {render() {return (<div>{this.props.name}<br />{/* 将一只老鼠子组件放在此处 即相当于把【实时显式鼠标移动位置】放在这 */}{/* <div style={{ height: "1000px", backgroundColor: "#eee" }}>鼠标实时位置:{x},{y}</div> */}<Mouse// 告诉我的baby拿到响应式数据x,y后如何渲染JSXrenderFn={(x, y) => <div style={{ height: "1000px", backgroundColor: "#eee" }}>鼠标实时位置:{x},{y}</div>}/></div>)}
}export default App

前端权限控制

  • 登录成功后,服务端返回该用户的角色/权限;
  • 可以将该角色/权限等级数据存储在全局(例如全局状态管理);
  • 路由层面A计划-动态生成路由表:根据该用户的等级动态添加它有权访问的路由(一旦用户访问自己无权访问的路由时命中404);
  • 路由层面B计划-路由守卫:使用路由守卫,当用户访问越权的路由时一脚踹到登录页;
  • 界面层面A计划-条件渲染:根据用户的权限条件渲染它能访问的Link,组件、具体元素等;
  • 界面层面B计划-封装:
  • Vue中可以自定义指令如v-auth="3"当用户的等级不足3时将该按钮disable掉或隐藏掉;
  • React中可以使用HOC实现例如WithCustomAuth(MyButton,3)在返回JSX的时候使用条件渲染
function WithCustomAuth(Com,level){function Parent(props){reurn ({authFromRedux >= level ? <Com {...props} /> : <a href="/login">登录</a>})}return Parent
}

Websocket与HTTP有啥区别

  • Websocket基于TCP协议,工作在传输层,长连接双工通信;
  • HTTP是应用层协议,单向短链接,请求-响应-断开;
  • Websocket已为大多数浏览器所支持,场景如:客服、秒杀、实盘、直播…
    案例
    服务端
var app = require('express')();
var server = require('http').Server(app);
var WebSocket = require('ws');// 服务端监socket监听在8080 等待客户端连接
var wss = new WebSocket.Server({ port: 8080 });// 准备客户端存储对象
const clients = {}/* 有客户端请求接入 入参ws即为接入的客户端socket对象 */
wss.on('connection', function connection(ws) {console.log('server: receive connection from client');// 将该客户端存下来 时间戳:socketclients[Date.now()] = wsconsole.log("clients",Object.keys(clients));// 接收到该客户端发来的消息ws.on('message', function incoming(message) {console.log('message',message);ws.send('got it:'+message);// 转发给它想要发送的其它客户端const [to,msg] = message.toString().split(":")clients[to*1].send(message.toString())});// 该客户端主动断开连接ws.on("close",function(code,reason){console.log("客户端已断开连接");})// 与该客户端的连接发送错误ws.on("error",function(err){//处理错误})// 立刻给刚刚接入的客户端发送消息ws.send('welcome!');
});/* 在http的3000端口返回页面给客户端 */
app.get('/', function (req, res) {res.sendfile(__dirname + '/index.html');
});
app.listen(3000);

客户端

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><input type="text" placeholder="please enter..." id="ipMsg"><button id="btn">发送消息</button><button id="btnClose">断开连接</button><script>// 发起远程连接请求websocket长连接var ws = new WebSocket('ws://localhost:8080');// 连接成功时打印一下ws.onopen = function () {console.log('ws onopen');//   ws.send('from client: hello');};// 收到服务端的消息时打印一下ws.onmessage = function (e) {console.log('ws onmessage');console.log('from server: ' + e.data);};// 点击按钮给服务端发送消息btn.onclick = function(e){ws.send(ipMsg.value);}// 点击按钮断开与服务端的连接btnClose.onclick = function(e){ws.close()console.log("连接已断开");}</script>
</body>
</html>

react中怎么在父组件里使用子组件的函数

  • 父组件给子组件一个callback,子组件在使用该callback时入参一个自己的函数,让父组件去调用
    PS:纯脑洞问题 没有普适性
function Parent(props){const callMe = (sonFn)=>sonFn()return (<><Son callback={callMe}></>)
}function Son({callback}){const sonFn = (sonFn)=>alert('老爸调用到我了')return (<><button onClick={callback(sonFn)}>让父组件调用我的函数</button></>)
}

Map与Object的区别

  • 本质上都是key-value管理数据
  • Map是ES6新增的数据结构,主要就是在Object的基础上封装除了几个便捷API,以做到和其它语言接轨(很多其它语言中都有Map这种数据结构)
  • 这些便捷API包括map.set(key,value),let value = map.get(key),map.delete(key),map.size
  • 一个简单的MyMap封装

class MyMap {constructor(){this.dataObj = {}this.size = 0}set(key,value){if(!this.dataObj.hasOwnProperty(key)){this.size ++}this.dataObj[key] = value}get(key){return this.dataObj[key]}delete(key){delete this.dataObj[key]this.size --}
}const mm = new MyMap()
mm.set("name","OOP小菜鸡")
console.log(mm.get("name"));
console.log(mm);

按需加载 VS 异步加载 VS TreeShakig VS Webpack分包

  • 按需加载主要指代码层面不引入不需要的东西,典型场景是组件库中只引入自己需要的组件
import {Button} from "antd"
  • 异步组件,什么时候访问,就什么时候加载,否则不加载
//同步引入 编译时引入 无论用户访问不访问都引入
//import Home from "@/views/Home.vue"//异步加载 运行时加载 用户访问该页面时才临时去加载
// 注释部分代表Webpack打包时将该组件打包为about.js这样一个异步chunk
const About = ()=>import(/* webpackChunkName: "about" */,"@/views/About.vue")
  • TreeShaking:Webpack打包时自动将引而未用的内容排除在外,启动方式mode:production
  • Wepack分包的核心目的是为了最大化地使用包的缓存,例如将常用的第三方包打在vendor.hash.js中,自己的轮子代码打在common.hash.js中,将自身的业务逻辑打在main.hash.js中,当项目需要升级时,如果只改动了业务代码而没有触及轮子与第三方包,则vendor.hash.js与common.hash.js这两个chunk的hash是不变的,HTTP的缓存机制自动生效,用户端只需要更新main.hash.js这一个包即可;

递归组件

  • 自己作为自己的子组件,例如:无穷子菜单,博文的无穷回复;
  • 核心逻辑,以无穷回复为例:
  • 每篇博文有它的回复数据,假设叫replies
  • 组件CommentItem正常渲染出每个回复item的用户名、回复时间
  • 每个回复的item依然有它的子回复replies
  • 将replies中的每一项,继续映射为一个新的CommentItem
function CommentItem({item}){return <><h3>item.username</h3><span>item.date</span>{/*渲染item的子回复replies*/}{item.replies.map(it=><CommentItem item={it}/>)}</>
}

[参考链接] (https://juejin.cn/post/7087904975400992798)

JWT-token的原理

# jwt鉴权机制

md5消息摘要算法保护用户的信息

md5消息摘要算法的基本原理

  • md5是消息摘要(digest)算法;
  • 无论【信息】多长或多短,一律生成一个不可逆的32位字符串;
  • 只要【信息】变化一点点,生成的消息摘要都会大相径庭;
  • 消息摘要算法用于校验数据的完整性(即原始数据是否被人篡改过);
  • 其它知名的消息摘要算法还有SHA256,原理相同,生成的消息摘要更长;

以保护用户的密码为例

  • 用户注册时填入的密码以消息摘要的形式存储在数据库中;
  • 用户登录时填写的登录密码,在服务端生成消息摘要,再与数据库中的密码消息摘要做比对;
  • 服务端在校验密码时生成消息摘要的过程,只要程序员不偷偷记录和转移数据,则理论上用户信息是“安全”的;

“这不需要测试,肯定是好的,不用担心”

前端技术面试核心问题(持续更新)相关推荐

  1. Android面试总结(持续更新修改)

    ###Android面试总结(持续更新修改) 1.Android 的四大组件是哪些,它们的作用? ①Activity是Android程序与用户交互的窗口,是Android构造块中最基本的一种,它需要为 ...

  2. PHP 面试总结(持续更新) --小丑

    Session与cookie的区别? cookie数据存放在客户的浏览器上,session数据放在服务器上,以文件的形式存放,可以从php.ini里面的session.save_path找到存放位置 ...

  3. 【Python】Python学到什么程度可以面试工作?------持续更新 ...

    前言: 从事python学习,有爬虫.web后台.深度学习相关经验, 坐标北京欢迎骚扰. 本答案力求简洁和直击重点,代码部分使用Python3,更详细的解释请Google,回答有误请务必提醒答主,我将 ...

  4. 多益2018春招前端技术面试

    2018春招,多益网络内推,前端开发工程师,技术面问题 据我了解,从一月到三月份年,多益一共启动了至少三批春招招聘.从同学的反馈来看,一月份考验刚结束的那批春招通过率比较高.至于我个人,参加的是三月份 ...

  5. 汽车环境感知技术详解【 持续更新ing 】— 超声波传感器原理及应用

    专栏解读: 本专栏针对自动驾驶技术(智能网联汽车技术)中的感知技术进行详细介绍. 包含: 汽车感知技术概念 多传感器融合原理 各传感器原理及应用(超声波,毫米波,激光雷达,视觉传感器,全球定位系统) ...

  6. flex布局练习题,面试必备,持续更新建议收藏~

    先言:  现在网页布局大多都是flex布局,像浮动这些用得比较少,在面试中flex也是被经常问到的.而有些同学学完flex后,又不懂怎么练习巩固,所以,所以,所以,我汇聚了一些常见的flex的练习题案 ...

  7. 车载传感器技术详解【 持续更新ing 】— 自动驾驶技术概述

    一.智能网联汽车定义: 1.定义: 智能网联汽车(Intelligent Connected Vehicle,ICV)是指车联网与智能车的有机联合,是搭载先进的车载传感器.控制器.执行器等装置,并融合 ...

  8. 汽车环境感知技术详解【 持续更新ing 】— 传感器概述与基本特性

    专栏解读: 本专栏针对自动驾驶技术(智能网联汽车技术)中的感知技术进行详细介绍. 包含: 汽车感知技术概念 多传感器融合原理 各传感器原理及应用(超声波,毫米波,激光雷达,视觉传感器,全球定位系统) ...

  9. 汽车环境感知技术详解【 持续更新ing 】— 激光雷达原理及应用

    专栏解读: 本专栏针对自动驾驶技术(智能网联汽车技术)中的感知技术进行详细介绍. 包含: 汽车感知技术概念 多传感器融合原理 各传感器原理及应用(超声波,毫米波,激光雷达,视觉传感器,全球定位系统) ...

最新文章

  1. 大型网站采用什么系统架构保证性能稳定性
  2. 基于RDKit的Python脚本:SDF格式转SMILES格式
  3. php中类的构造函数是,PHP 类的构造函数和析构函数
  4. tensorflow 进阶(四)---CNN
  5. Python日志详解【两篇就够了系列】--第一篇logging
  6. 【Django】ORM操作#2
  7. Profile文件管理
  8. Some Fiori offline screenshot in Mac
  9. 前端学习(2511):组件注册
  10. 2-4:C++快速入门之函数重载
  11. 分布式事务模型--最大努力通知型分布式事务
  12. HBase之Region Compact流程分析
  13. 深入分析同步工具类之AbstractQueuedSynchronizer
  14. C++算法学习(力扣:402. 移掉K位数字)
  15. xgboost和lightGBM区别
  16. 数据挖掘概念与技术(原书第三版)范明 孟小峰译-----第六章课后习题答案
  17. linux和windows截图软件下载,【教程】数字菌教你从windows过渡到linux之软件的替换...
  18. 群控 云控营销神器代码研究
  19. 微信小程序 image-cropper 还原按钮控制
  20. UE<C++>三步在C++中制作射击类游戏(射线检测、接口调用)

热门文章

  1. nodejs双感叹号用法
  2. python supper代码详解
  3. 制作自己的Tomcat镜像
  4. 堆排序稳定性举例_稳定排序和不稳定排序
  5. QQ宠物冒险岛全攻略
  6. 【云原生之Docker实战】使用Docker部署Alist网盘直链程序
  7. 如何解决医院网站商务通无轨迹来源路径的问题
  8. linux系统使用实验报告操作系统,linux操作系统实验报告1.doc
  9. AD域部署软件自动下发
  10. error RC1015: cannot open include file 'sal.h'.