前端面试题目整理
Liuyi 2020-10-27 面试
# 前端面试题整理
# SEO
1. 合理的设置title、description、keywords,
2. 语义化的HTML代码
3. 重要的html代码放在前面
4. 重要内容不要用js输出,爬虫不会抓取js获取内容
5. 少用iframe,爬虫不会抓取iframe里面的内容
6. 非装饰性图片加alt属性
7. 提高网站速度
# CDN
将图片跟视频放在CDN服务上面,实例七牛储存图片。
# 如何实现浏览器内多个标签页之间的通信?
1. iframe + contentWindow
2. postMessage
Windows.postMessage()方法项目目标窗口发送一个MessageEvent消息
otherWindow.postMessage(message, targetOrigin, [transfer])
window.addEventListener("message", receiveMessage, false);
1
2
3
4
2
3
4
4. SharedWorker(Web Worker API)
5. localStorge(localStorge API)
6. WebSocket
# 前端代码和资源的压缩与合并
1. Gzip压缩:Web服务器开启Gzip压缩后,会在Response的header中增加了Content-Encoding:gzip
2. js代码压缩
去掉多余的空格和回车,替换长的变量名,简化一些代码的写法。
3. 图片视频资源压缩
# CSS 盒模型
基本的:content的宽度 box-sizing: content-box
IE: width 属性不是内容的宽度,而是内容、内边距和边框的宽度的总和。
box-sizing: boder-box
# 层叠上下文
z-index:
# 清除浮动
增加伪元素clear: both
创建父级BFC
# 居中布局
块级元素
行内元素
# JS的基本数据类型和引用数据类型
基本数据类型:undefined、null、boolean、number、string、symbol
引用数据类型:object、array、function
# 图片实现自适应宽高
<img> 属性是会自动调整图片的宽高比,但是在布局家在当中图片高度会实现一个0到高度的变化 ,影响页面布局。<div>中使用padding 设置%值因为padding%的取值是基于宽度的
# flex常见属性
flex-direction flex-wrap justify-content align-items
# BFC是什么
块级格式化上下文,是一个独立的渲染区域,让处于 BFC 内部的元素与外部的元素相互隔离,使内外元素的定位不会相互影响。
1. 属于同一个 BFC 的两个相邻 Box 垂直排列
2. 属于同一个 BFC 的两个相邻 Box 的 margin 会发生重叠
3. BFC 中子元素不会超出他的包含块
4. BFC 的区域不会与 float 的元素区域重叠
5. 计算 BFC 的高度时,浮动子元素也参与计算
6. 文字层不会被浮动层覆盖,环绕于周围
# 什么是事件代理(事件委托)?
减少dom交互次数,提高了性能,利用了事件冒泡解决。
利用target属性(可以返回事件的目标节点,我们成为事件源)。
适合用事件委托的事件:click,mousedown,mouseup,keydown,keyup,keypress。
# 项目里面的前端鉴权是怎么实现的?
1. 1. HTTP Basic Authentication (HTTP基本认证)
将认证信息储存在 Authentication 中
3. session-cookie
将信息储存在session-cookie中
带有状态 session 会在一次会话结束之后关掉
5. Token 验证(包括JWT,SSO)
JWT:讲Token放入Authorization,Authorization: Bearer <token>
多平台
7. OAuth(开放授权)
微信授权
# 防抖和函数节流
防抖:指定时间间隔内只会执行一次任务
节流:任务频繁触发的情况下,只有任务触发的间隔超过指定间隔的时候,任务才会执行。
# js原型_构造函数_实例
![](1460000018155881.jpg)
[最详尽的 JS 原型与原型链终极详解,没有「可能是」。(一) - 简书](https://www.jianshu.com/p/dee9f8b14771)
# 原型链:
**原型链是由原型对象组成**,每个对象都有__proto__属性,指向了创建该对象的构造函数的原型,__proto__将对象连接起来组成了原型链。是一个用来**实现继承和共享属性**的有限的对象链。
属性查找机制
属性修改机制
# 执行上下文
1. 它包含三个部分:
变量对象(VO)
作用域链(词法作用域)
this指向
2. 它的类型:
全局执行上下文
函数执行上下文
eval执行上下文
3. 代码执行过程:
创建**全局上下文**(global EC)
全局执行上下文 (caller) 逐行**自上而下**执行。遇到函数时,**函数执行上下文**(callee) 被push到执行栈顶层
函数执行上下文被激活,成为 active EC, 开始执行函数中的代码,caller 被挂起
函数执行完后,callee 被pop移除出执行栈,控制权交还全局上下文 (caller),继续执行
# 常用的es6语法
1. let 块级作用域,不存在变量提升。
2. 解构复制
3. promise
Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一 的 API,各种异步操作都可以用同样的方法进行处理。
三个状态 。两个回调函数 两个函数参数。
不要在then方法里面定义 Reject 状态的回调函数(即then的第二个参 数),总是使用catch方法。
4. Iterator
遍历器(Iterator)就是这样一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作(即依次处理该数据结构的所有成员)。
5. class
6. Generator
一种异步编程解决方案
function* helloWorldGenerator() {
yield 'hello';
yield 'world';
return 'ending';
}
1
2
3
4
5
2
3
4
5
7. async 函数
Generator 函数的语法糖。
8. Set / Map
Set 类似于数组但是值都是唯一的 WeakSet 值只能是对象
Map “值-值”的对集合 WeakMap 只接受对象作为键名
# 代码的复用
函数的封装
继承
复制
混入
借用
# 模块化
分类:
es6: import/exports
commonjs: require / module.exports / exports
amd: require / defined
require与import
require支持动态导入
require是同步导入,import属于异步导入
repuire是值拷贝,import指向内存地址
# 图片懒加载
将图片地址储存在,data-XXX中然后在JS里面判断图片在可视区域内在设置图片src
# 跨域
JSONP
利用<script>标签不受跨域的特点实现,缺点只能支持get请求
CORS跨域资源共享
后端设置, Access-Control-Allow-Origin,Access-Control-Allow-Credentials
postMessage
# http状态码
100 Continue 一般在发送post请求时 http header返回此信息表示确认
200 OK 成功信息
201 Created 请求成功并且创建了新的资源
202 Accepted 服务器接受了请求但尚未处理
301 Moved Permanently 请求网站已永久移动到了新的位置
304 自从上次请求之后,网页未修改过
403 禁止访问
404 找不到如何与Url相匹配的资源
500 常见服务器错误
# HTTP和HTTPS
HTTP协议通常承载于TCP协议之上,在HTTP和TCP之间添加一个安全协议层(SSL或TSL),这个时候,就成了我们常说的HTTPS
默认HTTP的端口号为80,HTTPS的端口号为443
基本方法: GET, POST, PUT,DLETE
请求消息:![](2012072810301161.png)
响应消息
状态行
消息报头
空行
响应正文
keepalive:
Connection: Keep-Alive 避免重新建立连接
# TCP三次握手
所谓三次握手(Three-way Handshake),是指建立一个 TCP 连接时,需要客户端和服务器总共发送3个包。
三次握手的目的是连接服务器指定端口,建立 TCP 连接,并同步连接双方的序列号和确认号,交换 TCP 窗口大小信息。在 socket 编程中,客户端执行connect()时。将触发三次握手。
1. 第一次握手(SYN=1, seq=x):
客户端发送一个 TCP 的 SYN 标志位置1的包,指明客户端打算连接的服务器的端口,以及初始序号 X,保存在包头的序列号(Sequence Number)字段里。
发送完毕后,客户端进入SYN_SEND状态。
2. 第二次握手(SYN=1, ACK=1, seq=y, ACKnum=x+1):
服务器发回确认包(ACK)应答。即 SYN 标志位和 ACK 标志位均为1。服务器端选择自己 ISN 序列号,放到 Seq 域里,同时将确认序号(Acknowledgement Number)设置为客户的 ISN 加1,即X+1。 发送完毕后,服务器端进入SYN_RCVD状态。
3. 第三次握手(ACK=1,ACKnum=y+1)
客户端再次发送确认包(ACK),SYN 标志位为0,ACK 标志位为1,并且把服务器发来 ACK 的序号字段+1,放在确定字段中发送给对方,并且在数据段放写ISN的+1
发送完毕后,客户端进入ESTABLISHED状态,当服务器端接收到这个包时,也进入ESTABLISHED状态,TCP 握手结束。
# http缓存
1. 缓存控制
http1.0 :
Pragma: no-cache 不缓存
Expires: GMT 缓存 设置缓存时间
Cache-Control:
no-cache: 缓存
no-store: 不被缓存
max-age:缓存时间
public
private
must-revalidate
2. 缓存校验
Last-Modified: GMT 加在实体首部 服务端设置 [If-Modified-Since](https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/If-Modified-Since)
ETag: 服务器在第一次返回资源时会加上一个Etag,浏览器在再次请求此资源的时候设置 [If-None-Match](https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/If-None-Match)会携带上这个Etag,服务器检查这个Etag,判断为没有修改之后,返回响应304,并且一个空的返回体
Vary: User-Agent 因用于不同设备之间的缓存判断
# 柯里化
函数分步传递参数,每次传递部分参数,并返回一个更具体的函数接收剩下的参数,这中间可嵌套多层这样的接收部分参数的函数,直至返回最后结果。
# 深浅拷贝
基本数据类型跟应用数据类型。
浅拷贝只是复制了对象的应用,
深拷贝,json反序列化,递归复制
[深浅拷贝原理](https://segmentfault.com/a/1190000008838101)
function deepCopy (obj) {
var result;
//引用类型分数组和对象分别递归
if (Object.prototype.toString.call(obj) == '[object Array]') {
result = []
for (i = 0; i < obj.length; i++) {
result[i] = deepCopy(obj[i])
}
} else if (Object.prototype.toString.call(obj) == '[object Object]') {
result = {}
for (var attr in obj) {
result[attr] = deepCopy(obj[attr])
}
}
//值类型直接返回
else {
return obj
}
return result
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# symbol
# 一个完整的http事务是怎样一个过程?
1. 域名解析
2. 发起TCP三次握手
3. 建立TCP请求之后发起http请求
4. 服务器端响应http请求,浏览器得到html代码
5. 浏览器解析html代码,并请求html代码中的资源
6. 浏览器对页面进行渲染呈现给用户
# Generator
...
# async
...
# axios
创建axios是咧`const service = axios.create`
实例的方法:
1. request
2. get
3. post
4. delete
5. head
6. put
请求配置
{
url:
methods:
baseurl:
transformrequest: //对data进行任意转换处理
timeout:
responseType:
...
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
请求拦截器 `axios.interceptors.request.use`
响应拦截器 `axios.interceptors.response.use`
# 重绘与回流(重排)
重绘: 样式不改变布局,只进行UI层面的重新像素绘制,开销较少
回流(重排): 元素的尺寸,结构改变或者出发某些属性(伪类)浏览器重新渲染
总结:
1. 避免频繁操作样式可汇总后统一修改
2. 尽量少使用class进行样式修改
3. 减少dom增删次数
4. 使用变量存住 -> 获取DOM之后用变量储存
# 储存 请描述一下 cookies,sessionStorage 和 localStorage 的区别?
浏览器:
cookie: 通常用于储存用户身份,登录状态,http中自动携带,体积上限为4k,可自行设置过期时间。储存量小,只能储存字符串,影响性能
localStorage/ sessionStorage: 长时间储存,体积为4M,localStorage没有过期时间,sessionStorage,窗口关闭删除
IndexDB:受同源策略的限制
服务器:
分布式缓存redis
数据库
# Web Worker
多线程环境,可分配任务到worker中并行运行,两个线程可独立运行,互不干扰,可自带消息机制相互通信
// 创建 worker
const worker = new Worker('work.js');
// 向主进程推送消息
worker.postMessage('Hello World');
// 监听主进程来的消息
worker.onmessage = function (event) {
console.log('Received message ' + event.data);
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
限制:
同源策略
无法使用 document_windows_alert/confirm
无法加载本地资源
# 垃圾回收
考虑某个变量或对象在未来的程序运行中将不会被访问 向这些对象要求归还内存
**引用计数** **标记-清除**
# 内存泄漏
主要是因为程序不能释放那些不再使用的内存
**循环引用**
**无意的全局变量**
**被遗忘的计时器和回调函数** setInterval setTiemout
# Websocket
websocket是一个持久化协议,基于http,服务端可以主动push
数据格式比较轻量,性能开销小,通信高效。
可以发送文本,也可以发送二进制数据。
没有同源策略限制
长轮询 :客户端不断的向服务端发送请求
long poll 有消息时服务端向客户端发送请求
new WebSocket(url)
ws.onerror = fn
ws.onclose = fn
ws.onopen = fn
ws.onmessage = fn
ws.send()
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
# 实现一个二叉树的优先遍历
[js 中二叉树的深度遍历与广度遍历(递归实现与非递归实现) - 简书](https://www.jianshu.com/p/5e9ea25a1aae)
# addEventListener,第三个参数的作用是什么
可选。布尔值,指定事件是否在捕获或冒泡阶段执行。
# js事件阶段(捕获>目标>冒泡),阻止冒泡有哪些方法?
# 那么 apply、call、bind 三者相比较,之间又有什么异同呢?
[JS中的call、apply、bind方法详解 - 风雨后见彩虹 - 博客园](https://www.cnblogs.com/moqiutao/p/7371988.html)
区别是,当你希望改变上下文环境之后并非立即执行,而是回调执行的时候,使用 bind() 方法。而 apply/call 则会立即执行函数。
# eval()
# 不定宽高的情况下实现正方形,不定尺寸的图片自适应展示
任意方向的 padding-top
# 弹性布局模型 Flex
# forEach Map中断循环(详细的用法)
forEach Map 不能跳出循环,Map返回的是一个数组,forEach只是对每个元素进行处理。 通过try…catch 可以
# 如何跟踪排除内存泄露
[JS内存泄漏排查方法 - 云+社区 - 腾讯云](https://cloud.tencent.com/developer/article/1444558)
# webpack单位件独立打包
# for of 跟 for in的差别
[javascript总for of和for in的区别? - SegmentFault 思否](https://segmentfault.com/q/1010000006658882)
# <script>
标签async defer属性的区别
都是让js下载不阻止DOM渲染,但是defer会使js按顺序执行async是谁先下载好谁先执行
# em rem px 区别
px 相对于分辨率
em 相对与 父元素的font-size
rem 相对与 根元素的font-size
# get跟post的区别
*误区:我们经常说get请求参数的大小存在限制,而post请求的参数大小是无限制的。*
参考答案
实际上HTTP 协议从未规定 GET/POST 的请求长度限制是多少。对get请求参数的限制是来源与浏览器或web服务器,浏览器或web服务器限制了url的长度。为了明确这个概念,我们必须再次强调下面几点:
- HTTP 协议 未规定 GET 和POST的长度限制
- GET的最大长度显示是因为 浏览器和 web服务器限制了 URI的长度
- 不同的浏览器和WEB服务器,限制的最大长度不一样
- 要支持IE,则最大长度为2083byte,若只支持Chrome,则最大长度 8182byte 补充补充一个get和post在缓存方面的区别:
- get请求类似于查找的过程,用户获取数据,可以不用每次都与数据库连接,所以可以使用缓存。
- post不同,post做的一般是修改和删除的工作,所以必须与数据库交互,所以不能使用缓存。因此get请求适合于请求缓存。
# ['1','2','3'].map(parseInt) 输出什么,为什么?
输出:[1, NaN, NaN]
首先让我们回顾一下,map函数的第一个参数callback:var new_array = arr.map(function callback(currentValue[, index[, array]]) { // Return element for new_array }[, thisArg])
这个callback一共可以接收三个参数,其中第一个参数代表当前被处理的元素,而第二个参数代表该元素的索引。
而parseInt则是用来解析字符串的,使字符串成为指定基数的整数。parseInt(string, radix)接收两个参数,第一个表示被处理的值(字符串),第二个表示为解析时的基数。了解这两个函数后,
我们可以模拟一下运行情况
parseInt('1', 0) //radix为0时,且string参数不以“0x”和“0”开头时,按照10为基数处理。这个时候返回1parseInt('2', 1) //基数为1(1进制)表示的数中,最大值小于2,所以无法解析,返回NaN
parseInt('3', 2) //基数为2(2进制)表示的数中,最大值小于3,所以无法解析,返回NaNmap函数返回的是一个数组,所以最后结果为[1, NaN, NaN]