面试一般问题分为3部分:1.八股文 2.项目问题 3.手写代码
说明:本篇文章根据b站小姐姐的面试问题进行总结【前端】互联网大厂前端面试问什么?掌握这些最最最精髓问题,大厂实习不是梦!
1.八股文
html:
1.flex布局
- flex布局(常问:用法,有哪些属性,可能当场给出图片让写布局);
-
原理总结:通过给父盒子添加flex属性,来控制子盒子的位置和排列方式。
-
flex 布局父项常见属性:
-
flex-direction:设置主轴方向,row/row-reverse/column/column-reverse
-
justify-content:设置主轴子元素排列方式,flex-start/flex-end/center/space-around/space-between
-
flex-wrap:设置子元素是否换行,默认不换行,若父盒子一行上装不开,则会缩小子元素的宽度,从而仍然一行显示。nowrap/wrap/wrap-reverse
-
align-items :设置侧轴上的子元素排列方式(单行)。flex-start/flex-end/center/strech默认
-
align-content:设置侧轴上的子元素的排列方式(多行),只能用于子项出现换行的情况(多行)。flex默认/flex-end/center/space-around/space-between/strech
-
flex-flow:是
flex-direction
和flex-wrap
属性的复合属性,flex-flow: row wrap;
-
-
flex 布局子项常见属性
- flex :定义子项目分配剩余空间,用 flex 表示占多少份数,值可以是整数/百分数。
- align-self :控制子项自己在侧轴上的排列方式,允许单个项目有与其他项目不一样的对齐方式,可覆盖 align-items 属性。auto/strech/center/flex-start/flex-end
- order: 定义项目的排列顺序。数值越小,排列越靠前,默认为 0。
2.选择器
- 选择器相关知识;
-
基础选择器
- 标签选择器:标签名
- 类选择器:使用
class
属性来调用 class 类;.class-name1{} - id选择器:只能允许一个标签调用;#id名{}
- 通配符选择器:选取页面中所有标签;*{}
-
复合选择器
- 后代选择器:元素1 元素2 {}
- 子选择器:亲儿子;元素1 >元素2{}
- 并集选择器:用于集体声明;元素1,元素2{}
- 伪类选择器:用于向某些选择器添加特殊的效果
- 链接伪类选择器:a:link/visited/hover/active
- focus伪类选择器:获取焦点的表单元素;input: focus {background-color: yellow;}
- 其他标准伪类选择器::first-child/:last-child/:nth-child(an+b)/:not§/::after 用来创建一个伪元素/::before
-
3.head标签
- html文件head标签常见的标签,如:meta script title style link;
- title标签:定义网页的标题。
- meta标签:一般用于定义页面的特殊信息,例如页面的关键字、页面描述等
- link标签:用于引入外部样式文件(CSS 文件)
- style标签:用于定义元素的CSS样式。
- script标签:用于定义页面的JavaScript代码,或者引入外部JavaScript文件。
4.script标签属性
- script标签内的属性,defer async异步属性常问;来源
- src:定义引用外部脚本的URI,这可以用来代替直接在文档中嵌入脚本。指定了 src 属性的script元素标签内不应该再有嵌入的脚本。
- type:定义script元素包含或src引用的脚本语言。属性的值为MIME类型
- async:指示浏览器是否在允许的情况下异步执行该脚本。该属性对于没有src属性的脚本不起作用。
- defer:被设定用来通知浏览器“该脚本将在文档完成解析后,触发 DOMContentLoaded 事件前执行”。如果无src,则不起作用。
- 不管这段脚本放在html的何处(即使head中),都会等待dom解析完成后再去加载,如果将script标签放在整个html文件的最后,那就不需要defer了。
- async和defer的区别:defer要等到整个页面正常渲染结束,才会执行;async是在渲染html时发现 脚本已经异步下载完,就去执行,执行完了,再继续往下渲染html。
- crossorigin:添加crossorigin属性来获取跨站文件的错误信息
- integrity:提供hash值,来验证览器获得的资源(例如从 CDN 获得的)是否被篡改。
5.canvas
-
canvas相关(会不会用,了解它的哪些属性,能够使用到什么程度)
-
是 HTML5 新增的,一个可以使用脚本(通常为 JavaScript) 在其中绘制图像的 HTML 元素。它可以用来制作照片集或者制作简单(也不是那么简单)的动画,甚至可以进行实时视频处理和渲染。
-
属性:width/heigh
css:
1.display、visibility区别
- display:none visibility:hidden区别,是否触发重绘重排;
-
元素的显示与隐藏
- display 属性:none/block;隐藏元素后,不再占有原来的位置。
- visibility属性:hidden/visible;隐藏元素后,继续占有原来的位置。
- overflow 属性:visible/hidden/scroll/auto;指定了如果内容溢出一个元素的框(超过其指定高度及宽度)时,会发生什么。
-
两者区别:区别
-
重绘重排:重排和重绘
- display: none;/* 1重排 2不会被子元素继承,但是父元素都不在了,子元素自然也就不会显示了 3无法触发绑定的事件 4transition无效 */
- visibility: hidden;/* 1重绘 2会被子元素继承,可以通过设置子元素visibility: visible 使子元素显示出来 3无法触发绑定的事件 4transition无效 */
- opacity: 0;/* 1重绘 2也会被子元素继承,但是不能通过设置子元素opacity: 1使其重新显示 3可以触发绑定的事件 4transition有效 */
-
2.垂直居中
-
如何实现垂直居中(定位+平移,flex,一般需要说出2钟及以上方法);css实现水平/垂直居中效果 - 逍遥游 - 博客园 (cnblogs.com)
-
1.table表格法:显示设置父元素为:table,子元素为:cell-table,vertical-align: middle;文字text-align: center;
-
2.空元素法:在父元素里放一个空标签span,设置他的vertical-align: middle; 宽度为0
-
3.-50%定位法:子元素绝对定位,距离顶部 50%,左边50%,然后使用css3 transform: translate(-50%; -50%)
-
4.flex布局法:父盒子display: flex; justify-content: center; align-items: center;
-
5.绝对定位法:父元素使用定位(相对/绝对都行),子元素设置position: absolute; top: 0; left: 0; bottom: 0; right: 0; margin: auto;
-
外边距可以让块级盒子 水平居中,但是必须满足两个条件:盒子必须指定宽度(width);盒子左右的外边距都设置为 auto。 使行内元素或行内块元素水平居中
text-align: center;
-
-
3.定位
- 定位(属性和用法,如粘性定位的使用场景);
-
定位:将盒子定在某一个位置,所以定位也是在摆放盒子,按照定位的方式移动盒子。定位=定位模式(position=fixed)+边偏移(top/bottom/left/right)。
-
定位模式:
- 静态定位static:默认定位方式,无定位。
- 相对定位relative:相对于它原来的位置来移动,不脱标
- 绝对定位absolute:相对于它祖先元素来移动,脱标。如果没有祖先元素或者祖先元素没有定位,则以浏览器为准定位( Document 文档)。子绝父相
- 固定定位fixed:以浏览器的可视窗口为参照点移动元素,不随滚动条滚动,脱标。固定在版心右侧位置(让固定定位的盒子 left: 50%, 再margin—left:板心宽度的一半距离)
- 粘性定位sticky:可以被认为是相对定位和固定定位的混合。以浏览器的可视窗口为参照点移动元素(固定定位特点);粘性定位占有原先的位置(相对定位特点);必须添加 top, left, right, bottom 其中一个才有效跟页面滚动搭配使用。使用场景:侧边栏
-
定位叠放次序z-index:可控制盒子的前后次序,有定位的盒子才有此属性
-
- clear作用:清除浮动;
- 为什么需要清楚浮动:父级盒子很多情况下,不方便给高度,子盒子浮动又不占有位置,就会影响下面的盒子,对后面元素排版产生影响。
- clear:选择器: {clear: both;};弊端—margin失效;清除浮动策略—闭合浮动
- 清除浮动方法:
- 额外标签法(隔墙法):在最后一个浮动元素末尾添加一个空块级元素,给其赋以属性 clear: both;
- 父级添加 overflow:将其属性值设置为 hidden、auto或scroll;缺点—无法显示溢出部分
- :after 伪元素法:也是额外标签法的一种
- 双伪元素法
4.盒子模型
- 盒子模型(两种盒模型和区别,以及使用场景)参考
- 1.W3C标准盒模型:box-sizing:content-box(默认);当我们对一个元素设置他的width和height的时候,标准盒模型只是对content(蓝色部分)设置了宽高,这个元素真正的宽高就还要加上他的padding(内边距)border(边框)margin(外边距)
- 2.IE盒模型(怪异盒模型):box-sizing: border-box;当我们对一个元素设置他的width和height的时候,怪异盒模型把整个盒子看成是一个整体。给整个盒子一个宽高。如果还给盒子设置了额外的边距和边框。那么中间的content蓝色部分就要受到挤压,变小。
- 注意:css的盒模型由content(内容)、padding(内边距)、border(边框)、margin(外边距)组成。但盒子的大小由content+padding+border这几部分决定,而不加上margin。
- 注意:在编写页面代码时应尽量使用标准的W3C模型(需在页面中声明DOCTYPE类型),这样可以避免多个浏览器对同一页面的不兼容。因为若不声明DOCTYPE类型,IE浏览器会将盒子模型解释为IE盒子模型,FireFox等会将其解释为W3C盒子模型;若在页面中声明了DOCTYPE类型,所有的浏览器都会把盒模型解释为W3C盒模型。
- 使用场景:框架想要具备栅格系统,肯定要用border-sizing
js:
1.闭包
-
闭包(描述什么是闭包,闭包的优点,缺陷,如何解决缺陷);学习Javascript闭包 阮一峰的网络日志 (闭包的缺点与解决办法_zihanzy.com的博客
-
闭包(closure):指有权访问另一个函数作用域中变量的函数。(–JavaScript 高级程序设计)
-
闭包作用:延伸变量的作用范围;让这些变量的值始终保持在内存中
-
缺陷:由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
-
解决办法:1.能不用闭包就不用2.及时释放
var f = fn1() f() f = null //让内部函数成为垃圾对象,从而回收闭包
-
2.继承
- 继承(掌握每一种继承的手写代码);js继承的6种方式 - ranyonsue - 博客园 (cnblogs.com)
3.原型链
- 原型链(描述什么是原型链,如何访问原型);
- 定义:当访问一个对象的某个属性时,会先在这个对象本身属性上查找,如果没有找到,
_proto_
隐式原型上查找,即它的构造函数的prototype,如果还没有找到就会再在构造函数的prototype的_proto_
中查找,这样一层一层向上查找就会形成一个链式结构,我们称为原型链。 - 获取实例对象obj的原型对象,有三种方法:
obj.__proto__
obj. constructor.prototype
Object.getPrototypeOf(obj)
- 定义:当访问一个对象的某个属性时,会先在这个对象本身属性上查找,如果没有找到,
4.变量提升
- let const var(作用域相关考点,变量提升相关考点); lyyo_cd的博客-CSDN博客
- 什么是变量提升:JavaScript 中,函数及变量的声明都将被提升到函数的最顶部。变量可以在使用后声明,也就是变量可以先使用再声明。
- var声明变量存在变量提升,let和const不存在变量提升
- let、const都是块级局部变量
- const 的特性和 let 完全一样,不同的只是,const声明时候必须赋值;只能进行一次赋值,即声明后不能再修改;如果声明的是复合类型数据,可以修改其属性
- 同一作用域下let和const不能声明同名变量,而var可以
5.基本数据类型
- 基本数据类型(手写判断数据类型的方法);判断JS数据类型的四种方法
- 数据类型:基本类型:String、Number、Boolean、Symbol、Undefined、Null ;引用类型:Object,还包括 Function 、Array、RegExp、Date 等
- 判断方法:
- typeof :是一个操作符,其右侧跟一个一元表达式,并返回这个表达式的数据类型。返回的结果用该类型的字符串(全小写字母)形式表示,包括以下 7 种:number、boolean、symbol、string、object、undefined、function 等。
- instanceof :是用来判断 A 是否为 B 的实例,表达式为:A instanceof B,如果 A 是 B 的实例,则返回 true,否则返回 false。 在这里需要特别注意的是:instanceof 检测的是原型。instanceof 只能用来判断两个对象是否属于实例关系, 而不能判断一个对象实例具体属于哪种类型。
- constructor:当一个函数 F被定义时,JS引擎会为F添加 prototype 原型,然后再在 prototype上添加一个 constructor 属性,并让其指向 F 的引用。
- toString() :是 Object 的原型方法,调用该方法,默认返回当前对象的 [[Class]] 。这是一个内部属性,其格式为 [object Xxx] ,其中 Xxx 就是对象的类型。
6.数组
6.1(不)改变数组的方法
- 数组的一些方法,哪些能改变,哪些不能改变数组;发呆的薇薇°的博客-CSDN博客
- 改变数组的方法
- push() :向数组的 末尾添加 一个或多个元素,并返回新的长度
- pop(): 删除数组 的 最后一个 元素并返回删除的元素
- shift() : 删除 并返回数组的第一个 元素
- unshift() :向数组的 开头 添加一个或多个 元素,并返回新的长度
- splice() :用于向数组中 插入、删除或替换 数组里的元素
- reverse() :用于反转数组的元素排序
- sort() :对数组的元素进行 排序,排序顺序可以是字母或数字,升序或降序;默认按 字母升序 排列
- forEach() :调用数组的每个元素,并将元素传递给回调函数;对空数组不会执行回调。语法
array.forEach(function(item,index,arr),thisValue)
- 不改变原数组的方法
- filter() :创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。它不会对空数组进行检测。语法:
array.filter(function(item,index,arr),thisValue)
- concat() :连接于连接两个或多个数组,并返回结果;
该方法没有改变现有的数组,但是会返回连接两个或多个数组链接的副本。语法:array1.concat(array2,array3,...,arrayX)
- slice() : 选取数组的一部分,并返回一个新数组
该方法不会改变元素数组,而是将截取到的元素封装到一个新数组中返回。语法:array.slice(start,end)
- join() :通过指定的 分隔符 将数组中的元素进行分割并转换成一个字符串
- map() :通过指定函数处理数组的每个元素,并返回处理后的数组;不会对空数组进行检测。语法:
array.map(function(item,index,arr),thisValue)
- every():检测数组元素的 每个元素 是否都符合 条件(通过函数提供),不会对空数组进行检测。如果数组中检测到有一个元素不满足,则整个表达式返回false,且剩余的元素不会再进行检测。如果所有元素都满足条件,则返回 true。
- some():检测数组元素中是否有元素符合 指定条件(函数提供),会依次执行数组的每个元素, some()不会对空数组进行检测。如果有一个元素满足条件,则表达式返回true , 剩余的元素不会再执行检测。如果没有满足条件的元素,则返回false。
- indexOf():搜索数组中的元素,并返回它所在的位置。从头到尾地检索数组,看它是否含有对应的元素,开始检索的位置在数组start处或数组的开头(没有指定 start 参数时)。如果找到一个 item,则返回 item 的第一次出现的位置。开始位置的 索引为0,如果在数组中没找到 指定元素,则返回 -1。
- filter() :创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。它不会对空数组进行检测。语法:
- 改变数组的方法
6.2数组去重
-
数组去重; MomentYY - 博客园
-
1.利用Set()+Array.from():
-
const result = Array.from(new Set(arr))
。Array.from() 方法:对一个类似数组或可迭代对象创建一个新的,浅拷贝的数组实例。 -
`let arr1 = [1, 2, 2, 3, 3, 3, 4, 1, 2]; let res1 = [...new Set(arr1)]; //集合转为数组:[...st],这里st是一个集合 console.log(res1); // [ 1, 2, 3, 4 ]`
-
-
2.利用两层循环+数组的splice方法:
- 通过两层循环对数组元素进行逐一比较,然后通过splice方法来删除重复的元素。此方法对NaN是无法进行去重的,因为进行比较时
NaN !== NaN
。
- 通过两层循环对数组元素进行逐一比较,然后通过splice方法来删除重复的元素。此方法对NaN是无法进行去重的,因为进行比较时
-
3.利用数组的indexOf方法:
- 新建一个空数组,遍历需要去重的数组,将数组元素存入新数组中,存放前判断数组中是否已经含有当前元素,没有则存入。此方法也无法对NaN去重。
-
4.利用数组的includes方法:
- 此方法逻辑与indexOf方法去重异曲同工,只是用includes方法来判断是否包含重复元素。
- includes()方法:用来判断一个数组是否包含一个指定的值,根据情况,如果包含则返回 true,否则返回 false。
-
5.利用数组的filter()+indexOf():
- filter方法会对满足条件的元素存放到一个新数组中,结合indexOf方法进行判断。
-
6.利用Map():
- Map对象是JavaScript提供的一种数据结构,结构为键值对形式,将数组元素作为map的键存入,然后结合has()和set()方法判断键是否重复。
-
7.利用对象:
- 其实现思想和Map()是差不多的,主要是利用了对象的属性名不可重复这一特性。
-
6.3判断数组
- 判断数组的方法(主要是考Array.prototype.toString);一蓑烟雨~~的博客-CSDN博客;DOM曼珠沙华的博客-CSDN博客
- 通过instanceof判断:instanceof运算符用于检验构造函数的prototype属性是否出现在对象的原型链中的任何位置,返回一个布尔值
- 通过constructor判断:实例的构造函数属性constructor指向构造函数,那么通过constructor属性也可以判断是否为一个数组
- 通过Object.prototype.toString.call()判断:可以获取到对象的不同类型,不仅仅可以检验是否为数组,比如是否是一个函数,是否是数字等等
- 通过Array.isArray()判断:用于确定传递的值是否是一个数组,返回一个布尔值
6.4数组循环
- 数组循环的方法(map foreach for in for of);Naynehcs - 博客园 ;https://www.jb51.net/article/71814.htm
- for循环:
- for遍历数组索引,如果数组中存在空元素,也会执行
- 可以使用return、break、continue跳出或中断循环
- forEach:
- 可以接收三个参数=> item:数组当前项的值,index:数组当前项的索引,arr:数组对象本身。
- forEach无法跳出循环(return、break、continue不起作用)
- for … of:
- for … of 与for一样,如果遇到空元素同样会执行。
- 和for一样可以使用return、break、continue终止循环
- filter:
- 可以接收三个参数=> item:数组当前项的值,index:数组当前项的索引,arr:数组对象本身。
- filter配合return返回符合条件的新数组元素不可自定义,不会改变原数组,数组长度和原数组不同
- map:
- 可以接收三个参数=> item:数组当前项的值,index:数组当前项的索引,arr:数组对象本身
- 有返回值,可以return出来
- map返回新的数组元素可自定义,不会改变原数组,数组与原来长度一致
- some:
- 可以接收三个参数=> item:数组当前项的值,index:数组当前项的索引,arr:数组对象本身
- 配合return使用,返回布尔值,某一元素满足条件返回true,循环中断,只有所有元素都不满足条件才返回false
- every:
- 可以接收三个参数=> item:数组当前项的值,index:数组当前项的索引,arr:数组对象本身
- 配合return使用,返回布尔值,与some相反,某一元素不满足条件返回false,循环中断,只有所有元素满足条件才返回true
- find:
- 可以接收三个参数=> item:数组当前项的值,index:数组当前项的索引,arr:数组对象本身
- 配合return使用,返回第一个满足条件的元素值,如果不存在返回undefined
- findIndex:
- 可以接收三个参数=> item:数组当前项的值,index:数组当前项的索引,arr:数组对象本身
- 配合return使用,用于找出第一个符合条件的数组成员位置(索引),如果没有找到返回-1
- reduce:
- 方法接收两个参数,第一个回调函数(callback),第二个是初始值
- for循环:
7.parseInt
- parseInt的参数个数(主要考点就是第二个参数是进制);iKendall的博客-CSDN博客;[解析 1, 2, 3].map(parseInt)【JS面试题】
- parseInt(string,radix) 函数可解析一个字符串,并返回一个整数。当参数 radix 的值为 0,或没有设置该参数时,parseInt() 会根据 string 来判断数字的基数。
- radix:可选。表示要解析的数字的基数。该值介于 2 ~ 36 之间。
8.ES6新语法
- 知不知道ES6有哪些新语法;小北lulu的博客-CSDN博客
- 解决原有语法上的一些问题或不足(比如let,const)
- var 存在变量提升,let 不存在;let在同一个作用域下不可以重复定义同一个变量值,而var可以;有严格的作用域,var属于函数作用域,let属于块级作用域
- const 声明的变量为只读的,一旦声明,常量的值就不能改变;声明的变量一定要初始化,不能只声明不赋值;声明的变量只在块级作用域内有效
- 对原有语法进行增强,更加易用(比如解构,展开,参数默认值,模板字符串)
- 数组的解构
- 对象的解构
- 模板字符串:用反引号来包裹起来字符串: ``;支持换行;${}中可以使用函数表达式,返回最终值
- 字符串的扩展方法:startsWith() 判断是否以某个字符开头;endsWith()判断是否以某个字符结尾;includes()判断是否包含某个字符
- 参数默认值
- 展开运算符(…):合并数组;代替apply;浅拷贝
- 箭头函数:箭头函数不会改变this的指向
- 对象字面量
- Object.assign():用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target),如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性覆盖前面的属性;还可用于对象的浅拷贝
- Proxy:在目标对象的外层搭建了一层拦截,外界对目标对象的某些操作,必须通过这层拦截
- Reflect用法:为操作对象而提供的新API,将Object对象的属于语言内部的方法放到Reflect对象上,即从Reflect对象上拿Object对象内部方法,比较方便,可读性更强。
- 全新的对象,全新的方法,全新的功能(promise)
- 全新的数据类型和数据结构(symbol,Set,Map)
- 解决原有语法上的一些问题或不足(比如let,const)
9.ES6模块化
- ES6模块化的基本使用(常问,有哪些使用方式,怎么引入/导出,有什么区别);博客
- 定义:模块化是指将一个大的程序文件,拆分成许多小的文件,然后将小文件组合起来。
- 优势:防止命名冲突;代码复用;高维护性
- 方法一(模块化语法):主要由两个命令构成:
export
和import
- 模块导出数据语法:单个导出/合并导出/默认导出
- 模块导入数据语法:通用导入/解构赋值导入/简便方式导入,针对默认暴露
- 方法二:将文件导入都写进一个 app.js 文件中,然后在里面写入要导入的模块,在 index.html 中引入 app.js 文件内容。
- 两种方法的区别
10.垃圾回收机制
11.箭头函数
- 箭头函数和普通函数的区别;少油少盐不要辣的博客-CSDN博客
- 1.this(执行上下文)指向
- 2.构造函数
- 3.arguments对象
- 4.隐式return
- 5.当作为回调方法去使用时
- 6.注意点
12.map weakmap set weakset区别
- map weakmap set weakset区别。_IT入门; touryung - 博客园
浏览器(计网):
1.http
- http1.1、http2区别;球意迹的博客-CSDN博客_http1.1
- Http1.0:请求一次,连接自动断开
- Http1.1:一次连接,可以发起多次请求
- http2.0:
- 多路复用:HTTP2.0使用了多路复用的技术,做到同一个连接并发处理多个请求,而且并发请求的数量比HTTP1.1大了好几个数量级
- 数据压缩:HTTP1.1不支持header数据的压缩,HTTP2.0使用HPACK算法对header的数据进行压缩,这样数据体积小了,在网络上传输就会更快
- 服务器推送:意思是说,当我们对支持HTTP2.0的web server请求数据的时候,服务器会顺便把一些客户端需要的资源一起推送到客户端,免得客户端再次创建连接发送请求到服务器端获取。这种方式非常合适加载静态资源
2.浏览器缓存
- 浏览器缓存全过程,强缓存协商缓存字段有哪些,优先级,http状态码;foolBirdd的博客-CSDN博客_;CSDN资讯的博客-CSDN博客
- 缓存流程:
- 第一次请求需要的资源,服务器返回资源的同时在 response hearder 响应头中添加了缓存策略,告诉浏览器缓存规则(比如以何种方式缓存,缓存信息…),此时就进行缓存了
- 第二次如果是请求相同资源,那么就会检查缓存里面是否有相应资源,有的话直接取用,具体方式请看后续
- 强缓存:检查强缓存,不发送 http 请求直接从缓存里读取资源。一般强缓存都会设置有效时间,过期就失效
- Cache-Control:
- public:响应可以被客户端和代理服务器缓存
- private(默认取值):响应只有客户端可以缓存
- no-cache:直接进入协商缓存阶段
- no-store:不进行任何缓存
max-age = xxx(xxx 代表数字):缓存内容在 xxx 时间后失效,单位为秒 - must-revalidate:如果缓存失效,必须校验正确后才能使用,某些特殊情况客户端是可以使用过期缓存的,比如校验请求发送失败的时候
- Expires:一个 GMT 格式的时间字符串(时间戳)。服务器返回该请求结果缓存的到期时间,再次发送请求时,如果未超过则直接使用缓存。缺点是判断是否过期用的是本地时间,本地时间可以自己修改
- Pragma:取值为 no-cache,等同 Cache-Control 取值 no-cache
- Cache-Control:
- 协商缓存:需要携带缓存标识(tag)发送 http 请求,由服务器判断是否使用缓存。服务端会进行判断,若资源已发生变化,则返回新资源,否则告诉浏览器启用缓存即可
- 触发条件(两个):强缓存过期;Cache-Control 的值包含 no-cache
- Last-Modified 返回资源文件在服务器最后的修改时间。浏览器再次请求时,If-Modified-Since 携带上次 Last-Modified 的值,到服务端与最后被修改的时间做对比,若时间小于服务端最后修改时间,则代表资源已变更,重新返回资源,状态码为 200,反之状态码为 304,代表缓存可用
- ETag 返回当前文件的一个唯一标识符(服务器生成),再次请求时 If-None-Match 会携带 Etag 的值,与服务端的 Etag 值比较,若不一致,则返回新资源,状态码为 200;反之则继续使用缓存,状态码为 304
- 缓存流程:
3.浏览器存储
- 浏览器储存(localstorage sessionStorage cookie区别及使用,不仅要知道概念,还要知道代码怎么写,自己要动手实践);小贤笔记的博客-CSDN博客
- localStorage: localStorage 的生命周期是永久的,关闭页面或浏览器之后 localStorage 中的数据也不会消失。localStorage 除非主动删除数据,否则数据永远不会消失
- sessionStorage: sessionStorage 的生命周期是仅在当前会话下有效。sessionStorage 引入了一个“浏览器窗口”的概念,sessionStorage 是在同源的窗口中始终存在的数据。只要这个浏览器窗口没有关闭,即使刷新页面或者进入同源另一个页面,数据依然存在。但是 sessionStorage 在关闭了浏览器窗口后就会被销毁。同时独立的打开同一个窗口同一个页面,sessionStorage 也是不一样的
遇到js,css文件阻塞问题(基于此问async defer区别) - cookie: cookie生命期为只在设置的cookie过期时间之前一直有效,即使窗口或浏览器关闭。 存放数据大小为4K左右, 有个数限制(各浏览器不同),一般不能超过20个。缺点是不能储存大数据且不易读取
- localStorage 和 sessionStorage 都具有相同的操作方法,例如 setItem()、getItem() 和 removeItem() 等
4.文件阻塞
- js,css文件阻塞的问题,浏览器是怎么处理js,css这些引入文件的,基于此问async和defer异步下载文件的区别小凳子腿的博客-CSDN博客;贾顺名 - 博客园 ;async和defer的作用和区别 ;
- 浏览器渲染网页阻塞顺序
- 1:构建DOM树时,如遇到JS元素时,会阻塞DOM树和CSS规则树的构建,优先执行JS文件
- 2:构建DOM树时,如遇到CSS元素时,会开启异步请求线程,该线程会先下载CSS文件,再构建CSS规则树,该线程会阻塞JavaScript引擎线程,但不会阻塞DOM树的构建
- 3:CSS解析和JS解析互斥,也就是说JS解析时会阻塞CSS解析而CSS解析时也会阻塞JS解析
- 4:JS解析时,如果JS还操作了CSS,而这个CSS还没有下载或构建解析,则会延迟执行JS,直到完成CSS下载构建解析,再会继续执行JS
- 当遇到JS时:
- 渲染引擎会停止执行,控制权交给JS引擎,当执行JS代码时
如果遇到获取DOM,那么如果该DOM还没有解析,则会获取为null,如果JS代码还操作了CSS,而这个CSS如果还没有下载和构建,那么浏览器首先会阻塞JS引擎执行,然后会开启一个异步请求线程,在该线程上,去下载构建CSS规则树,CSS规则树构建完成后,再继续执行JS代码,当JS执行完以后,控制权再次交给渲染引擎去执行。
- 渲染引擎会停止执行,控制权交给JS引擎,当执行JS代码时
- 当遇到CSS元素时:
- 也会开启异步线程,去下载构建CSS规则树,但同时也会继续构建后面的DOM树,也就是说DOM解析和CSS解析可以同时进行,但如果后面遇到JS元素,则会阻塞JS引擎线程执行,后面DOM树解析不受影响。
- async和defer的区别:
- defer:用于开启新的线程下载脚本文件,并使脚本在文档解析完成后执行。
- async:用于异步下载脚本文件,下载完毕立即解释执行代码。
- 浏览器渲染网页阻塞顺序
5.浏览器输入url的过程
- 浏览器输入url后的全过程;小凳子腿的博客-CSDN博客
- 1:根据网址进行DNS解析,将相应的域名解析为IP地址
- 2:客户端根据IP地址去寻找对应的服务器并进行TCP三次握手,建立TCP连接
- 3:客户端发起HTTP请求,请求对应资源
- 4:服务器响应并返回相应数据(如:HTML文件)
- 5:浏览器将获取的HTML文档由HTML解析器解析成DOM树
- 6:同时由CSS解析器将CSS样式解析成CSS Rule Tree(CSS规则树)
- 7:将生成的DOM树和CSS规则树合并生成Rendering Tree(渲染树)
- 8:根据渲染树,在屏幕上对元素进行布局
- 9:根据渲染树,将各个元素绘制到屏幕上
- 10:客户端与服务器进行TCP的四次挥手
6.TCP和UDP区别
- tcp udp区别,什么是队头阻塞;技术博客;什么是队头阻塞以及如何解决 ;TCP和UDP的区别
- 区别
- TCP是面向连接的,UDP是面向无连
- TCP是可靠的,UDP是不可靠的
- TCP是面向字节流的,UDP是面向报文的
- TCP只有一对一的传输方式,而UDP不仅可以一对一,还可以一对多,多对多
- UDP的头部开销小,TCP的头部开销大
- TCP会产生粘包问题,UDP会产生丢包问题
- 队头阻塞
- TCP协议下每个数据包都有唯一的序号,协议能够保证这些包的可靠、按顺序传输。但如果多个包中某个序号比较靠前的在传输过程中发生了丢包,其它序号靠后的包即使已顺利到达,也需要在接收方的缓冲区中等待,直到队头包重传成功才能将报文组装并返回给应用层。
- TCP中的队头阻塞的产生是由TCP自身的实现机制决定的,无法避免。想要在应用程序当中避免TCP队头阻塞带来的影响,只有舍弃TCP协议。
- 区别
其它:
1.promise
- promise常用的一些方法,promise.all 、promise.race手写;
- 常用方法
- Promise.all
- Promise.any
- Promise.race
- Promise.allSettled
- 常用方法
2.路由相关
- 路由相关,history和hash的区别(常问),仔细了解原理和用法;history路由和hash的区别 ;单页应用到底该用hash模式还是history模式;哈希路由(hash模式)和历史路由(history模式)的区别 ;单页面应用history路由实现原理
- 区别:
- hash模式原理:在 url 中的 # 之后对应的是 hash 值, 其原理是通过hashChange() 事件监听hash值的变化, 根据路由表对应的hash值来判断加载对应的路由加载对应的组件
- history原理:运用了浏览器的历史记录栈,之前有back,forward,go方法,之后在HTML5中新增了pushState()和replaceState()方法,它们提供了对历史记录进行修改的功能,不过在进行修改时,虽然改变了当前的URL,但是浏览器不会马上向后端发送请求。
- 区别:
3.跨域问题
-
跨域问题,常问 cors、jsonp,主要还是回答cors,设置了Access-Control-Allow-Origin头字段*后,无法携带cookie,如何解决:跨域请求CORS和jsonp
-
答案1:
-
当使用ajax发送一个简单请求,会在请求头中增加一个Origin头信息,指定该请求发送方的域, 用于提交给服务器判断是否接受该源跨域请求,如果服务器同意该跨域访问,正常返回数据,并在响应头信息中携带添加Access-Control-Allow-Origin头信息,值为Origin也就是发送方的域信息,这个头信息旨在告诉浏览器服务器同意了其他域访问自己,浏览器可以将该返回值返回给请求方而不要拦截。如果服务器返回的信息中没有该字段信息,这个数据将会被拦截,无法到达请求方,浏览器并会报错。
-
利用src和href标签属性可以直接通过GET请求跨域访问其他站点的特点,而诞生了jsonp的使用方法。
-
-
答案2:
- JSONP 原理:实际上
script
中的src
属性中可以放的不止 JS 这一种文件类型,也可以是一个网站地址。script
处理 JS 文件的原理,首先加载该地址中的 JS 文件,然后从头到尾执行一遍该文件的内容。所以,如果src
的内容是一段内容为函数的字符串,那么该函数将会被执行。那么服务器可以返回一个 “函数字符串”,然后客户端执行提前准备好的该函数内容。 - CORS:全称为 Cross-Origin Resource Sharing,即 跨域资源共享,它允许浏览器向跨域服务器发送 Ajax 请求,克服了 Ajax 只能同源使用的限制。使用 CORS 的时候,客户端的代码不需要修改,在服务端作相应的配置皆可。
- 同源政策是浏览器对 Ajax 技术的限制,服务器端是不存在同源政策限制。因此,客户端A可以先向自身所在的服务器端A发送 ajax 请求,服务器A再向服务器B发送请求。服务器A将从服务器B响应来的数据传给客户端A。这样,就绕过了同源政策,实现跨域请求。
- 允许所有非同源网站的请求:
Access-Control-Allow-Origin: '*'
(对于服务器B来说) - 允许的请求方式:Access-Control-Allow-Methods: ‘get,post’ (对于服务器B来说)
- 服务器端A向服务器端B( http://localhost:3002 )使用
request
发送请求
- HTTP Cookie(也叫 Web Cookie 或浏览器 Cookie)是 服务器发送到用户浏览器并保存在本地的一小块数据,它会在浏览器下次向同一服务器再发起请求时被携带并发送到服务器上。通常,它用于告知服务端两个请求是否来自同一浏览器,如 保持用户的登录状态。Cookie 使基于无状态的HTTP协议记录稳定的状态信息成为了可能。
- 跨域请求时,不会携带Cookie,解决方法:
- 对于前端,设置
xhr.withCredentials
指定在涉及到跨域请求时,是否携带 cookie 信息,默认值为false
(也就是设置xhr.withCredentials=true
) - 对于服务端,设置
Access-Control-Allow-Credentials:true
允许客户端发送请求时携带 cookie。
- 对于前端,设置
- 跨域请求时,不会携带Cookie,解决方法:
- JSONP 原理:实际上
-
vue:
1.双向绑定原理
- 问的比较少,基本没有问语法的,大厂基本都是react,vue最多问一下双向绑定原理;
2.webpack打包
-
webpack打包,plugin babel loader区别及用法,一般是简历上写了才会问。 loader与plugin 区别
-
loader:
- 由于webpack 本身只能打包commonjs规范的js文件,所以,针对css,图片等格式的文件没法打包,就需要引入第三方的模块进行打包。loader虽然是扩展了 webpack ,但是它只专注于转化文件(transform)这一个领域,完成压缩,打包,语言翻译。
- css-loader和style-loader模块是为了打包css的
- babel-loader和babel-core模块是为了把ES6的代码转成ES5
- url-loader和file-loader是把图片进行打包的。
-
plugin:
-
plugin完成的是loader不能完成的功能。也是为了扩展webpack的功能,但是 plugin 是作用于webpack本身上的。而且plugin不仅只局限在打包,资源的加载上,它的功能要更加丰富。从打包优化和压缩,到重新定义环境变量,功能强大到可以用来处理各种各样的任务。
-
html-webpack-plugin:不但完成了html文件的拷贝,打包,还给html中自动增加了引入打包后的js文件的代码
-
clean-webpack-plugin 插件:可以在每次打包发布时自动清理掉 dist 目录中的旧文件
-
-
3.怎么学习vue
- 还有可能问到你平时是怎么学习vue的。
2.项目
根据大家自己写的项目问,没有固定问题。
可能问:
1.前后端怎么沟通接口
- 你在项目中承担了什么工作,前后端怎么沟通接口?
2.如何发生请求
-
前端如何发送请求,涉及ajax(axios)知识;
- jQuery提供的
$.ajax()
封装好了 Ajax 请求
$.ajax({ // 设置请求类型 type: 'get', // 设置请求地址 url: 'http://www.example.com', // 设置请求参数 data: { name: 'zhangsan', age: '20' }, // 设置请求参数类型 contentType: 'application/x-www-form-urlencoded', // 设置请求发送前的要做的事情 beforeSend: function () { // 阻断请求的发送 return false }, // 请求成功后要做的事情 success: function (response) {}, // 请求出现错误要做的事情 error: function (xhr) {} });
- Axios 是专注于网络数据请求的库。相比于原生的 XMLHttpRequest 对象,axios 简单易用。相比于 jQuery,axios 更加轻量化,只专注于网络数据请求。
- jQuery提供的
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ng3Bjzsy-1649945417216)(C:\Users\sissiz\AppData\Roaming\Typora\typora-user-images\image-20220411192215668.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-an23Jdon-1649945417219)(C:\Users\sissiz\AppData\Roaming\Typora\typora-user-images\image-20220411192429721.png)]
3.现场写代码
1.前端知识相关:
- promise(更多是基于promise写一些功能实现), promise.all,promise.race手写 ;
- ajax请求手写(封装成基于promise的);
- 深拷贝;
- 数据类型判断;
- 手写new操作符;
- 防抖节流函数手写;
- 解析url中的参数;
2.leetcode算法题:
- 机器人路径(动规问题,理解动态规划思想);
- 数组相关(主要是会使用splice、slice等js方法);
- 链表相关(反转链表);
- 还是需要多刷题,具体关于刷题的建议可以参考我上个视频中关于面试准备的部分