一、序
又到每年的金三银四找工作了,当然需要些八股文来撑过面试阶段了,这里收集些前端常用的,然后说的公司,厦门的助兴科技可以避雷,因为我体验过...然后这里面试题汇总我面试时小公司总在问的那些,算是频率高的那种吧!!!
祝:心想事成、事事顺心
二、HTML部分
(1)文档声明
<!-- HTML5中文档声明的写法 -->
<!DOCTYPE html>
作用: 告诉浏览器用哪一个HTML版本标准来解析文档
说明: 在浏览器的发展过程中,HTML出现过多个版本,不同的版本在元素、属性的书写格式上面存在差异,如果不事先告诉浏览器文档的标准是什么,那么大部分浏览器肯定会选择大多数浏览器都支持的解析方式,这种称为怪异模式,页也叫混杂模式,这样做的代价为降低解析效率,并且在解析的过程中会出现难以预料的bug,因此文档声明是必须的
(2)严格模式和混杂模式
严格模式: 指浏览器按照W3C标准来解析文档
混杂模式: 指浏览器按照浏览器自己的标准来解析文档
意义: 这两种模式存在的意义在于兼容旧网站,让其能够在大多数浏览器上面展示出来
(3)混杂模式的特点
- 宽高的算法与标准的不一致,也就是两种盒模型
- 表格中的样式不会继承
- 可以设置行内元素的宽高
(4)HTML语义化
H5新增的标签:
<header />:用于定义页面的头部区域
<nav />:定义页面的导航链接部分区域
<main />:定义文档的主要内容,该内容在文档中应当是独一无二的
<article />:定义页面独立的内容
<section />:表示文档中的一个区域
<aside />:表示一个和其余页面内容几乎无关的部分,被认为是独立于该内容的一部分且可以被单独的拆分出来而不会影响整体
<footer />:定义最近一个章节内容或者根节点元素的页脚
作用:
- 去掉或者丢失样式的时候能够让页面有清晰的结构
- 有利于SEO,能够让爬虫抓取更多有效的信息
- 方便其它设备解析,让其用有意义的方式来渲染网页
- 便于团队的开发和维护
(5)WEB标准和W3C的理解
解释: 任何东西都需要一个标准,有了标准才能够更好的交流和进行推广,由于不同的标准会得到不同的结果,因此如何确定标准就显得十分重要;标准的作用在于降低开发难度以及开发成本,减少各种bug,从而提高网站的易用性,而W3C就是一个推出标准的组织,由它来发展WEB规范
(6)SEO优化操作
合理的TDK: 所谓的TDK其实就是title、description、keywords
title:指网页的标题title,这是搜索引擎最先抓取网页时所获取的内容,一般不超过80个字符
description:对网页内容的简单概括,一般不超过150个字符
keywords:告诉搜索引擎网页的内容是围绕那些词语展开的,有点寻找主语的味道,因此每个词语都需要在文中找到对应的匹配才有利于排名,词语一般不超过3个
<!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>健康饮食指南 - 简单易学的健康饮食原则</title>
<meta name="description" content="探索如何通过合理饮食来改善健康,包含常见的健康饮食建议和推荐食谱">
<meta name="keywords" content="健康饮食, 饮食原则, 健康食谱, 营养均衡">
</head>
<body>
<!-- 网页内容 -->
</body>
</html>
重要内容在前: 因为内容的抓取是从上到下的
谨慎使用display:none: 因为所有引擎会过滤里面的内容,所以对于不显示的对象可以使用别的方法,比如opacity:0
(7)iframe
作用: 把一个网页的框架和内容嵌入到已有的网页中
优点:
重载时不需要重载整个页面,只需要重载页面中的一个框架页,因而减少了数据的传输,加快了网页的下载速度
方便制作导航栏
缺点:
浏览器的后退按钮无效
多数的小型移动设备无法完全显示框架里面的内容
阻塞页面的加载,window的onload事件需要在所有的iframe加载完毕之后才会触发
(8)替换元素和非替换元素
说明: 替换元素的大部分展示效果不由css决定,比如<img />,在页面展示的效果主要取决于你使用什么图片,虽然你可以控制它的位置和大小,但是你无法控制其本身的内容;<img />、<video />、<audio />和大部分表达元素都属于替换元素。那么除此之外的元素就是非替换元素了,它的展示完全由css决定
(9)src和herf的区别
说明: src用于指定资源文件的路径,而herf用于指定链接的地址
(10)meta标签
作用: 提供关于HTML文档的元数据,这些数据不会在页面上显示,但是对于机器而言是可读的
常见标签:
content:设置或返回meta元素的content属性的值name:把content属性链接到某一个名称
(11)label
作用: 当点击label里面的文字时,浏览器会自动将焦点转移到相关的表单控件之上,一般是将label的for属性与input的id值设置成一样的来进行绑定
使用:
<label for="male">男</label>
<input type="radio" name="sex" id="male" />
(12)title与h1、b与strong、i与em的区别
title属性表示网页的标题,h1元素则表示层次明确的页面内容标题,对页面信息的抓取也有很大的影响
strong是标明重点内容,有语气加强的含义,使用阅读设备阅读网络时:strong会重读,而b是展示强调内容
i内容展示为斜体,em表示强调的文本
(13)前端页面的三层构成
结构层:由HTML或者XHTML之类的标记语言来创建,其语言中的标签对网页的语义做出来描述,但是内容如何显示并不由它负责
表示层:由css来控制,它对如何显示内容做出了回答
行为层:由JS来控制,它来处理内容与事件之间的联系
(14)微格式
说明: 它是建立在已有的、被广泛采用的标准基础之上的一组开放的数据格式,具体表现在把语义嵌入到HTML中,相当于对WEB网页进行语义注解,有助于处理HTML文档的软件更好的理解,一般需要对网站进行SEO优化的话可以考虑使用
(15)HTML5的新特性
- 拖拽释放API
- 语义化标签
- 视频、音频
- 画布
- 本地存储
(16)img的title和alt
说明: 鼠标移动到元素上显示的是title,当图片由于部分原因加载不出来的时候,为了提高图片的可读性,使其展示alt里面的内容
三、CSS部分
(1)BFC
作用: 它是一个独立的布局环境,环境里面跟外面之间互不影响
触发条件:
- float 设置为 left、right
- overflow 设置为 auto、scroll、hidden
- positon 设置为 absolute、fixed
解决问题:
- 外边距垂直方向重合
- 浮动元素令父元素高度坍塌
(2)opacity: 0、visibility: hidden、display: none的区别
结构上看:
display:none会让元素完全从渲染树中消失,渲染的时候不占据任何空间, 不能点击
visibility:hidden不会让元素从渲染树消失,渲染元素继续占据空间,只是内容不可见,不能点击
opacity:0不会让元素从渲染树消失,渲染元素继续占据空间,只是内容不可见,可以点击
继承上看:
display: none和opacity: 0是非继承属性,子孙节点消失由于元素从渲染树消失造成,通过修改子孙节点属性无法显示
visibility: hidden是继承属性,子孙节点消失由于继承了hidden,通过设置visibility: visible;可以让子孙节点显式。
性能上看:
display:none修改元素会造成文档回流,读屏器不会读取display: none元素内容,性能消耗较大
visibility:hidden修改元素只会造成本元素的重绘,性能消耗较少读屏器读取visibility: hidden元素内容
opacity: 0修改元素会造成重绘,性能消耗较少
(3)文本溢出
单行溢出:
// 溢出隐藏
overflow: hidden;
// 溢出部分用...展示
text-overflow:ellipsis;
// 不允许换行
white-space: nowrap;
多行溢出:
// 设置元素为块级弹性box容器
display: -webkit-box;
// 规定box内元素排列方式为垂直方向
-webkit-box-orient: vertical;
// 指定元素显示的文本行数,超过部分省略展示
-webkit-line-clamp: 3;
// 溢出的文本内容进行隐藏处理
overflow: hidden;
(4)居中为什么使用transform
解释: 这是一个合成属性,它在进行动画的时候会创建一个合成层、使得动画元素在一个独立的层中进行动画,一般浏览器会将一个层的内容先绘制到一个位图中去,只要该层的内容不变化,就不会进行重绘,从而优化了性能
(5)粘性布局
作用: 在屏幕范围的时候元素不会收到定位的影响,当元素超出屏幕范围,元素的的定位方式为固定定位
特点:
元素不会脱离文档流,也就是会占位置
元素固定定位时的偏移是相对于最近具有滚动框的祖先元素,如果祖先元素都不可以滚动,则是相对于视口来进行计算的
(6)transition和animation的属性
transition:
transition-property:指定过渡的CSS属性
transition-duration:指定过渡所需的完成时间
transition-timing-function:指定过渡函数
transition-delay:指定过渡的延迟时间
animation:
animation-name:指定要绑定到选择器的关键帧的名称
animation-duration:动画指定需要多少秒或毫秒完成
animation-timing-function:设置动画将如何完成一个周期
animation-delay:设置动画在启动前的延迟间隔
animation-iteration-count:定义动画的播放次数
animation-direction:指定是否应该轮流反向播放动画
animation-fill-mode:规定当动画不播放时,要应用到元素的样式
animation-play-state:指定动画是否正在运行或已暂停
(7)隐藏元素常用方法
css的display属性:
.hidden {
display: none;
}
HTML5新增的hidden属性:
<div hidden>
</div>
(8)PNG图片
说明: PNG图片主要有三个类型,分别为 PNG 8、PNG 24、PNG 32
PNG 8:PNG 8中的8,其实指的是8bits,相当于用2^8大小来存储一张图片的颜色种类,2^8等于256,也就是说PNG 8能存储256种颜色,一张图片如果颜色种类很少,将它设置成PNG 8得图片类型是非常适合的。
PNG 24:PNG 24中的24,相当于3乘以8 等于 24,就是用三个8bits分别去表示 R(红)、G(绿)、B(蓝)。R(0-255),G(0-255),B(0-255),可以表达256乘以256乘以256=16777216种颜色的图片,这样PNG 24就能比PNG 8表示色彩更丰富的图片。但是所占用的空间相对就更大了。
PNG 32:PNG 32中的32,相当于PNG 24 加上 8bits的透明颜色通道,就相当于R(红)、G(绿)、B(蓝)、A(透明)。R(0~255),G(0~255),B(0~255),A(0~255)。比PNG 24多了一个A(透明),也就是说PNG 32能表示跟PNG 24一样多的色彩,并且还支持256种透明的颜色,能表示更加丰富的图片颜色类型。
(9)渐进增强和优雅降级
优雅降级:一开始就构建完整的功能,然后向下进行低版本的兼容
渐进增强:先针对低版本浏览器构建页面,保证其基本的功能,然后针对高级浏览器进行功能的追加来完善用户的体验
(10)@import和link区别
作用上:
@import:只有导入样式表的作用link:不仅可以加载 CSS 文件,还可以定义其它的连接属性
加载顺序上:
@import:引入的 CSS 将在页面加载完毕后被加载link:引入的 CSS 同时加载
兼容性上:
@import:它是CSS2.1 才有的语法,故只可在 IE5+ 才能识别link:没有兼容性问题
(11)常见清除浮动的方式
方法一: 给父级添加overflow:hidden
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Clear Float</title>
<style>
.parent {
overflow: hidden;
border: 1px solid black;
}
.child {
float: left;
width: 100px;
height: 100px;
margin: 10px;
background-color: lightblue;
}
</style>
</head>
<body>
<div class="parent">
<div class="child">Float Left 1</div>
<div class="child">Float Left 2</div>
</div>
</body>
</html>
方法二: 在浮动元素下方添加空div
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Clear Float</title>
<style>
.parent {
border: 1px solid black;
}
.child {
float: left;
width: 100px;
height: 100px;
margin: 10px;
background-color: lightblue;
}
.clear {
clear: both;
height: 0;
overflow: hidden;
}
</style>
</head>
<body>
<div class="parent">
<div class="child">Float Left 1</div>
<div class="child">Float Left 2</div>
<div class="clear"></div>
</div>
</body>
</html>
方法三: 使用伪元素
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Clear Float</title>
<style>
.parent {
border: 1px solid black;
}
.child {
float: left;
width: 100px;
height: 100px;
margin: 10px;
background-color: lightblue;
}
.clearfix::after {
content: "";
display: table;
clear: both;
}
</style>
</head>
<body>
<div class="parent clearfix">
<div class="child">Float Left 1</div>
<div class="child">Float Left 2</div>
</div>
</body>
</html>
(12)选择器权重
结论: !important(∞) > 内联样式(1000) > ID 选择器(100) > 类选择器、伪类选择器、属性选择器(10) > 元素选择器、伪元素选择器(1)
说明: 这个是用来判断样式的优先级的,后面括号里面的代表其选择器的权重值,比较优先级的时候就看谁的值高,谁的优先级就高
注意: 没有10个元素选择器等价于1个类选择器这样的说法,只是按数量比较而已
(13)什么是重绘和重排
重绘:一般元素的外观发生改变,比如颜色的更改
重排:一般是元素的大小、位置发生变化,导致网页需要重新计算布局、重新排列元素
注意: 重排和重绘代价是高昂的,它们会破坏用户体验,并且让UI展示非常迟缓,而相比之下重排的性能影响更大,在两者无法避免的情况下,一般我们宁可选择代价更小的重绘;重绘不一定重排,重排一定重绘
(14)避免重绘重排常用做法
使用 CSS 动画代替 JavaScript 动画:CSS 动画通常比 JavaScript 动画效率更高,可以减少重绘和重排的次数。
使用文档碎片:在 DOM 中频繁插入大量元素时,可以先创建一个文档碎片,将所有要插入的元素添加到文档碎片中,然后一次性将文档碎片插入到文档中,减少重绘和重排次数。
避免触发重排的属性:一些属性的改变会触发重排,如改变元素尺寸、位置等,避免在动画中频繁改变这些属性。
使用 CSS3 属性:CSS3 的一些属性如 transform 和 opacity 不会触发重排,可以更好地优化页面性能。
批量修改样式:如果需要对多个元素进行样式修改,可以将这些修改放在一个类中,然后一次性添加或移除类名,而不是单独对每个元素进行样式修改。
避免频繁操作 DOM:尽量避免频繁对 DOM 进行操作,可以将多次操作合并为一次操作,减少重绘和重排的次数。
(15)图片的优化
可以多个图标文件整合到一张图片中,也就是雪碧图
对于移动端可以采用CDN加载图片,计算出适配屏幕的宽度,然后再去裁剪
装饰类的图片可以使用css来代替
(16)css3新增
- 渐变
- 2d/3d转换
- 过渡与动画
- 背景
- 媒体查询
- 颜色模式
(17)常用的css的性能优化
- 使用id选择器,因为其唯一性所以十分高效
- 避免使用深层次的选择器嵌套
- 使用渐进增强式的css写法
- 不要使用@import
- 避免过多使用重绘重排属性
(18)图片格式
png:是便携式网络图片,一种无损数据压缩位图,优点在于压缩比高,色彩好。 大多数地方都可以用。
jpg:是一种针对相片使用的一种有损的压缩格式,在色调及颜色平滑变化做的不错。常被用来储存和传输照片的格式。
gif:是一种位图文件格式,以8位色重现真色彩的图像。可以实现动画效果。
webp:格式是谷歌在2010年推出的图片格式,压缩率只有 jpg 的2/3,大小比 png 小了45%。缺点是压缩的时间更久了,兼容性不好
四、JavaScript部分
(1)常见的数组去重
使用Set结构:
const arr = [1, 2, 2, 3, 4, 4];
const uniqueArr = Array.from(new Set(arr));
使用filter方法:
const arr = [1, 2, 2, 3, 4, 4];
const uniqueArr = arr.filter(
(value, index, self) => self.indexOf(value) === index
);
(2)箭头函数
特点:
- 只有一个形参就不需要用括号括起来
- 如果函数体只有一行,就不需要放到一个块中
- 如果函数的返回值只有一句代码,就不需要 return 关键字
- 箭头函数没有自己的 this,它只会继承父作用域中的this
与普通函数的区别:
- 首先写法上要简洁很多
- 箭头函数不能使用new关键字,也就不能用于构造函数
- 箭头函数没有自己的this
- 箭头函数没有原型对象
(3)new操作符做的事情
创建一个空对象
将构造函数的原型指向这个空对象
执行构造函数中的代码,为空对象添加属性和方法
如果构造函数没有返回对象,则将这个创建的对象返回出去,如果有返回对象,则将返回的对象返回出去
(4)call、apply、bind
call和apply: 这两个是类似的,它们在调用的时候就会执行,其区别在于传参方式
call(this, arg1, arg2, ...)apply(this, [argsArray])
bind: 它会返回一个新函数,新函数执行的时候才会改变this的指向
bind(this, arg1, arg2, ...)
(5)事件循环
说明: JS中的任务分为同步任务和异步任务,主线程会先执行同步任务,由于JS是单线程的,因此发现异步任务的时候会在任务队列中放置一个事件,这个事件的触发代表任务的运行,之后继续去执行同步任务,当所有同步任务执行完毕后,开始从任务队列中按顺序去执行异步任务,异步任务按照处理时间的长短分为宏任务和微任务,微任务优先执行,宏任务的代表是定时器,微任务的代表是Promsie
(6)闭包
作用: 简单理解就是在内函数中可以访问外函数中的变量
举例:
// 外函数
function outerFunction() {
let outerVariable = "I am from outer";
// 内函数
function innerFunction() {
console.log(outerVariable);
}
// 返回内函数
return innerFunction;
}
const closureFunc = outerFunction();
closureFunc();
(7)null和undefined的区别
undefined:当试图访问不存在或者没有赋值的变量时,就会得到一个undefined
null:而null就表示一个空值或者一个不存在的对象
(8)defer和async的区别
defer:只适用于外部JS文件,这种文件会在页面加载的时候开始下载,加载过程是异步的,在页面加载完毕之后再执行JS文件
async:同样只适用于外部的JS文件,不过文件是立即加载并执行,同样加载过程是异步的,由于立即执行,那么文件的执行顺序就不一定了
(9)原型与原型链
原型:每个对象都有一个称为原型的对象,这个对象定义了该对象共享的属性和方法
原型链:由于每个对象都有自己的原型对象,而原型对象本身也有自己的原型对象,从而形成了一条链状结构,这就是原型链
(10)作用域和作用域链
作用域:它决定了变量的可见性和生命周期,在JS中作用域分为全局作用域和局部作用域,全局作用域是在代码的任何地方都可以访问的作用域,而局部作用域只是在特定代码块内才能访问的作用域
作用域链:当在作用域中访问一个变量的时候,JS会在当前作用域中查找这个变量,没有找到就去它的父作用域中去找,直到找到对应的变量或者到达全局作用域找不到为止
(11)浅拷贝
作用: 将一个对象的第一层的属性复制出来,放到一个新对象里面,此时这两个对象是相关联的,如果对象存在嵌套浅拷贝是不管用的
常见实现方式:
// Object.assign()
let obj = { a: 1, b: { c: 2 } };
let shallowCopy = Object.assign()({}, obj);
// ...操作符
let obj = { a: 1, b: { c: 2 } };
let shallowCopy = { ...obj };
(12)深拷贝
作用: 简单理解就是将一个对象的副本复制一个出来,复制出来的与之前的对象之间没有任何关联
常见实现方式:
// 递归实现
function deepCopy(obj) {
// 如果是基本类型直接返回
if (typeof obj !== "object" || obj === null) {
return obj;
}
// 然后根据数据的类型创建不同的初始对象
let result = Array.isArray(obj) ? [] : {};
// 一直遍历,直到没有属性值不是对象为止
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
result[key] = deepCopy(obj[key]);
}
}
return result;
}
// JSON.parse和JSON.stringify
let obj = { a: 1, b: { c: 2 } };
let deepCopiedObj = JSON.parse(JSON.stringify(obj));
(13)ES6新增
- Promsie
- ...操作符
- let、const关键字
- 模板字符串
- Set和Map结构
- 迭代器和生成器
(14)防抖
作用: 在一段时间内只执行一次操作
简单实现: 利用定时器
// debounce 函数接受两个参数:func 是要执行的函数,
// delay 是延迟时间,即在多长时间内只执行一次。返回
// 的函数在被调用时会设置一个定时器,在延迟时间内如
// 果再次调用这个函数,则会清除之前的定时器,并重新
// 设置一个新的定时器。这样,在延迟时间内如果函数被
// 频繁调用,只有最后一次调用会触发实际执行。
function debounce(func, delay) {
let timerId;
return function () {
const context = this;
const args = arguments;
clearTimeout(timerId);
timerId = setTimeout(function () {
func.apply(context, args);
}, delay);
};
}
(15)节流
作用: 在一次操作执行后,必须隔指定的时间之后,才能触发下一次操作
简单实现: 利用时间戳
// throttle 函数接受两个参数:func 是要执行的函数,
// delay 是时间间隔,即在多长时间内只能执行一次。
// 返回的函数在被调用时会检查距离上次执行的时间间
// 隔是否已经超过设定的间隔时间,如果超过则执行操作,
// 并更新上次执行时间戳。
function throttle(func, delay) {
let lastRunTimestamp = 0;
return function () {
const context = this;
const args = arguments;
const currentTimestamp = Date.now();
if (currentTimestamp - lastRunTimestamp >= delay) {
func.apply(context, args);
lastRunTimestamp = currentTimestamp;
}
};
}
(16)内存泄露与垃圾回收
内存泄露: 程序的运行需要内存,对于持续运行的服务进程,必须及时释放不再使用的内存,否则内存的占用就会越来越高,导致最后内存没了而影响系统的正常运行,也就是说不使用的内存没有及时释放就会造成内存泄露,内存的回收就是垃圾回收,其常用的两种机制为标记清除和引用计数
标记清除: 垃圾回收器在运行的时候给内存中的所有变量加上标记,去掉被使用的变量的标记,那么剩下带有标记的就是需要删除的变量,然后由垃圾回收器删除这些变量并释放它们的内存空间
引用计数: 声明一个变量并将一个引用类型的值赋值给这个变量的时候,这个引用类型的值的引用次数就+1,同一个值赋给另一个变量,其引用也+1,当包含这个引用类型值的变量又被赋值成另外一个值得时候,其引用就会-1,当引用计数为0的时候,就表示无法访问这个值,此时就会被垃圾回收器删除了
(17)变量提升
说明: 在代码的运行过程中,变量和函数声明会被提升到当前作用域的顶部,但是变量的赋值却不会提升,也就是说在代码执行之前,可以在声明之前访问这些变量和函数
(18)严格模式
作用: 它为JS增加一些限制,帮助开发者编写更安全、更严谨的代码,提高JS引擎优化代码的能力,一般在代码文件或者函数开头使用'use strict'表示启用严格模式
"use strict";
// 严格模式下的代码
function myFunction() {
"use strict";
// 严格模式下的代码
}
特点:
- 变量必须先声明后赋值
- 禁止删除变量和函数
- 禁止使用with语句和eval函数
- this会指向undefined
- 禁止使用八进制表示
(19)为什么0.1 + 0.2 != 0.3
解释: 简单理解就是JS中的数字都是会转换成二进制来存储的,一般是用64位二进制数来存储,而有些浮点数转换成二进制的时候会无限循环,而真正需要的只有64位,因此会出现误差,自然也就不会得到想要的值了
(20)map和foreach的区别
返回值:
map():方法会返回一个新的数组,数组中的元素是原始数组经过函数处理后的结果
forEach():方法不会返回任何值,它只是对数组中的每个元素执行指定的函数,但不改变原数组
对原数组的影响:
map():不会改变原数组,它会返回一个新的数组
forEach():也不会改变原数组,但可以在回调函数中修改原数组的值
使用场景:
map():通常用于将一个数组映射到另一个数组,每个元素都能按照指定的函数进行转化
forEach():通常用于对数组中的某个元素执行某些操作
(21)for...in 和 for...of 的区别
遍历对象:
for..in:用于遍历对象的可枚举属性,包括对象自身的属性以及继承的属性
for..of:用于遍历可迭代对象,不过不能用于普通对象的遍历
返回值:
for..in:返回的是属性名字符串for..of:返回的是值本身
遍历顺序:
for..in:不保证属性的遍历顺序,因为对象属性的顺序是不确定的
for..of:按照迭代器顺序依次取值
五、网络部分
(1)建立TCP链接
说明: TCP协议通过三次握手来建立可靠的链接,开始的时候服务器会进入监听状态,然后开始三次握手
第一次:客户端发送syn数据包到服务器,表示客户端想和服务器建立链接
第二次:服务器收到syn数据包之后返回一个syn/ack的数据包给客户端,表示同意客户端的链接请求
第三次:客户端收到服务器的syn数据包之后,返回一个ack的数据包给服务器,等服务器收到这个ack的数据包后,链接建立完毕
(2)关闭TCP链接
说明: 主要通过四次挥手来实现这个过程的,最开始客户端与服务器都能相互传递和接收数据
第一次:客户端发送一个fin的消息给服务器,表示客户端不再发送数据,但是能够接收数据,它在等待一个ack的消息来确认服务器收到关闭的请求
第二次:服务器收到fin的消息后,回复一个ack的消息给客户端,表示收到客户端的关闭请求
第三次:之后服务器也发送一个fin的消息给客户端,表示服务器端也准备关闭链接
第四次:客户端收到服务器的fin消息后,也会发送一个ack的消息表示确认关闭请求,在等待最大报文存活时间之后,关闭链接,而服务器收到客户端返回的ack信息后也会关闭链接,至此链接关闭,释放资源
(3)状态码
301: 表示会缓存重定向的地址,之后会不再重新请求服务器,直接使用缓存的地址请求,这样能够减少请求的次数
302: 表示不会缓存重定向地址,浏览器会继续使用原来的地址进行请求
(4)GET请求和POST请求的区别
浏览器发送GET请求不会携带请求体
GET请求传递的数据有限,但是POST请求则没有限制
GET请求的地址可以被保存为浏览器的书签,但是POST请求不可以
GET请求的参数通过路径参数传递,会暴露在地址栏里面,不安全,但是POST请求不会
刷新页面时55,如果页面通过POST请求得到,那么会提示用户是否重新提交,而GET请求则不会
(5)XXS攻击和CSRF攻击
XXS攻击: 通过对用户输入数据的处理不当而进行的安全漏洞攻击,比如在表单提交的时候在表单内容中添加恶意脚本,这样在浏览页面的时候如果脚本加载完毕,可能会使页面破坏,或者窃取用户的信息
CSRF攻击: 这是一种利用用户已登录的身份进行非用户意愿操作的攻击,比如修改个人信息、转账等
(6)常见的网络性能优化
- 通过defer、async属性,可以让页面尽早的加载JS文件
- 使用CDN可以大幅缩减静态资源的访问时间
- 服务端的文件可以压缩过后再返回给客户端
六、Vue部分
(1)MVVM的理解
理解: 这是一种设计思想,其中M表示数据模型层,它用来定义数据操作和业务逻辑,V表示视图层,它用来将数据模型转换成UI显示出来,这两部分之间没有任何关联,它们通过VM,也就是视图模型层进行交互,M和VM之间的交互是双向的,因此v中数据的变化会同步到M中,而M中数据的更改会反应到V上,由于这样的同步工作完全是自动的,因此开发人员只需要关注业务逻辑,其他的操作交给MVVM来统一管理
(2)Vue的优点
响应式编程: 也就是Vue会自动对页面中的某些数据变化做出反应,这是其最大的优点,以至于让开发人员不再去操作DOM对象,能够有更多的时间去思考业务逻辑了
组件化开发: Vue通过组件将单页应用的各个模块拆分成一个一个单独的组件,然后一个一个的去实现这些组件并将它们拼接起来,一个应用就完成了,这样就提高了项目的可维护性,便于协同开发
虚拟DOM: Vue可以通过JS进行预处理,把真正展示的DOM计算出来并优化,然后将这个计算出来的DOM转换成真实的DOM,由于它没有频繁的去操作真实的DOM,因此其性能、效率上更好,更快
(3)Vue2的生命周期
beforeCreate:当前阶段啥也不能用
created:在实例创建完成后发生,当前阶段可以使用数据,更改数据,这里更改数据不会触发 updated 函数。可以做一些初始数据的获取,在当前阶段无法与 DOM 进行交互,如果非要想,可以通过 vm.$nextTick 来访问 DOM 。
beforeMount:发生在挂载之前,在这之前 template 模板已导入渲染函数编译。而当前阶段虚拟 DOM 已经创建完成,即将开始渲染。在此时也可以对数据进行更改,不会触发 updated。
mounted:在挂载完成后发生,在当前阶段,真实的 DOM 挂载完毕,数据完成双向绑定,可以访问到 DOM 节点,使用 $refs 属性对 DOM 进行操作。
beforeUpdate:发生在更新之前,也就是响应式数据发生更新,虚拟 DOM 重新渲染之前被触发,你可以在当前阶段进行更改数据,不会造成重渲染。
updated:发生在更新完成之后,当前阶段组件 DOM 已完成更新。要注意的是避免在此期间更改数据,因为这可能会导致无限循环的更新。
beforeDestroy:发生在实例销毁之前,在当前阶段实例完全可以被使用,我们可以在这时进行善后收尾工作,比如清除计时器。
destroyed:这里啥都没有了,都被上面销毁了
(4)Vue2响应式原理的理解
说明: Vue在初始化数据的时候,使用Object.defineProperty重新定义data里面的属性,当页面使用到对应的属性的时候,会进行依赖收集,当数据发生变化的时候,就会通知相关的依赖进行更新的操作
(5)Vue3响应式原理的理解
说明: 它使用代理来替代Object.defineProperty来实现,其原因如下:
Object.defineProperty无法监控到数组的下标的变化,导致通过数组下标添加元素不能实时响应
Object.defineProperty只能劫持对象的属性,如果属性是一个对象的话还需要递归遍历去劫持,而代理可以直接劫持一个对象,返回一个新对象
代理不仅可以代理对象,还可以代理数组,同时其存在13种拦截的方法,使其有更多的操作空间
(6)v-model的原理
说明: 默认情况下它是一个value属性和一个input事件的结合,不过对于不同的标签,其属性和事件的结合有不同的组合,自己实现的时候,可以通过model属性的prop和event属性来进行自定义
(7)Vue2的diff算法
主要过程:
同级比较,然后再比较子节点
先判断一方有子节点,一方没有子节点的情况,如果新树的没有,旧树的有,则删除旧节点,如果相反,则进行添加节点就好
如果都有子节点,就使用两端比较的算法开始分析,同时从新旧子节点的两端开始比较,借助key去寻找可复用的节点,再进行更改引用指向、移动等相关的操作,它与react的diff算法相比,同等情况下可以减少节点的移动次数,减少了不必要的性能消耗
之后递归比较子节点,直到全部对比完成
(8)hash模式与history模式的区别
hash模式: #后面的hash值的变化,不会导致浏览器向服务器发送请求来获取页面,从而页面不会刷新,之后通过hashchange事件来监测hash值发生了什么变化,然后根据变化来进行页面更新的操作
history模式: 通过H5新增的pushState和replaceState,这两个API改变Url的时候不会发送请求,从而根据Url的变化进行页面的更新
区别:
在Url展示上面,hash模式存在#,但是history没有
兼容性上,hash模式做的更好
刷新页面的时候,hash模式可能正常加载到hash值对应的页面,但是history模式如果不做处理,通常返回404,一般需要进行重定向操作
(9)v-if和v-show的区别
原理:
v-if:动态的向DOM树中添加和删除DOM元素实现v-show:利用DOM元素的display:none样式实现
编译过程:
v-if:有一个局部的编译/卸载过程,切换过程中合适的销毁和重建内部的事件监听和子组件
v-show:基于简单的css切换
编译条件:
v-if:它是惰性的,如果值为假,就什么也不做,只有条件第一次为真的时候才开始编译
v-show:在任何条件下都会被编译,然后被缓存,并且DOM元素是保留的
性能:
v-if:拥有更高的切换开销,所以适用于需要根据条件动态显示或隐藏DOM元素的场景
v-show:拥有更高的初始化渲染开销,所以它适合频繁切换的场景
原理:
v-if:动态的向DOM树中添加和删除DOM元素实现v-show:利用DOM元素的display:none样式实现
(10)keep-alive
作用: 它是Vue内部的组件,用于缓存其内部组件实例,这样避免创建组件时需要的开销,并同时保留其组件状态,不过它就需要更多的内存给它使用了
属性: 它使用exclude和include来控制那些组件需要被缓存,然后通过max来控制最大的缓存数量,如果超过规定的数量,那么就会移除最久没有使用的组件缓存了
生命周期: 其内部嵌套的组件都具有两个生命周期函数,分别是activated和deactivated,对应组件激活和失活时触发
原理: 其内部维护了一个key的数组和一个缓存对象,key数组用来记录组件的key值,如果没有key值则自动为其生成一个,缓存对象以key值为键,虚拟节点为值,用于缓存组件对应的虚拟DOM,在其渲染函数中,判断当前渲染的虚拟节点是否在缓存中存在,如果有就读取返回,并把当前节点在key数组中的位置移动到数组末尾,这样就能保证它是最新的了,如果没有就将其缓存,当超过max的数值后,就将key数组的第一个值删除即可
(11)Vue中的data为什么是函数
解释: 其原因在于每复用一次组件,就会得到一份新的data,类似给每个组件创建一个私有的数据空间,让每个组件能够维护自己各自的数据,如果写成一个对象的形式,那么所有组件就会共享一份数据,导致一个变化全部变化的结果
(12)computed的原理
说明: 在beforeCreate执行后,Vue会遍历computed里面的所有属性,为每一个属性添加一个watcher对象,并传入一个函数,这个函数的实质就是computed里面配置的取值器getter,这样getter在运行的时候就会开始收集依赖,它和渲染函数的区别在于,这个函数不会立即执行,因为你可能没有使用到,但是考虑计算属性是否会被渲染函数使用,所以在创建watcher的时候,为其添加一个lazy的配置项,这个配置项会决定watcher是否立即执行,收到lazy的影响,watcher还会保留value和dirty这两个属性来实现缓存,value是用来保存watcher运行的结果,由于最开始不会运行,所以初始值是undefined,dirty用来表示当前的value是否是旧值,那么它的初始值就是true了;然后在使用计算属性的时候,判断其对应的watcher是否为旧值,如果不是旧值就运行对应的函数,计算依赖,将其缓存在对应的value中,并将dirty设置为false,表示它是一个新值;当dirty值为false的时候,会直接将这个新值返回,不做其它的事情
注意: 由于收集依赖的时候不仅收集到了计算属性的依赖,还收集到了组件的依赖,当计算属性改变的时候,会先触发计算属性的watcher执行,它只做一件事,就是将dirty的值设置为true,表示value它现在是一个旧值了;之后组件进行重新渲染,重新渲染的时候在模板中又会读到计算属性,因此再一次触发计算属性的watcher,它发现dirty的值为true,那么就会重新执行函数去缓存值,而对于取值器setter,它会直接使用你设置的那个setter
(13)watch和computed的区别
computed有缓存,它依赖的值变化的时候才会重新计算,但是watch不是
watch支持异步,但是computed不支持
(14)methods和computed的区别
在使用时,computed 当做属性使用,而 methods 则当做方法调用
computed 可以具有 getter 和 setter,因此可以赋值,而 methods 不行
computed 无法接收多个参数,而 methods 可以
computed 具有缓存,而 methods 没有
(15)常见性能优化的方法
- 在循环的过程中保证key值得唯一性
- 合理的使用v-if和v-show
- 使用路由懒加载和异步组件
- 图片懒加载
- 防抖、节流
- cdn加载第三方模块
(16)常见首屏加载速度优化方法
请求优化:CDN 将第三方的类库放到 CDN 上,能够大幅度减少生产环境中的项目体积,另外 CDN 能够实时地根据网络流量和各节点的连接、负载状况以及到用户的距离和响应时间等综合信息将用户的请求重新导向离用户最近的服务节点上。
缓存:将长时间不会改变的第三方类库或者静态资源设置为强缓存,将 max-age 设置为一个非常长的时间,再将访问路径加上哈希达到哈希值变了以后保证获取到最新资源,好的缓存策略有助于减轻服务器的压力,并且显著的提升用户的体验
gzip:开启 gzip 压缩,通常开启 gzip 压缩能够有效的缩小传输资源的大小。
http2:如果系统首屏同一时间需要加载的静态资源非常多,但是浏览器对同域名的 tcp 连接数量是有限制的(chrome 为 6 个)超过规定数量的 tcp 连接,则必须要等到之前的请求收到响应后才能继续发送,而 http2 则可以在多个 tcp 连接中并发多个请求没有限制,在一些网络较差的环境开启 http2 性能提升尤为明显。
懒加载:当 url 匹配到相应的路径时,通过 import 动态加载页面组件,这样首屏的代码量会大幅减少,webpack 会把动态加载的页面组件分离成单独的一个 chunk.js 文件
预渲染:由于浏览器在渲染出页面之前,需要先加载和解析相应的 html、css 和 js 文件,为此会有一段白屏的时间,可以添加loading,或者骨架屏幕尽可能的减少白屏对用户的影响体积优化
合理使用第三方库:对于一些第三方 ui 框架、类库,尽量使用按需加载,减少打包体积
提高代码使用率:利用代码分割,将脚本中无需立即调用的代码在代码构建时转变为异步加载的过程
封装:构建良好的项目架构,按照项目需求就行全局组件,插件,过滤器,指令,utils 等做一 些公共封装,可以有效减少我们的代码量,而且更容易维护资源优化
图片懒加载:使用图片懒加载可以优化同一时间减少 http 请求开销,避免显示图片导致的画面抖动,提高用户体验
使用 svg 图标:相对于用一张图片来表示图标,svg 拥有更好的图片质量,体积更小,并且不需要开启额外的 http 请求
压缩图片:可以使用 image-webpack-loader,在用户肉眼分辨不清的情况下一定程度上压缩图片
(17)Vue2和Vue3的部分区别
- Vue3使用ts进行重写
- Vue3的响应式原理通过Proxy实现
- 使用setup函数替代beforeCreate和Created两个生命周期
- Vue3支持多个<script />
- Vue3不存在this