2023面试题大全updating

一、css的居中方式

摘自,CSS居中方式总结_明月落乌江的博客-CSDN博客_css居中

1)行内元素水平居中

给父元素设置text-algin:center后,可以实现子元素水平居中

对行内元素(inline),行内块(inline-block),行内表(inline-table),inline-flex也有效果。

2)块级元素水平居中

a.给元素设置margin:0 auto,可以实现元素本身居中

b.子绝父相后:

left:50%;margin-left:一半长度

left:50%;transform: translateX(-50%);

3)多块级元素水平居中

a.给父元素设置text-algin:center后,给多个块级元素同时设置inline-block,可以实现多个元素挨着居中

b.利用flex布局,给父元素设置display:flex,jusitify-content:center

4)单行行内元素垂直居中

将height和line-height设置成相同的高度,可以实现元素垂直居中

5)多行元素垂直居中

a.利用表格布局的verticval-algin:middle来实现布局。父元素设置display:table,子元素设置成display:table-cel,vertical-algin:middle

b.利用flex布局diplay:flex,flex-direction:column,jusitify-content:center

6)块级元素垂直居中

在子绝父相的情况下:

top:50%;margin-top:-一半高度;或者top:50%;

transform: translateY(-50%);

未知宽高元素水平垂直居中方法

1. 设置元素相对父级定位`position:absolute;left:50%;right:50%`,让自身平移自身高度50% `transform: translate(-50%,-50%);`,这种方式兼容性好,被广泛使用的一种方式
2. 设置元素的父级为弹性盒子`display:flex`,设置父级和盒子内部子元素水平垂直都居中`justify-content:center; align-items:center` ,这种方式代码简洁,但是兼容性ie 11以上支持,由于目前ie版本都已经很高,很多网站现在也使用这种方式实现水平垂直居中
3. 设置元素的父级为网格元素`display: grid`,设置父级和盒子内部子元素水平垂直都居中`justify-content:center; align-items:center` ,这种方式代码简介,但是兼容性ie 10以上支持
4. 设置元素的父级为表格元素`display: table-cell`,其内部元素水平垂直都居中`text-align: center;vertical-align: middle;` ,设置子元素为行内块`display: inline-block; `,这种方式兼容性较好
5.设置元素相对父级定位`position:absolute;left:0;right:0;top:0;bottom:0;margin:auto;`,没有兼容性问题

注意:auto

auto是自适应的意思,auto是很多尺寸值的默认值,也就是由浏览器自动计算块级元素中margin、border、padding以及content宽度之和构成父元素width
http://t.csdn.cn/2zYTK

二、px,em,rem,%,vm&vh

摘自px、em、rem和%的定义 - 蛋蛋超人z - 博客园

1)px

px单位的名称为像素,它是一个固定大小的单元。1px就是屏幕上的一个点

2)em

em单位的名称为相对长度单位,它是用来设置文本的字体尺寸的,相对于父级元素对象内文本的字体尺寸;如果没有人为设置当前对象内文本的字体尺寸,那么它相对的是浏览器默认的字体尺寸(16px)。

在 `font-size` 中使用是相对于父元素的字体大小,

在其他属性中使用是相对于自身的字体大小,如 width

3)rem

rem是css3新增的一个相对长度单位,它的出现是为了解决em的缺点,em可以说是相对于父级元素的字体大小,当父级元素字体大小改变时,又得重新计算。rem出现就可以解决这样的问题,rem只相对于根元素的字体大小,即HTML元素。所以只要在html标签上设置字体大小,文档中的字体大小都会以此为参照标准,一般用于自适应布局。

4)%

%也很常见,它和em差不多一样,都是相对于父级元素。但%可以在很多属性中使用,比如:width、height、font-size等。而em是用来设置字体大小(font-size)的单位,width、height等属性是没有em单位的。

5)vh&vm

视口高度和视口宽度

在移动端响应式页面中,通常使用vw配合rem。原理是使用vw设置根元素html字体的大小,当窗口大小发生改变,vw代表的尺寸随着修改,无需加入媒体查询和flexible.js,页面中的其他元素仍使用rem为单位,就可实现响应式。

三、display的值和作用

摘自display的值和作用_CM22222的博客-CSDN博客_display有哪些值?说明他们的作用

1)display的值有

none,inline,block,list-item,inline-block,table,inline-table,table-caption,table-cell,table-row,table-row-group,table-column,table-column-group,table-footer-group,table-header-group,run-in,box,inline-box,flexbox,inline-flexbox,flex,inline-flex

2)作用

none: 表示隐藏对象,与visibility属性的hidden值不同,display:none不为被隐藏的对象保留物理空间 ,会从文档流中移除,然visibility:hidden就保留

inline(默认值):表示指定对象为内联元素。默认宽度为内容宽度,不可设置宽高,同行显示。

block: 指定对象为块元素。默认宽度为父元素宽度,可设置宽高,换行显示。

list-item: 指定对象为列表项目。像块类型元素一样显示,并添加样式列表标记。 

inline-block: 指定对象为内联块元素。默认宽度为内容宽度,可以设置宽高,同行显示。 

table: 指定对象作为块元素级的表格。类同于html标签table(CSS2)

inline-table: 指定对象作为内联元素级的表格。类同于html标签table(CSS2)

table-caption: 指定对象作为表格标题。类同于html标签caption(CSS2)

table-cell: 指定对象作为表格单元格。类同于html标签td(CSS2)

table-row: 指定对象作为表格行。类同于html标签tr(CSS2)

table-row-group: 指定对象作为表格行组。类同于html标签tbody(CSS2)

table-column: 指定对象作为表格列。类同于html标签col(CSS2)

table-column-group: 指定对象作为表格列组显示。类同于html标签colgroup(CSS2)

table-header-group: 指定对象作为表格标题组。类同于html标签thead(CSS2)

table-footer-group: 指定对象作为表格脚注组。类同于html标签tfoot(CSS2)

run-in: 根据上下文决定对象是内联对象还是块级对象。(CSS3)

box: 将对象作为弹性伸缩盒显示。(伸缩盒的最老版本中属性)(CSS3)

inline-box: 将对象作为内联块级弹性伸缩盒显示。(伸缩盒的最老版本中属性)(CSS3)

flexbox: 将对象作为弹性伸缩盒显示。(伸缩盒的最老版本中属性)(CSS3)

inline-flexbox: 将对象作为内联块级弹性伸缩盒显示。(伸缩盒的最老版本中属性)(CSS3)

flex: 将对象作为弹性伸缩盒显示。(伸缩盒的最老版本中属性)(CSS3)

inline-flex: 将对象作为内联块级弹性伸缩盒显示。(伸缩盒的最老版本中属性)(CSS3)

四、数组去重

1)先将原数组排序,在与相邻的进行比较,如果不同则存入新数组

            var arr=[1,4,9,1,2,7,8,3,3,7,8,9,5,6];
			var newArr=[];
			arr.sort(function(a,b){
				return a-b;
			});
			for(var i=0;i<arr.length;i++){
				if(arr[i]!=arr[i+1]){
					newArr.push(arr[i]);
				}
			}
			console.log(newArr)//[1, 2, 3, 4, 5, 6, 7, 8, 9]

2) 遍历数组,查找新数组中有没有包含旧数组中的值

			//如果在新数组中没有找到。则push进去
			var arr=[1,1,1,2,3,4,4,2,5,5,5];
			var newArr=[];
			for(var i=0,len=arr.length;i<len;i++){
				if(!newArr.includes(arr[i])){
					newArr.push(arr[i]);
				}
			}
			console.log(newArr);

3)reduce

let arr = [1,2,1,2,3,5,4,5,3,4,4,4,4];
let result = arr.sort().reduce((init, current) => {
    if(init.length === 0 || init[init.length-1] !== current) {
        init.push(current);
    }
    return init;
}, []);
console.log(result); // - [1,2,3,4,5]
let arr = [1,2,1,2,3,5,4,5,3,4,4,4,4];
let result = arr.sort().reduce((init, current) => {
    if(init.length === 0 || init[init.length-1] !== current) {
        init.push(current);
    }
    return init;
}, []);
console.log(result); // - [1,2,3,4,5]

3)set方法

let arr = [1,1,2,3,4,4];
let mySet = new Set(arr);
let newArr = Array.from(mySet);
console.log(newArr);  //[1,2,3,4]

五、统计字符串中出现最多的字符

1)利用对象键不可重复

            var str="qqqwwerrrr";
			var obj={};
			for(var i=0;i<str.length;i++){
				if(str[i] in obj){
					obj[str[i]]++;
				}else{
					obj[str[i]]=1
				}			
			}
			var max=0;
			var char="";
			for(var k in obj){
				if(obj[k]>max){
					max=obj[k];
					char=k;
				}
			}
			console.log(max,char)//4 'r'

 统计数组中元素出现次数

var names = ['Alice', 'Bob', 'Tiff', 'Bruce', 'Alice', 'Bob', 'Bob'];
var countedNames = names.reduce(function (allNames, name) {
  console.log(allNames,name);
  if (name in allNames) {
    allNames[name]++;
  }
  else {
    allNames[name] = 1;
  }
  return allNames;
}, {});
console.log(countedNames);

六、js垃圾回收机制

摘自JS垃圾回收机制_Sunsine_C的博客-CSDN博客_js垃圾回收机制

GC算法

垃圾回收机制的简写。可以找到内存中的垃圾,并释放和回收垃圾。

GC中的垃圾是什么?

  • 程序中不再需要使用的对象
  • 程序中不能再访问到的对象

GC算法是什么?

GC是一种机制,垃圾回收器完成具体的工作。

  • 工作的内容就是查找垃圾释放空间、回收空间。
  • 算法就是工作时查找和回收所遵循的规则

常见的GC算法

引用计数

 缺陷:频繁计数影响性能,无法处理循环引用问题

// 对象被 a 引用
let a = {
    b: {
        x: 10
    }
}

let a1 = a // 又被 a1 引用
let a = 0 // 不再被 a 引用,但仍然被 a1 引用
let a1 = null // 不再被 a1 引用

// 对象最终没有任何引用,会被回收
function fn() {
    const obj1 = {}
    const obj2 = {}
    obj1.a = obj2
    obj2.a = obj1 // 循环引用,无法回收 obj1 和 obj2
}
fn()

标记清除

    标记:遍历所有的GC Roots,并将从GC Roots可达的对象设置为存活对象;
    清除:遍历堆中的所有对象,将没有被标记可达的对象清除;
    定期从根(即全局变量)开始向下查找,能找到的即保留,找不到的即回收。循环引用不再是问题
    注意:大量的内存遍历工作,所以执行性能较低,内存不连续,空间浪费

拿 Vue 来举例说明

组件中有全局变量、函数的引用。组件销毁时要记得清空

组件有全局定时器。组件销毁时要记得清除。

组件中有全局事件的引用。组件销毁时记得解绑。

组件中使用了自定义事件,销毁时要记得解绑。

标记整理

        在进行完标记清除之后,对内存空间进行压缩,节省内存空间,解决了标记清除算法内存不连续的问题。节省内存空间,解决了标记清除算法内存不连续

复制算法

    内存一分为二,存活对象复制到空白内存,最后将正在使用的内存空间的对象清除
    简洁高效
    不适合用于存活对象多的情况,因为那样需要复制的对象很多
    复制算法往往用于内存空间中新生代的垃圾回收,因为新生代中存活对象较少,复制成本较低
 
备注:
    新生代    存活对象少    复制算法
    老年代    存活对象多    标记清除整理

如何检测内存变化

可使用 Chrome devTools Performance 来检测内存变化

  1. 刷新页面,点击“GC”按钮
  2. 点击“Record”按钮开始记录,然后操作页面
  3. 操作结束,点击“GC”按钮,点击“结束”按钮,看分析结果

七、页面渲染流程

摘自页面渲染流程_Mountain Ghost的博客-CSDN博客_页面渲染的过程

页面渲染的流程_XuJiaShuo777的博客-CSDN博客_页面渲染的全过程

dom节点和样式相结合后,构建呈现树,供浏览器解析绘制画面

一、dom树

        浏览器把html代码解析成1个Dom树,html中的每个tag都是Dom树中的1个节点,根节点就是我们常用的document对象。dom树就是html结构,里面包含了所有的html tag,包括用JS添加的元素。

二、样式结构体

        浏览器把所有样式(主要包括css和浏览器自带的样式设置)解析成样式结构体,在解析的过程中会去掉浏览器不能识别的样式。

三、呈现树 render tree

        dom tree和样式结构体结合后构建呈现树(render tree),将每个节点与其对应的css样式结合。

四、绘制页面

        一旦render tree构建完毕后,浏览器就根据render tree来绘制页面。

理解:

        1.render tree可以粗犷的理解为加上了对应样式的dom树;

        2.  render tree不包含隐藏的节点(比如display:none的节点,还有head节点),因为这些节点不会用于呈现,而且不会影响呈现的,所以就不会包含到render tree中。(不占位置,不影响布局)

        3.visibility:hidden隐藏的元素还是会包含到render tree中的,因为visibility:hidden 会影响布局,会占有位置。(占位置,影响布局)

重绘(颜色变了就是重绘)

        重新绘画(页面的重新渲染),对页面进行操作,如:更换颜色、更换背景,不改变页面布局,但是颜色或背景变了,就会重新渲染页面,这就是重绘。

重排(节点发生变化,高宽位置发生变化)

        1)、添加或者删除可见的DOM元素;

        2)、元素位置改变——display、float、position、overflow等等;

        3)、元素尺寸改变——边距、填充、边框、宽度和高度

        4)、内容改变——比如文本改变或者图片大小改变而引起的计算值宽度和高度改变;

        5)、页面渲染初始化;

        6)、浏览器窗口尺寸改变——resize事件发生时;

如何减少和避免重排

重排的成本比重绘的高的多。一个节点的 Reflow 很有可能导致子节点,甚至父节点以及兄弟节点的 Reflow 。在一些高性能的电脑上也许还没什么,但是如果 Reflow 发生在手机上,那么这个过程是延慢加载和耗电的。----浏览器的渲染原理简介

1. 直接改变className,如果动态改变样式,则使用cssText(考虑没有优化的浏览器);

2. 让要操作的元素进行”离线处理”,处理完后一起更新;

        a) 使用DocumentFragment进行缓存操作,引发一次回流和重绘;
        b) 使用display:none技术,只引发两次回流和重绘;
        c) 使用cloneNode(true or false) 和 replaceChild 技术,引发一次回流和重绘;

3.不要经常访问会引起浏览器flush队列的属性,如果你确实要访问,利用缓存;

4. 让元素脱离动画流,减少回流的Render Tree的规模;

5. 避免dom操作,将频繁dom操作,改为一次操作;对dom查询做缓存

重排一定引起重绘,重绘不一定是因为发生了重排

八、http中的方法

摘自HTTP协议详解_一只咸鱼。。的博客-CSDN博客_http协议

传统的方法
get获取数据,post提交数据

现在的方法
get获取数据
post新建数据
put/patch更新数据 
delete删除数据

GET 和 POST 的区别

GET和POST请求的区别(超详细)_java中get请求和post请求_Java运动猿的博客-CSDN博客

GET 和 POST 其实没有本质区别,使用 GET 的场景完全可以使用 POST 代替,使用 POST 的场景一样可以使用 GET 代替。但是在具体的使用上,还是存在一些细节的区别

1.get请求一般是去取获取数据(其实也可以提交,但常见的是获取数据);
post请求一般是去提交数据。

2.get因为参数会放在url中,所以隐私性,安全性较差,请求的数据长度是有限制的,
不同的浏览器和服务器不同,一般限制在 2~8K 之间,更加常见的是 1k 以内;
post请求是没有的长度限制,请求数据是放在body中;
GET方式需要使用Request.QueryString来取得变量的值,而POST方式通过Request.Form来获取变量的值,也就是说Get是通过地址栏来传值,而Post是通过提交表单来传值。

GET 方法简约版报文可能是这样的

GET /index.php?name=qiming.c&age=22 HTTP/1.1
Host: localhost

POST 方法简约版报文可能是这样的


POST /index.php HTTP/1.1

Host: localhost


Content-Type: application/x-www-form-urlencoded name=qiming. c&age=22

3.get请求刷新服务器或者回退没有影响,post请求回退时会重新提交数据请求。

4.get请求可以被缓存,post请求不会被缓存。

5.get请求会被保存在浏览器历史记录当中,post不会。get请求可以被收藏为书签,因为参数就是url中,但post不能。它的参数不在url中。

6.get请求只能进行url编码(appliacation-x-www-form-urlencoded),post请求支持以下多种编码

multipart/form-data:既可以上传文件等二进制数据,也可以上传表单键值对,只是最后会转化为一条信息;
x-www-form-urlencoded:只能上传键值对,并且键值对都是间隔分开的。(用Qs库转换)
application/json: 以序列化的 JSON 字符串形式传输

注意:

按照网上大部分文章的解释,POST 比 GET 安全,因为数据在地址栏上不可见。
然而从传输的角度来说,他们都是不安全的,因为 HTTP 在网络上是明文传输,只要在网络节点上抓包,就能完整地获取数据报文。
要想安全传输,就只有加密,也就是 HTTPS

九、数组转字符串

        1)遍历数组加入到新字符串中

            var arr=['q','w','e','r','t'];
			var str="";
			for(var i=0;i<arr.length;i++){
				str+=arr[i];
			}
			console.log(str);//qwert

        2)利用join()

            var arr=['q','w','e','r','t'];
            var res=arr.join("");
			console.log(res)//qwert

十、连接两个数组

        1)利用concat()

            var arr1=[1,2,3];
			var arr2=['a','b','c']
			console.log(arr1.concat(arr2))//[1, 2, 3, 'a', 'b', 'c']

十一、const用法

摘自JS中const的使用 - 码农教程

1.const用来定义常量,赋值之后不能再赋值,再次赋值会报错。

2.const不能只声明不赋值,会报错。

3.const常量含义是你不能改变其指向的对象。例如user对象不可以改变,但是你可以改变user对象下的属性。

        const内存地址详解

        对象count一开始只是0x10的地址,直接将count(给count重新赋值,指向一个新的对象)指向地址改为0x20会报错,const是常量,无法更改对象地址。

        对象user一开始指向0x10地址,user有NameAgeHeight三个属性,此时修改属性Name='ttt',user对象的地址未改变,不会报错。

十二、css定位

摘自谈谈fixed ,related , absolute_yang114544的博客-CSDN博客

 1)static静态定位

         是HTML中默认的定位,符合常规文档流。

2)relative相对定位

         相对定位是相对本身位置而言的,进行上下左右的偏移,但是他不脱离文档流。

3)absolute绝对定位

       绝对定位是相对于父元素来定位的,如果没有父元素或者说父元素没有定位的情况下,会向上一直找寻参照物,直至最终的浏览器窗口,区别于相对定位,绝对定位会脱离文档流。

4)fixe固定定位

        固定定位(position:fixed),可理解为绝对定位中的一种特殊情况,即absolute包含fixed。它的特殊之处在于它不用像absolute疯狂“找爸爸”,它天生参照于浏览器窗口!当为对象设置固定定位后,该对象即处于浏览器窗口画面中的固定位置,无视文档长短、窗口大小和滚条滚动。

5)sticky粘滞定位

当元素滚到指定top位置时,就不会再滚了

开启之后的特点
      1、开启粘滞定位,元素不会脱离文档流,也就是元素性质也不会发生改变
      2、开启粘滞定位后,元素位置不发生改变,需要配合偏移量使用
          一般情况下,是配合top值使用
         在没有到达top值之前,元素是随着滚动条滚动而滚动,
              当到达top值之后,元素就不会随着滚动条滚动而滚动了
      3、粘滞定位是后来增加的定位方式,注意它的兼容性,一般兼容到ie9以上
      4、粘滞定位的原点也是浏览器视口,也就是html根标签

十三、float和absolute的区别

摘自float和absolute的区别_幼儿园编程的博客-CSDN博客_absolute和float区别

二者都会脱离文档流,当子元素设置float或者absolute后,父元素都会造成高度塌陷的问题

float

        float浮动,当元素通过float来脱离文档流时,虽然其他的元素会当其不存在,但其他元素的内容还是会把这个元素占的位置让出来。也就是该元素浮动在另外一个有文字内容的元素上时,文字内容并不会被浮动的元素覆盖,而是环绕在周围。

        如下图紫色div为浮动元素,蓝色div中的内容会围绕在紫色div周围。因此可以说float这种属于半脱离文档流。float也常常用来实现文字的环绕效果

注意:float和inline-block的相似之处

inline-block和float可以出现相同的效果,不同的是,inline-block实现元素并排,元素之间会有间隙,因为加入了HTML代码中的空格

可以看到下面黑色盒子并不会贴到最左边,这和float元素找位置的原理有关,每个float盒子定位都是依据上一个盒子的右边界来定位的,每个盒子都会往前查找,知道碰到页面边界,而上图的黑盒子往前查找,找到金色盒子,但是没有碰到它的边界,所以再往前找,就碰到红色盒子的边界,所以就停在了这里。

absolute

        absolute脱离文档流的时候,其他元素和元素中的文本都会无视掉他,因此不会像float那样将其他元素的内容挤到旁边去

        如下图紫色div(设置了透明度)会覆盖掉蓝色div的内容

十四、CSS3选择器

  • 通配符选择器
  • 类选择器
  • id选择器
  • 元素选择器
  • 属性选择器

        ①简单属性选择器:选择具有某个属性名的元素

        ②具体属性值选择器:选择具有指定属性键值对(属性名和属性值都要匹配)的元素

        ③子串匹配属性选择器:可以规定属性值包含什么字符串(*)或以什么字符串开头(^)/结尾($)

  • 后代选择器
  • 子元素选择器
  • 兄弟选择器

        ①相邻兄弟选择器E+F

        ②通用兄弟选择器E~F

  • 伪元素选择器

        ①:first-line/::first-line伪元素 用于向文本的首行设置特殊样式,只能用于块级元素

        ②:first-letter/::first-letter伪元素 用于向文本的首字母设置样式,只能用于块级元素

        ③:before/::before 在元素内容之前添加内容,属于该元素,默认伪元素是行内元素

        ④:after /::after 在元素内容之后添加内容,属于该元素,默认伪元素是行内元素

        ⑤::selection  设置元素在被选择时的样式。

  • 伪类选择器
  • 群组选择器

十五、数组冒泡排序

             function buddleArray(arr){
				for(var r=1;r<arr.length;r++){//外层循环实现需要几次遍历
					for(var i=0;i<arr.length-r;i++){//内层循环实现每次遍历把小的值往后放
						//从0开始遍历arr数组,到length-1结束,每次i++
						//如果当前元素arr[i]<arr[i+1],则交换两值位置
						//x+=y,y=x-y,x-=y
						if(arr[i]<arr[i+1]){							
							arr[i]+=arr[i+1];
							arr[i+1]=arr[i]-arr[i+1];
							arr[i]-=arr[i+1];
						}
					}
				}
				return arr;
			}
			var a=[2,5,6,9,3,1,4];
			buddleArray(a);
			console.log(a);// [9, 6, 5, 4, 3, 2, 1]

十六、创建新数组,向数组插入数据

			var newArr=[];
			newArr.unshift("b");
			newArr.push("a");
			console.log(newArr);// ['b', 'a']

十七、讲下你做轮播图的思路,无缝轮播

        box固定宽高,overflow:hidden;position:relative;

        ul放在box里面,宽度由内容li标签决定,position:absolute;left:0;

        li标签设置浮动属性,超出的部分会被隐藏。li标签内放图片。

        克隆一个第一个li节点到最后(如果需要平滑过渡)

        js添加定时器,让ul左移负值,移动到最后一个li标签后,再让ul标签left:0;

十八、原型和原型链

原型就是prototype,原型链就是__proto__,实例上的属性和方法,在构造函数里找不到就沿着__proto__去找,构造函数的原型上找不到,就在构造函数的原型链,到达Object.prototype找

最详尽的 JS 原型与原型链终极详解,没有「可能是」。(一) - 简书
1-面向对象的原型_哔哩哔哩_bilibili

对象分为普通对象和函数对象
person1 和 person2 都是 构造函数 Person 的实例
实例的构造函数属性(constructor)指向构造函数。
每个对象都有 __proto__ 属性,但只有函数对象才有 prototype 属性
原型对象就是 Person.prototype,原型对象(Person.prototype)是 构造函数(Person)的一个实例
JS 在创建对象(不论是普通对象还是函数对象)的时候,都有一个叫做__proto__ 的内置属性,用于指向创建它的构造函数的原型对象。person1.__proto__ == Person.prototype

十九、闭包

摘自js中的闭包_万物皆可div的博客-CSDN博客_js闭包

闭包的作用是在函数的外部读取到函数内部的变量,并保护私有变量不被修改

示例:        

        function f1() {
            var n = 999;
            function f2() {
                alert(n);
            }
            return f2;
        }
        var result = f1();
        result(); // 999

由于在Javascript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成"定义在一个函数内部的函数"。

所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。

以下摘自javascript 闭包问题,为什么要写成闭包的形式? - SegmentFault 思否

  1. 直接 return 返回的是变量,闭包返回的是执行环境
  2. 闭包不是为了让函数外部拿到内部变量,而是为了保护私有变量不被随意修改
  3. return 出来的是一个值,不是变量本身,此处的 return 是取得私有变量值的一种方法,跟闭包没有严格关系
  4. 闭包作为一个可以访问函数内部变量的函数,更多的是可以在其中添加其他的条件,过滤无效的值。如果直接return 变量,然后赋值的话,还要在后续去判断这个值的有效性。

所有自由变量的查找是在函数定义的地方逐渐向上级作用域查找查找,而不是在执行的地方查找
this取决于函数执行的地方

二十、HTML5的新特性

        1)用于绘画的 canvas 元素

        2)用于媒介回放的 video 和 audio 元素

        3)对本地离线存储的更好的支持

        4)新的特殊内容元素,比如 article、footer、header、nav、section

        5)新的表单控件,比如 calendar、date、time、email、url、search

二十一、css3的新特性

        1)css3选择器

        2)边框特性

        3)多背景图

        4)颜色与透明度

                除了rgb和16进制两种模式,HSL、HSLA、RGBA

        5)多列布局与弹性盒模型布局

        6)盒子的变形

                旋转、扭曲、缩放、移位

        7)过渡与动画

        8)web字体

                @font-face

        9)媒体查询

        10)阴影

二十二、Utf-8编码汉字占多少个字节

        在UTF-8编码中,一个中文字符等于三个字节,一个中文标点符号占三个字节;一个英文字符等于一个字节,一个英文标点占一个字节;一个数字符号等于一个字节。

二十三、vue基于什么语言开发的

        vue是基于JavaScript语言开发的,是一套用于构建用户界面的渐进式JavaScript框架,旨在更好地组织与简化Web开发。Vue的核心库只关注视图层,并且非常容易学习,也非常容易与其他库或已有项目整合。

二十四、js对数组的操作,包括向数组中插入删除数据

1)删除:arr.splice(starti,n)

2)插入:arr.splice(starti,0,新值1,,,)

3)替换:arr.splice(starti,n,新值1,,,)

5)push()在数组末尾添加一个元素,此方法会直接修改原数组,并返回新的数组长度

6)pop()删除并返回数组最后一个元素,会改变原数组

7)unshift()在数组开头添加一个元素;此方法会直接修改原数组,并返回新的数组长度

8)shift()删除并返回数组第一个元素,返回一个对应类型的值,原数组会被改变

9)sort()排序

纯函数

不改变原素组(没有副作用),并返回一个数组

concat,map,filter,slice

原数组改变的方法,七个

push pop shift unshift reverse sort splice

二十五、辗转相除法

			function maxNumber(n1, n2) {
			     var n3;
			     n3 = n1%n2;
			     if(n3==0){
			         return n2;
			     }
			     return maxNumber(n2,n3);
			 }

 二十六、js选择器

js中原生的选择器

  1. document.getElementById()
  2. document.getElementsByClassName()
  3. document.getElementsByName()
  4. document.getElementsByTagName()

    DOM扩展出了Selector API标准

     5、document.querySelector()
     6、document.querySelectorAll()

二十七、settimeout和setInterval的区别,以及setTimeout多次执行

settimeout只执行一次,setInterval只要没有清除就会一直执行

settimeout通过设置回调函数,可以多次执行,如下

            function fn(){
			    console.log("1");
			    setTimeout(fn,3000);    
			}
			fn();

二十八、transition transform translate 之间的区别 transform的属性有哪些?

transition是过渡

transform是变换

translate四transform的一个值,让元素在水平或垂直方向移动

transform的属性有translate、rotate、scale、skew

二十九、<ol><li></li></ol>结构的html代码,写原生js实现点击某个li就弹出对应的索引值

let 定义 i, 会把每次循环都成一个封闭空间。 i 值 就不会传递到空间外了(虽然它也可以自增)。具体可以了解下ES6 对for 的解释,let 和 const 命令 - ES6 教程 - 网道

			for( let i = 0 ; i< lis.length; i++){
				lis[i].onclick = function(){
					console.log(i);
				 }
			}

用事件委托,也就是冒泡

		<ul>
			<li data-index="0">111</li>
			<li data-index="1">222</li>
			<li data-index="2">333</li>
		</ul>
		<script type="text/javascript">
			document.querySelector("ul").onclick=function(e){
				console.log(e.target.dataset.index)
			}
		</script>

三十、对数组进行随机排序, 要求数组中的每个元素不能停留在原来的位置

随机生成index下标,将旧数组的值逐一推入新数组中

            let arr=[0,1,2,3,4,5,6,7,8,9];
			function fn(arr){
				var arrClone=arr.concat();
				let newArr=[];
				while(arr.length){
					let index=Math.floor(Math.random()*arr.length);
					newArr.push(arr.splice(index,1)[0]);
				}
				for(var i=0;i<arrClone.length;i++){
					if(arrClone[i]==newArr[i]){
						return fn(newArr);
					}
				}
				return newArr;
			}
			console.log(fn(arr))

三十一、http和https的区别

       总的来说,https更安全,https成本更高,https响应慢,https更耗费服务器资源
HTTP 明文传输,数据都是未加密的,安全性较差,HTTPS(SSL+HTTP) 数据传输过程是加密的,安全性较好。
使用 HTTPS 协议需要到 CA(Certificate Authority,数字证书认证机构) 申请证书,一般免费证书较少,因而需要一定费用。证书颁发机构如:Symantec、Comodo、GoDaddy 和 GlobalSign 等。
HTTP 页面响应速度比 HTTPS 快,主要是因为 HTTP 使用 TCP 三次握手建立连接,客户端和服务器需要交换 3 个包,而 HTTPS除了 TCP 的三个包,还要加上 ssl 握手需要的 9 个包,所以一共是 12 个包。
http 和 https 使用的是完全不同的连接方式,用的端口也不一样,前者是 80,后者是 443。
https 其实就是建构在 SSL/TLS 之上的 HTTP 协议,所以,要比较 https 比 https要更耗费服务器资源。

三十二、ajax

  1. ajax是前端与后端连接的桥梁,负责发起请求,对接后端的接口
  2. ajax 最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。

创建ajax的过程

  1. 创建XHR对象:new XMLHttpRequest()
  2. 设置请求参数:request.open(Method, 服务器接口地址)
  3. 发送请求: request.send(),如果是get请求不需要参数,post请求需要参数request.send(data)
  4. 监听请求成功后返回状态码200,进行渲染数据操作

 readyState值说明

状态描述
0UNSENT代理被创建,但尚未调用 open() 方法。
1OPENEDopen() 方法已经被调用。
2HEADERS_RECEIVEDsend() 方法已经被调用,并且头部和状态已经可获得。
3LOADING下载中;responseText 属性已经包含部分数据。
4DONE下载操作已完成。

简式说明

0 : 此时是点击立即购买的时候
1 : 在这个阶段对应的就是选择付款方式和收货地址
2: 这里对应的就是立即付款
3 : 在这里对应的就是,当你点击立即付款之后他会将物品发货也就是返回了数据,但又没完全返回,对应的就是你已经可以宣布收到物品了但又没完全收到。
4 : 此时就是你收到货物了,脸上露出了猥琐的笑容,浅浅的笑容就让你感到比中奖还要光荣,拆完箱子之后就决定这个商品喜不喜欢,喜欢就请求完成,不喜欢就退货请求失败。

手写ajax请求

//get请求
let xhr = new XMLHttpRequest()
xhr.open('get', 'example.php?query=4&em=0')
xhr.send()
xhr.onreadystatechange = function() {
    if(xhr.readyState === 4) {
        if(xhr.status === 200){
            console.log(xhr.responseText);
        }
    }
}

//post请求
let xhr = new XMLHttpRequest()
xhr.open('post', 'example.php')
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
xhr.send('query=4&em=0')
xhr.onreadystatechange = function() {
    if(xhr.readyState === 4) {
        if(xhr.status === 200){
            console.log(xhr.responseText);
        }
    }
}

三十三、盒子模型和怪异模型

        1)标准盒模型

    标准盒大小计算公式:width(content) + padding + border + margin        

   2)怪异盒模型

     怪异盒大小的计算公式:width(content + padding + border) + margin     

        3)对盒模型设置的属性 box-sizing                

三十四、bookstrap的响应式所示怎么实现的

        分别为不同的屏幕分辨率定义布局,页面元素宽度随着窗口调整而自动适配。每个屏幕分辨率下面会有一个布局样式,可以对元素位置和大小进行改变。

三十五、js的数据类型

1)基本数据类型:

        字符串(String)、数字(Number)、bigInt(支持比number更大范围的整数)、布尔(Boolean)、空(Null)、未定义(Undefined)、symbol

BigInt

JS基本数据类型 —— BigInt_what_z的博客-CSDN博客_js bigint

BigInt数据类型的目的是比Number数据类型支持的范围更大的整数值以任意精度表示整数的能力尤为重要。使用BigInt,整数溢出将不再是问题

创建BigInt

1、整数的末尾追加n即可

2、调用 BigInt() 构造函数

2)引用数据类型:

        对象(Object)、函数(Function)

三十六、cookie和session有什么联系

       Session是由应用服务器维持的一个服务器端的存储空间,用户在连接服务器时,会由服务器生成一个唯一的SessionID,用该SessionID 为标识符来存取服务器端的Session存储空间。而SessionID这一数据则是保存到客户端,用Cookie保存的,用户提交页面时,会将这一 SessionID提交到服务器端,来存取Session数据

相同之处

        HTTP 是无状态的协议(对于事务处理没有记忆能力,每次客户端和服务端会话完成时,服务端不会保存任何会话信息),所以服务器与浏览器为了进行会话跟踪(知道是谁在访问我),就必须主动的去维护一个状态,这个状态用于 告知服务端前后两个请求是否来自同一浏览器 。而这个状态需要通过 cookie 或者 session 去实现。

        记录服务器和客户端会话状态的机制

不同之处

安全性:

        Session 比 Cookie 安全,Session 是存储在服务器端的,Cookie 是存储在客户端的。


存取值的类型不同:

        cookie 只支持存字符串数据,想要设置其他类型的数据,需要将其转换成字符串,Session 可以存任意数据类型。


有效期不同:

        cookie 可设置为长时间保持,比如我们经常使用的默认登录功能,Session 一般失效时间较短,客户端关闭(默认情况下)或者 Session 超时都会失效。


存储大小不同:

        单个 Cookie 保存的数据不能超过 3K,Session 可存储数据远高于 Cookie,但是当访问量过多,会占用过多的服务器资源。

三十七、图片预加载和懒加载

摘自图片的懒加载与预加载_HaanLen的博客-CSDN博客_图片预加载和懒加载

懒加载

        当页面滚动到目视范围内,再进行加载,以提高首屏加载速度

        懒加载也叫延迟加载,指的是在长网页中延迟加载图片的时机,当用户需要访问时,再去加载,这样可以提高网站的首屏加载速度,提升用户的体验,并且可以减少服务器的压力。
        懒加载的实现原理是将页面上图片的 src 属性设置为空字符串,将图片的真实路径保存在一个自定义属性中,当页面滚动的时候,进行判断,如果图片进入页面可视区域内,则从自定义属性中取出真实路径赋值给图片的 src 属性,以此来实现图片的延迟加载。       

预加载:

        直接将所有资源一下子加载到本地

        指的是将所需的资源提前请求加载到本地,这样后面在需要用到时就直接从缓存取资源。通过预加载能够减少用户的等待时间,提高用户的体验。

        实现方法最常用的方式是使用 js 中的 image 对象,通过为 image 对象来设置 scr 属性,来实现图片的预加载。 

三十八、减少页面加载时间的方法

摘自三种减少页面加载时间的方法。(加载时间指感知的时间或者实际加载时间)_不愿停的博客-CSDN博客_三种减少页面加载时间的方法

1)减少http请求

2)优化图片文件,减小其尺寸

扩展:将图片转成base64

步骤:搜索base64工具,上传图片后粘贴base64编码,放入img src中就可以了

优缺点:可以减少请求,但是会增大图片体积。base64图片适合做小图片,不适合做大图片

3)图片元素定义好宽高,不然浏览器会不断调整页面

4)在文件头部放css样式的定义,尾部放js脚本

5)减少DCOM元素

6)压缩css文件,js文件,去掉换行、空格

文件加载更快

1. 让传输的数据包更小(压缩文件/图片):图片压缩和文件压缩

2. 减少网络请求的次数:雪碧图/精灵图、节流防抖

3. 减少渲染的次数:缓存(HTTP缓存、本地缓存、Vue的keep-alive缓存等)

页面渲染更快

1. 提前渲染:ssr服务器端渲染

2. 避免渲染阻塞:CSS放在HTML的head中 JS放在HTML的body底部

3. 避免无用渲染:懒加载

4. 减少渲染次数:对dom查询进行缓存、将dom操作合并、使用减少重排的标签

性能优化原则

多使用内存,缓存。以空间换取时间
减少CPU计算量,减少网络加载耗时
从加载和渲染入手

三十九、分析代码中最终生效的CSS样式(CSS样式权重计算)

各选择器优先级

  1. 在行内写入 !important (最高优先级慎用,一般是用来检测是否是选择器权重问题)

  2.内联样式                                                                       1000  

  3.id选择器                                                                        100

  4.类和伪类选择器/属性选择器                                          10

  5.元素选择器                                                                    1

  6.通配符、子选择器、相邻选择器等。如*、>、+            0

  7. 继承的样式      没有优先级                                          00

如何计算优先级

   1、比较优先级时,需要将所有选择器的优先级进行相加计算,最后优先级越高,则优先显示

   2、 (并集选择器)分组选择器是单独计算的;

   3、 如果优先级计算后相同,此时则优先使用靠下的样式;

   4、选择器的累加,不会超过上一级数量级, 例如:类选择器再高也不会超过id选择器,量变达不到质变;

一般来说选择器越具体,优先级越高。

四十、数组中删除指定索引的元素

			function fn(arr,index){
				arr.splice(index,1);
				return arr;
			}
			var arr1=[1,2,3,4,5];
			console.log(fn(arr1,2));

 四十一、获取数组最后一个元素

            var arr = [1,2,3,4,5];
            // 方式1
            var last = arr.pop();
            // 方式2
            var last = arr.slice(-1)[0];
            // 方式3
            var last = arr[arr.length-1]

四十二、div高度百分百

        需要将div所有的父元素height都设置成百分百,

        例如html,body,div{height:100%};div{background:red}

四十三、localstore和sessionstore的区别

摘自

LocalStoreage和SessionStoreage区别与用法 - lenglingx的个人页面 - OSCHINA - 中文开源技术交流社区

localstore

        LocalStorage 译为 “本地存储器”,是 HTML5 中新增的一个存储对象,跟 Cookie 一样也是用来本地存储来的,但是解决了 Cookie 存储空间不足的问题 (cookie 每条存储空间为 4k),而 localStorage 浏览器一般支持 5M,通常以键 / 值对形式的字符串进行存储。只要不手动删除,就会一直存在

sessionstore

        SessionStorage 译为 “会话存储”,也是 HTML5 新增的一个存储对象, 用于本地临时存储同一窗口的数据,在关闭窗口之后将会删除这些数据,SessionStorage 浏览器一般支持 5M,通常以键 / 值对形式的字符串进行存储。

他们的特点

        1. 不同浏览器之间无法共享 LocalStorage 或 SessionStorage 中的数据。

        2.LocalStorage 和 SessionStorage 可以使用统一的 API 接口。

        3.LocalStorage 或 SessionStorage 通常以键 / 值对形式的字符串进行存储,所以在存储时需要对数据格式进行转换,使用 JSON.stringify 方法将对象转换成字符串,提取时用 JSON.parse 方法将字符串转换成对象

用法示例

localStoreage.setItem('键','值')   //保存数据本地(变量名,值)
localStoreage.getItem('键')        //获取本地数据(变量名)
localStoreage.removeItem('键')     //移除本地数据(变量名)
localStoreage.key(0)               //获取指定下标数据
localStoreage.clear()              //清除localStoreage
//需要配合
JSON.stringify(value)
JSON.parse(value)

四十四、ES6新特性

摘自ES6新特性有哪些?_嘿哈,辉的博客-CSDN博客_es6新特性有哪些

1)、新的原始类型和变量声明

2)、新的对象和方法

3)、函数默认值。箭头函数,class类

5)、模块的导入和导出

6)、异步机制

四十五、怎么理解模块化开发

摘自Js模块化开发的理解_WindrunnerMax的博客-CSDN博客_js模块化开发

模块化开发其实就是封装细节,提供使用接口,彼此之间互不影响,每个模块都是实现某一特定的功能,同时也需要避免全局变量的污染

模块化规范

CommonJsAMDCMDES6都是用于模块化定义中使用的规范,其为了规范化模块的引入与处理模块之间的依赖关系以及解决命名冲突问题,并使用模块化方案来使复杂系统分解为代码结构更合理,可维护性更高的可管理的模块。

ES6

ES6在语言标准的层面上实现了模块的功能,是为了成为浏览器和服务器通用的模块解决方案,ES6标准使用export与export default来导出模块,使用import导入模块。此外在浏览器环境中是可以使用require来导入export、export default导出的模块的,但依然建议使用import标准导入模块。目前ES6模块是静态的,无法实现按需加载,当然可以使用babel进行解析,也可以使用CommonJS的require,此外有一份新的规范提案也有可能将动态加载并入标准。

四十六、手机号正则表达式

let reg=/^1[3|4|5|7|8][0-9]{9}$/

  • 1 以1开头
  • [3|4|5|7|8] 第二位是3或4或5或7或8任意一位
  • [0-9]{9}$ 以0-9任意9位数字结尾

四十七、用CSS实现一个背景色为红色,半径为200px的圆,并设置不停的上下移动动画

            div{
				width: 400px;
				height: 400px;
				background-color: red;
				border-radius: 50%;
				margin: 0 auto;
				animation: move 10s infinite;
			}
			@keyframes move{
				0%{
					transform: translateY(0);
				}
				50%{
					transform: translateY(400px);
				}
				100%{
					transform: translateY(0);
				}
			}

四十八、列举两种清除浮动的方法

1)在父级元素结尾前加个清除浮动的空div

clear:both

2)给要清除浮动的父级元素定义伪类after

.clearFloat:after{
    display:block;
    clear:both;
    content:"";
}

四十九、代码实现3栏效果,左右两栏固定宽度,中间栏随着浏览器宽度自适应变化

1)左右两个盒子用绝对定位靠边,中间盒子为标准流,独占一行。左右的盒子会将左右两两边覆盖掉

2)左右两个盒子用浮动定位,中间盒子为标准流独占一行。左右的盒子会将左右两两边覆盖掉

3)用grid布局

<!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>
    <style>
    .box{
        display: grid;
        grid-template-columns: 100px 1fr 100px;
        /*或者,grid-template-columns: 100px auto 100px;*/
        grid-template-rows: 100px;
        /* grid-column-gap: 10px; */
    }
    .item{
        background-color: aliceblue;
    }
    .item1,.item3{
        background-color: red;
    }
    </style>
</head>
<body>
    <div class="box">
        <div class="item item1"></div>
        <div class="item item2"></div>
        <div class="item item3"></div>
    </div>
</body>
</html>

五十、代码实现parse方法,将有效的JSON字符串转换成JavaScript对象

var str = '{"name":"John"}';
var obj = jQuery.parseJSON(str);
alert( obj.name === "John" );

五十一、cookie和localStorage的区别,如何获得他们?

cookie

1、只能存储文本

2、单条存储有大小限制4KB左右

3、数量限制,一般浏览器,限制大概在50条左右

4、读取有域名限制

5、时效限制

6、路径限制

localStorage

1、存储值限定为string类型,使用需要转换

JSON.parse()//转为数组、JSON.stringify()//转为字符串

2、只要写入,存储时限可以是永久

3、浏览器隐私模式下不可读取。

4、太多了会导致页面卡顿

5、不能被爬虫读取

cookie和localStorage的使用

cookie:

    存:

        document.cookie = 'key=value';

    取:

        let cookie = document.cookie;
    需要注意的是cookie一般是后端处理

localStorage:

    存:

        window.localStorage.setItem(key, value);
        window.localStorage.name = 'zhangsan';

    取:

        let value = window.localStorage.getItem(key);
        let name = window.localStorage.name;

五十二、用什么方法判断是否是数组?又用什么方法判断是否是对象?

1、obj.constructor

2、obj instanceof Array

3、Object.prototype.toString.call()

上面三种数组对象都可以判断

此外数组还可以用Array.isArray()

五十三、对H5新增的语义化标签的理解?

摘自引用样式的方式有哪几种?他们的优先级排序怎么样?_@少年啊的博客-CSDN博客_引入样式的方法有哪几种

header、nav、section、artice、aside、footer

  1. 语义化标签和无语义化div一样,都是表示一个空的容器
  2. 易于用户阅读,样式文件未加载时,页面结构清晰。
  3. 有利于SEO,搜索引擎根据标签来确定上下文和各个关键字的权重。
  4. 方便屏幕阅读器解析,如盲人阅读器根据语义渲染网页。
  5. 有利于开发和维护,代码更具可读性,代码更好维护。
  6. HTML5语义化标签并没有广泛使用,比如京东、淘宝等,还是使用div元素,设置id是header或者footer,这个可能是因为HTML5新增的语义化标签的作用不是特别大,网站没有必要重写

五十四、引用样式的方式有哪几种?他们的优先级排序怎么样?

        1、内联(行内样式) - 在标签内直接写样式

        2、内嵌(内部样式) - 在head标签里,加一个style标签,在style里写样式

        3、外联(外部样式) - 新建一个.css文件,通过link来引入样式

        4、导入(导入样式) - 在head标签里,加一个style标签,再写@import url(),跟用link的方式差不多

优先级:

        1、就近原则

        2.理论上:内联>内嵌>外联>导入

        3.实际上:内嵌、外联、导入在同一个文件头部,在CSS选择器权值相同的情况下,谁离相应的代码近,谁的优先级高

五十五、内存泄漏

内存泄露是指你用不到(访问不到)的变量,依然占据着内存空间,不能被再次利用起来

常见的内存泄漏

1)意外的全局变量

2)闭包引起的内存泄漏

3)没有清理DOM元素

4)被遗忘的定时器和回调函数

怎样避免内存泄漏

1)减少不必要的全局变量,或者生命周期较长的对象,及时对无用的数据进行垃圾回收;

2)注意程序逻辑,避免“死循环”之类的 ;

3)避免创建过多的对象  原则:不用了的东西要及时归还,对象用完赋值为null。

五十六、什么是闭包

https://github.com/WindrunnerMax/EveryDay/blob/master/JavaScript/JavaScript%E9%97%AD%E5%8C%85.md

闭包的作用是从函数的外部访问函数内部的变量

闭包就是利用“函数内部可以访问函数外部的变量”的特性而建立的

由于在Javascript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成"定义在一个函数内部的函数"。

所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁

示例:

function student(){
    var name = "Ming";
    var sayMyName = function(){ // sayMyName作为内部函数,有权访问父级函数作用域student中的变量
        console.log(name);
    }
    console.dir(sayMyName); // ... [[Scopes]]: Scopes[2] 0: Closure (student) {name: "Ming"} 1: Global ...
    return sayMyName; // return是为了让外部能访问闭包,挂载到window对象也可以 
}
var stu = student(); 
stu(); // Ming

 就是在函数内部在写一个函数表达式。读取函数下的变量再return给函数本身

闭包的缺点降低网页性能,所以能不用就不用

五十七、null和undefined的区别

undefined是所有仅声明但未赋值的变量默认值
null的空是专门修饰引用类型对象的空

五十八、css有哪些选择符?可继承的属性有哪些?css3新增的伪元素有哪些?css优先级的计算

选择符

1.id选择器
2.类选择器
3.标签选择器
4.相邻选择器
5.子选择器
6.后代选择器
7.通配符选择器,也称全局选择器
8.属性选择器
9.伪类选择器

可继承的属性有哪些?(子标签继承父标签)

  1. text-*
  2. font-*
  3. color-*
  4. ……

优先级算法

1.优先级就近原则,同权重情况下样式定义最近者为准;
2.载入样式以最后载入的定位为准;
3.!important > id > class > tag
4.important 比 内联优先级高,但内联比 id 要高

不可继承的属性有哪些

边框、内外边距’、高宽

css3新增伪类

p:first-of-type:选择属于其父元素的首个p元素的每个p元素。
p:last-of-type:选择属于其父元素的最后p元素的每个p元素。
p:only-of-type:选择属于其父元素唯一的p元素的每个p元素。
p:only-child:选择属于其父元素的唯一子元素的每个p元素。
p:nth-child(2):选择属于其父元素的第二个子元素的每个p元素。
:enabled: disabled 控制表单控件的禁用状态。
:checked: 单选框或复选框被选中。

五十九、link和@import的区别

摘自【前端】link 和 @import 的区别_Dora_5537的博客-CSDN博客

link和@import 的区别( link 属于 XHTML 标签,而 @import 是 CSS 提供的)

1. 引用的方式不同:

link(外部引用): <link rel="stylesheet" href="xxx.css"  type="text/css" />
 
@import(导入式): @import url(xxx.css);

2. 放置的位置不同:link 一般放在 head 标签中,而 @import 必须放在 <style  type="text/css"> 标签中。

3. 加载方式不同:link 会和 dom 结构一同加载渲染,而 @import 只能等 dom 结构加载完成以后才能加载渲染页面。

4. 兼容性不同:@import 只能在 IE6 以上才能识别,而 link 是 XHTML 标签,无兼容问题。

5. 样式权重不同:link 方式的样式的权重高于 @import。

6. 改变样式:link 支持使用 JavaScript 改变样式,而 @import 不可以。

7. 加载内容不同:link 除了可以加载 css 文件以外,还可以加载 MIME 类型的文件;而 @import 只能加载 css 文件。

六十、浏览器如何实现不同标签页的通信?

1、localstorage

2、Websocket

六十一、iframe的优缺点

摘自浅谈iframe的优缺点及应用场景_baxiadsy_csdn的博客-CSDN博客_iframe的优缺点

优点: 

1.iframe能够把嵌入的网页原样展现出来;

2.模块分离,便于更改,如果有多个网页引用iframe,只需要修改iframe的内容,就可以实现调用的每一个页面内容的更改,方便快捷;

3.网页如果为了统一风格,头部和版本都是一样的,就可以写成一个页面,用iframe来嵌套,增加代码的可重用;

4.如果遇到加载缓慢的第三方内容如图标和广告,这些问题可以由iframe来解决;

5.重载页面时不需要重载整个页面,只需要重载页面中的一个框架页;

6.方便制作导航栏。

缺点: 

1.样式和脚本需要额外链入,调用外部页面,需要额外调用css,增加页面额外的请求次数,增加服务器的http请求;

2.代码复杂,在网页中使用框架结构最大的弊病是搜索引擎的“蜘蛛”程序无法解读这种页面,会影响搜索引擎优化,不利于网站排名;

3.框架结构有时会让人感到迷惑,滚动条除了会挤占有限的页面空间外会使iframe布局混乱,还会分散访问者的注意力,影响用户体验;

4.链接导航疑问。运用框架结构时,必须保证正确配置所有的导航链接,否则,会给访问者带来很大的麻烦。比如被链接的页面出现在导航框架内,这种情况下访问者便被陷住了,因为此时他没有其他地点可去; 

5.产生多个页面,不易管理;

6.多数小型的移动设备(PDA 手机)无法完全显示框架,设备兼容性差。

六十一、js 的继承实现方式有哪些

JS实现继承的几种方式_星河·的博客-CSDN博客_js 实现继承

六十二、eval是什么?

1、eval是js中最强大的方法之一,它就像一个完整的ECMAScript解析器,它会根据ECMAScript语句对字符串进行解析和计算。

2、eval中的所有变量声明和函数声明都不会增加。

示例:

eval("x=10;y=20;console.log(x*y)");//21
console.log(eval("2+2"));//4
var x=10;
console.log(eval(x+17));//27

六十三、用什么会导致内存泄漏

摘自什么操作会造成内存泄漏?_爱学习的小欣欣的博客-CSDN博客_哪些操作会导致内存泄露

1. 使用未声明的变量,而意外的创建了一个全局变量,而使这个变量一直留在内存中无法被回收。

2. 设置了 setInterval 定时器,而忘记取消它,如果循环函数有对外部变量的引用的话,那么这个变量会被一直留在内存中,而无法被回收。

3. 获取一个 DOM 元素的引用,而后面这个元素被删除,由于我们一直保留了对这个元素的引用,所以它也无法被回收。

4. 不合理的使用闭包,从而导致某些变量一直被留在内存当中。

六十四、什么是BFC

摘自JavaScript中BFC的使用_南风花海的博客-CSDN博客_bfc js

BFC(Block formatting context)

直译为块级格式化上下文,把BFC理解成一块独立的渲染区域,BFC看成是元素的一种属性, 当元素拥有了BFC属性后,这个元素就可以看做成隔离了的独立容器。容器内的元素不会影响容器外的元素

BFC属于普通流

    把BFC理解成一块独立的渲染区域,BFC看成是元素的一种属性, 当元素拥有了BFC属性后,这个元素就可以看做成隔离了的独立容器。

如何触发BFC

        1.根元素 (<html>)

        2.浮动元素(元素的float值不是none)

        3.绝对定位(元素的position为absolute或fixed)

        4.display为inline-block、table-cell、table-caption、table、table-row、table-row-group、

        table-header-group、table-footer-group、inline-table、flow-root、flex或 inline-flex、grid或 inline-grid

        5.overflow值不为visible的元素 即为 overflow:hidden;

        6.contain的值为layout-content,paint的元素

BFC特性和作用

        1.可以避免外边距重叠,margin击穿

        2.解决高度塌陷

        3.阻止元素被浮动元素覆盖

六十五、css样式不生效怎么办

1、html标签没有写完整

2、样式被覆盖,用!important检查

3、css语法错误,单词拼错了

4、css表编码错误,用utf-8再保存一下

5、浏览器缓存问题,清除缓存重启浏览器

6、有一些属性无效和元素类别有关,用display:block

7、样式表关联问题,尝试给body加背景颜色,可以查得出来

 六十六、什么是事件委托?优点缺点有哪些?

        事件委托的核心是,利用js的冒泡和事件targert属性。例如给ul标签绑定点击事件,可以触发li标签上的点击事件

事件委托优点:

1、减少事件注册,节省内存。比如,在table上代理所有td的click事件,在ul上代理所有li的click事件。

2、简化了dom节点更新时,相应事件的更新。比如不用在新添加的li上绑定click事件,当删除某个li时,不用移解绑上面的click事件。

事件委托缺点:

1、事件委托基于冒泡,对于不冒泡的事件不支持

2、层级过多,冒泡过程中,可能会被某层阻止掉。

3、理论上委托会导致浏览器频繁调用处理函数,虽然很可能不需要处理。所以建议就近委托,比如在table上代理td,而不是在document上代理td。

4、把所有事件都用代理就可能会出现事件误判。比如,在document中代理了所有button的click事件,另外的人在引用改js时,可能不知道,造成单击button触发了两个click事件。

六十七、箭头函数和普通函数区别?

1、箭头函数更加简洁

2、箭头函数没有自己的this,只会在自己作用域的上一层继承this。所以箭头函数中this的指向在它在定义时已经确定了,之后不会改变。

3、call()、apply()、bind()等方法不能改变箭头函数中this的指向

4、箭头函数不能作为构造函数使用,因为没有prototype

5、箭头函数没有自己的arguments(伪数组),在箭头函数中访问arguments实际上获得的是它外层函数的arguments值

六十八、请大概讲一下JS的执行机制

摘自JS执行机制_js中执行机制_FG.的博客-CSDN博客

1、单线程

2、同步和异步

3、宏任务和微任务

具体示例分析:

 链接:依次点击4个li标签,哪一个选项是正确的运行结果?_搜狗笔试题_牛客网
来源:牛客网

这里考的是JS的运行机制! 事件(click,focus等等),定时器(setTimeout和setInterval),ajax,都是会触发异步,属于异步任务;js是单线程的,一个时间点只能做一件事,优先处理同步任务; 按照代码从上往下执行,遇到异步,就挂起,放到异步任务里,继续执行同步任务,只有同步任务执行完了,才去看看有没有异步任务,然后再按照顺序执行!这里for循环是同步任务,onclick是异步任务,所以等for循环执行完了,i变成4了,注意:这里因为i是全局变量,最后一个i++,使得i为4(后面的onclick函数,最后在循环外面执行,不受i<length限制); 所以for循环每执行一次,onclick事件函数都会被挂起一次,共4次; for循环结束后,点击事件 触发了4个onclick函数,接着输出4个4!

六十九、为什么不推荐使用行内样式

1、多个元素样式相同时,style会让代码大量重复,既冗余又不好维护

2、style需要预留给js控制,优先级比class或者id更高

3、样式和内容混杂在一起,不符合规范,不利于维护

4、影响网页性能

5、单独写一个样式文件,可以在浏览器建立缓存,二次访问更快

引用css的三种方式

1、外部样式表,link

2、内部样式表(嵌入式),写在head>style

3、行内样式表

七十、HTTP状态码

1xx,表示服务器收到请求,但是还没有返回

2xx,请求成功
200表示请求成功,一般在GET和POST请求中可以见到;

3xx,重定向,如302,服务器告诉客户端,我这里不行,并给了客户端另一个地址去访问
302表示临时重定向(配合location,浏览器自动处理),每一次访问都会访问到老域名,再跳转到新域名。服务端的响应头返回302状态码,并且附加location,浏览器自动跳转location
301表示永久重定向,(配合location,浏览器自动处理),比如说域名到期了,老域名永远不用了,永久跳转到新域名
304表示所请求的资源并未修改

4xx,客户端错误,如404
403表示没有权限,服务器拒绝执行客户端的请求,比如没有登录就要访问主页
404表示服务器找不到客户端所请求的资源(网页)

5xx,服务端错误,如500
500表示服务器内部错误,例如服务器死机了
504表示网关超时,例如服务器连接数据库超时

七十一、export和export default?

摘自export default 和 export 区别_转角羊儿的博客-CSDN博客

1.export与export default均可用于导出常量、函数、文件、模块等

2.你可以在其它文件或模块中通过import+(常量 | 函数 | 文件 | 模块)名的方式,将其导入,以便能够对其进行使用

3.在一个文件或模块中,export、import可以有多个,export default仅有一个

4.通过export方式导出,在导入时要加{ },export default则不需要

七十二、computed、watch、methods

computed

computed适用于一个数据受多个数据影响,例如购物车,总价受数量,单价,折扣等等影响
计算属性具有缓存属性,属于响应式依赖进行缓存,如果其中的没有值改变,则它调用的就是上一次 计算缓存的数据,只有在它的相关依赖发生改变时才会重新求值,因此提高了性能。

watch

watch更多的是观察的作用,无缓存性,类似于某些数据的监听回调,每 当监听的数据变化时都会执行回调进行后续操作。

当我们需要在数据变化时执行异步或开销较大的操作时,应该使用 watch,使用 watch 选项允许我们执行异步操作 ( 访问一个 API ),限制我们执行该操作的频率, 并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的

一个数据影响多个数据,例如搜索数据

methods

页面只要重新发生渲染就会被调用

七十三、call、apply、bind

首先,call apply bind三个方法都可以用来改变函数的this指向,具体区别如下:

1、fn.call (newThis,params) call函数的第一个参数是this的新指向,后面依次传入函数fn要用到的参数。会立即执行fn函数。

2、fn.apply (newThis,paramsArr) apply函数的第一个参数是this的新指向,第二个参数是fn要用到的参数数组,会立即执行fn函数。

3、fn.bind (newThis,params) bind函数的第一个参数是this的新指向,后面的参数可以直接传递,也可以按数组的形式传入。不会立即执行fn函数,且只能改变一次fn函数的指向,后续再用bind更改无效。返回的是已经更改this指向的新fn

七十四、说一说map 和 forEach 的区别?

map有返回值,可以开辟新空间,return出来一个length和原数组一致的数组,即便数组元素是undefined或者是null

forEach默认无返回值,返回结果为undefined,可以通过在函数体内部使用索引修改数组元素

map的处理速度比forEach快,而且返回一个新的数组,方便链式调用其他数组新方法,比如

filter、reduce let arr = [1, 2, 3, 4, 5];

let arr2 = arr.map(value => value * value).filter(value => value > 10);

// arr2 = [16, 25]

需要得到新数组就用map,单纯修改数组元素可以使用forEach。都可以用则优先使用map,因为map执行起来更快

七十五、说一说事件循环Event loop,宏任务与微任务?

执行js代码的时候,遇见同步任务,直接推入调用栈中执行,遇到异步任务,将该任务挂起,等到异步任务有返回之后推入到任务队列中,当调用栈中的所有同步任务全部执行完成,将任务队列中的任务按顺序一个一个的推入并执行,重复执行这一系列的行为。

异步任务又分为宏任务和微任务。

宏任务:任务队列中的任务称为宏任务,每个宏任务中都包含了一个微任务队列。

微任务:等宏任务中的主要功能都完成后,渲染引擎不急着去执行下一个宏任务,而是执行当前宏任务中的微任务

宏任务包含:执行script标签内部代码、setTimeout/setInterval、ajax、postMessageMessageChannel、setImmediate,I/O(Node.js)

微任务包含:Promise、MutonObserver、Object.observe、process.nextTick(Node.js)

同步任务执行完了,再执行异步任务。异步任务分为宏任务和微任务,宏任务包含微任务,宏任务下的微任务执行完毕后,再执行下一个宏任务

七十六、说一说new会发生什么

1. 创建一个空的简单JavaScript对象(即`{}`)

2. 为步骤1新创建的对象添加属性`__proto__`,将该属性链接至构造函数的原型对象

3. 将步骤1新创建的对象作为`this`的上下文

4. 如果该函数没有返回对象,则返回`this`

七十八、说一下token 能放在cookie中吗

token简要

token一般是用来判断用户是否登录的,它内部包含的信息有:uid(用户唯一的身份标识)、time(当前时间的时间戳)、sign(签名,token 的前几位以哈希算法压缩成的一定长度的十六进制字符串)

`token`可以存放在`Cookie`中,`token` 是否过期,应该由后端来判断,不该前端来判断,所以`token`存储在`cookie`中只要不设置`cookie`的过期时间就ok了,

如果 `token` 失效,就让后端在接口中返回固定的状态表示`token` 失效,需要重新登录,再重新登录的时候,重新设置 `cookie` 中的 `token` 就行

token认证流程

1. 客户端使用用户名跟密码请求登录

2. 服务端收到请求,去验证用户名与密码

3. 验证成功后,服务端签发一个 token ,并把它发送给客户端

4. 客户端接收 token 以后会把它存储起来,比如放在 cookie 里或者 localStorage 里

5. 客户端每次发送请求时都需要带着服务端签发的 token(把 token 放到 HTTP 的 Header 里)

6. 服务端收到请求后,需要验证请求里带有的 token ,如验证成功则返回对应的数据

token放在cookie中可能造成csrf问题

1.实现上是可以的,功能上不推荐,容易产生csrf问题
2.token一般存储在sessionStorage/localStorage里面。token的出现就是为了解决用户登录后的鉴权问题,如果采用cookie+session的鉴权方式,则无法有效地防止CSRF攻击,同时,如果服务端采用负载均衡策略进行分布式架构,session也会存在一致性问题,需要额外的开销维护session一致性。

七十九、说一下浏览器输入URL发生了什么

1、输入url后,浏览器会先查找本地是否有缓存,有则直接返回并渲染缓存内容

2、获取域名对应的IP地址,建立tcp连接。

host文件中有对应的IP地址,则直接建立tcp连接。没有则进入DNS解析,将域名解析成IP地址

3、和服务器建立tcp连接后,也就是三次握手。浏览器会封装数据包,(包含请求行,请求头,请求正文,并把该域名相关Cookie等数据附加到请求头),发起请求

4、服务器接收到请求后,会封装响应数据(括响应行,响应头,响应正文),返回给浏览器

数据传输完成后,TCP四次挥手断开连接

5、如果顺利,会直接开始渲染页面了

八十、说一说性能优化有哪些性能指标,如何量化?

1.性能评估 Chrome Performance选项卡 / Lighthouse 生成性能检测报告
2.值得关注的性能指标
(1)LCP (Largest Contentful Paint 最大内容绘制 )
(2)首屏渲染时间(也叫白屏时间)
(3)FCP (Fitst Contentful Paint 首先内容绘制 )
(4)可交互时间 (Time to Interactive TTI)
(5) Network请求时间(jax,js等)
3.浏览器开发者工具什么都能看得到,可以调用性能监测API 或建立 前端监控系统(无痕埋点)

八十一、js创建对象的几种方式

Javascript创建对象的七种常用方式_js创建对象的几种方式_老年的程序员的博客-CSDN博客

1、通过{}创建对象

2、通过new Object()创建对象

3、使用字面量创建对象

小结:前面三种创建对象的方式存在2个问题:1.代码冗余; 2.对象中的方法不能共享,每个对象中的方法都是独立的。

4、使用工厂模式创建对象

5、通过构造函数创建对象

小结:解决了前三种方式的代码冗余的问题,但是方法不能共享的问题还是存在

6、通过原型模式创建对象

每个方法中都有一个原型(prototype),每个原型都有一个构造器(constructor),构造器又指向这个方法。

通过原型创建对象,把属性和方法绑定到prototype上,通过这种方式创建对象,方法是共享的,每个对象调用的是同一个方法

这种方式创建的对象会存在问题,假如原型中包含有引用类型的属性,那么如果某个对象修改了该属性的值,所有的该原型创建的对象访问的值都会改变。

7、通过原型+构造函数的方式创建对象

属性定义在构造函数里面,方法定义在原型protype上

这种方式结合了上面两种方式,解决了代码冗余,方法不能共享,引用类型改变值的问题

八十二、给出一个空数组或空对象,怎么判断为空?

Javascript创建对象的七种常用方式_js创建对象的几种方式_老年的程序员的博客-CSDN博客

1、对象转换成字符串,再判断是否等于"{}"

2、for in 循环

3、Object.keys()方法,返回对象的属性名组成的一个数组,若长度为0,则返回空对象(ES6写法)

4、Object.getOwnPropertyNames()方法获取对象的属性名,存到数组中,如果长度为0,则为空对象

5、jQuery中的isEmptyObject()方法,其原理是利用for in方式来判断(注意:使用这种方式记得引用jQuery)

八十三、flex布局       

问到flex布局时,可以从主轴副轴说起

        flex-direction设置主轴方向

        flex-wrap设置元素查出容器范围,是否换行

        flew-flow就是前两个属性的集合

        justify-content,设置元素在主轴方向上的对齐方式

        align-items,设置元素在副轴上的对齐方式

        align-content,存在多跟副轴线时,设置元素在副轴对齐方式

        flex属性是 flex-grow属性、flex-shrink属性、flex-basis属性的简写。默认值为:0 1 auto
        
flex:(0 1 auto) | auto(1 1 auto) | none (0 0 auto)

        order属性设置项目排序的位置,默认值为0,数值越小越靠前

        align-self属性表示当前项目可以和其他项目拥有不一样的对齐方式

八十四、html元素

块元素

a)块元素以块的形式显示为一个矩形区域,默认不设置宽度时,继承父元素的宽度

b)块元素默认情况下,独占一行,自上而下排列

c)块元素可以定义自己的宽度和高度,以及盒模型中的任意属性(margin,padding,border)

d)块元素可以作为一个容器容纳其他的块元素和内联元素

行内元素

a)行元素也显示为一个矩形区域,但是宽高由内容来决定

b)行元素默认情况下在一行逐个进行显示

c)行元素不能定义自己的宽度和高度,可以定义与宽度相关的属性(左右margin,左右padding等),不可以定义与高度相关的一下属性(上下margin,上下padding,line-height等)与IFC有关

d)行元素只能嵌套内联元素,不能嵌套块元素

行内块元素

a)即具有行元素特点:在一行逐个进行显示

b)又具有块元素的特点:可以定义宽高以及盒模型中的任意属性

浮动和定位对元素类型的影响

浮动和绝对定位的元素等同于inline-block的效果,会转换元素类型

相对定位和绝对定位都会提升元素的层级

相对定位不会改变元素的性质(行内仍然行内,块仍然块)

绝对定位不区分块还是行内还是行内块,也就是块元素不会独占一行了,行内元素可以设置宽高等

八十五、vue钩子函数 

钩子函数按照组件生命周期的过程分为,挂载阶段=>更新阶段=>销毁阶段
new Vue() --->初始化生命周期

挂载阶段

beforeCreate、created、beforeMounted、mounted

created:实例创建完成,可访问data、computed、watch、methods上的方法和数据,未挂载到DOM,不能访问到el属性,el属性,ref属性内容为空数组,常用于简单的ajax请求,页面的初始化

beforeMount:在挂载开始之前被调用,beforeMount之前,会找到对应的template,并编译成render函数 mounted

mounted:实例挂载到DOM上,此时可以通过DOM API获取到DOM节点,$ref属性可以访问常用于获取VNode信息和操作,ajax请求

更新阶段

beforeUpdate、updated

beforeupdate:响应式数据更新时调用,发生在虚拟DOM打补丁之前,适合在更新之前访问现有的DOM,比如手动移除已添加的事件监听器

updated:虚拟 DOM 重新渲染和打补丁之后调用,组件DOM已经更新,可执行依赖于DOM的操作避免在这个钩子函数中操作数据,可能陷入死循环

销毁阶段

beforeDestroy、destroyed

beforeDestroy:实例销毁之前调用。这一步,实例仍然完全可用,this仍能获取到实例,常用于销毁定时器、解绑全局事件、销毁插件对象等操作

激活阶段

activeted、deactivated

因为keep-alive会将组件保存在内存中,并不会销毁以及重新创建,所以不会调用组件的created,destroyed方法,需要用activated与deactivated这两个生命钩子来得知当前组件是否处于活动状态。

组件一旦被keep-alive缓存,那么再次渲染的时候就不会执行 created、mounted 等钩子函数。使用keep-alive组件后,被缓存的组件生命周期会多activated和deactivated 两个钩子函数,它们的执行时机分别是keep-alive包裹的组件激活时调用和停用时调用。

被keep-alive包裹的组件,会被缓存
如<keep-alive>包裹两个组件:组件A和组件B。当第一次切换到组件A时,组件A的created和activated生命周期函数都会被执行,这时通过点击事件改变组件A的文字的颜色,在切换到组件B,这时组件A的deactivated的生命周期函数会被触发;在切换回组件A,组件A的activated生命周期函数会被触发,但是它的created生命周期函数不会被触发了,而且A组件的文字颜色也是我们之前设置过的。

父子组件钩子函数在三个阶段的代码执行顺序

挂载:父亲created> 子created > 子mounted> 父亲mounted>

销毁:父亲beforeDestroy> 子beforeDestroy > 子destroyed> 父destroyed

父组件更新:父beforeUpdate —> 子beforeUpdate —> 子updated —> 父updated

子组件更新:父beforeUpdate —> 子beforeUpdate —> 子updated —> 父updated

八十六、判断数据类型

typeof

只能判断基本数据类型和函数类型

instance of

只能判断引用数据类型,可以更改,会不准确

Object.prototype.toString.call()

最实用

isArray()

判断是否是数组对象

constructor

可以被更改,导致不准确

八十七、axios特点

(1)axios 是一个基于promise的HTTP库,支持promise所有的API

(2)浏览器端/node端(服务器端)都可以使用,浏览器中创建XMLHttpRequests

(3)支持请求/响应拦截器

(4)它可以转换请求数据和响应数据,并对响应回来的内容自动转换成 JSON类型的数据

(5)批量发送多个请求

(6)安全性更高,客户端支持防御XSRF

八十八、请求头和响应头

请求头(request)

Accept,浏览器可接收的数据格式
Accept-Encoding,浏览器可接收的压缩算法,如gzip
Accept-Language,浏览器可接收的语言,如zh-CN
Connection:keep-alive,一次tcp连接重复使用
cookie,只要是同域,不是跨域,都会将cookie加入请求头中
host,请求的域名
User-Agent,简称UA,浏览器信息

响应头(Response)

Content-Type,返回数据的格式
Content-Length,返回数据的字节大小
Content-Encoding,返回数据的压缩算法,如gzip
Set-Cookie,服务端改cookie

自定义响应头和请求头

可以自定义添加请求头或响应头中字段,只要不和现有的重复即可

缓存相关的headers

Cache-Control        Expires
Last-Modifed        If-Modified-Since
Etag        If-None-Match

八十九、http缓存

页面加载速度中,http请求是大头,为了提高加载效率,将一些js,css,图片等缓存在浏览器端,下一次就不用重新请求这些资源了。html可能随时被更新,需要保证每次请求到最新的页面

Cache-Control

服务端会判断请求的资源是否需要被缓存,需要被缓存,就在响应头中加入Cache-Control
Cache-Control:Max-Age=10000,单位是秒。超出缓存时间后,会重新请求资源
Cache-Control:no-cache,不用缓存,正常请求
Cache-Control:no-store,既不用服务端缓存,也不用客户端缓存

关于expires
同在响应头中,同为控制缓存,但是已经被Cache-Control替代了

 协商缓存

服务端缓存策略,指服务端判断是否需要缓存,而不是缓存在服务端
服务端判断客户端资源,是否和服务端资源一样,一致则不需要重新请求,返回304。不一样则重新请求,返回200

资源标识在响应头中,且有两种
Last-Modifed,资源的最后修改时间
Etag,资源的唯一标识,(一个字符串,相对于指纹)

策略会优先使用Etag
Last-Modifed只能精确到秒级
如果资源被重复生成,而内容不变,则Etag更精确

 

 

 三种刷新策略

正常操作,地址栏输入url,跳转链接,前进后退等
强制缓存,协商缓存都有效

手动刷新,F5,点击刷新按钮,右击菜单刷新
强制缓存失效,协商缓存有效

强制刷新,ctrl+F5
强制缓存,协商缓存都失效

九十、深拷贝

 /**
  * 深拷贝 - 只考虑了简单的数组、对象
  * @param obj obj
*/
function cloneDeep(obj: any) {
    if (typeof obj !== 'object' || obj == null ) return obj

    let result: any
    if (obj instanceof Array) {
        result = []
    } else {
        result = {}
    }

    for (let key in obj) {
        if (obj.hasOwnProperty(key)) {            
            result[key] = cloneDeep(obj[key]) // 递归调用
        }
    }

    return result
}
/**
 * 深拷贝
 * @param obj obj
 * @param map weakmap 为了避免循环引用
 */
export function cloneDeep(obj: any, map = new WeakMap()): any {
    if (typeof obj !== 'object' || obj == null ) return obj

    // 避免循环引用
    const objFromMap = map.get(obj)
    if (objFromMap) return objFromMap

    let target: any = {}
    map.set(obj, target)

    // Map
    if (obj instanceof Map) {
        target = new Map()
        obj.forEach((v, k) => {
            const v1 = cloneDeep(v, map)
            const k1 = cloneDeep(k, map)
            target.set(k1, v1)
        })
    }

    // Set
    if (obj instanceof Set) {
        target = new Set()
        obj.forEach(v => {
            const v1 = cloneDeep(v, map)
            target.add(v1)
        })
    }

    // Array
    if (obj instanceof Array) {
        target = obj.map(item => cloneDeep(item, map))
    }

    // Object
    for (const key in obj) {
        const val = obj[key]
        const val1 = cloneDeep(val, map)
        target[key] = val1
    }

    return target
}

九十一、防抖与节流

防抖使用场景

  1. 按钮点击太快,重复请求,需要防抖
  2. 调整浏览器窗口大小,resize次数太频繁,计算太多,需要防抖
  3. 搜索框搜索输入,不需要每输入一个字就进行搜索
    let ipt=document.querySelector("input");
    let btn=document.querySelector("button");

    const debounce=(()=>{
        let timer=null;
        return (callback,delay)=>{
            if(timer)clearTimeout(timer);
            timer=setTimeout(callback,delay);
        }
    })();

    btn.addEventListener('click',function(){
        debounce(()=>{
            console.log(ipt.value);
        },2000)
    })

节流使用场景

  1. scroll事件,每隔一秒计算一次位置信息
    let ipt = document.querySelector("input");
    const throttle = (() => {
        let last = 0;
        return (callback, delay) => {
            let now = +new Date();
            if (now - last > delay) {
                callback();
                last = now;
            }
        }
    })()
    ipt.addEventListener('input', function () {
        throttle(() => {
            if (ipt.value == "") return;
            console.log(ipt.value)
        }, 300)
    })

防抖与节流的区别 

防抖是指定时间内只触发一次函数,指定时间内两次触发,会重新计算时间

节流是指定时间内只触发一次函数,指定时间内两次触发,不会重新计算时间

函数防抖一定连续触发的事件,只在最后执行一次,而函数节流一段时间内只执行一次。

九十二、Promise加载一张图片

        function loadImg(src){
            return new Promise(
                (resolve,reject)=>{
                    const img = document.createElement('img');
                    img.src=src;
                    img.onload=()=>{
                        resolve(img)
                    }
                    img.onerror=()=>{
                        reject(new Error(`图片加载失败${src}`))
                    }
                }
            )
        }
        let url="https://img-home.csdnimg.cn/images/20201124032511.png";
        loadImg(url).then(img=>{
            console.log(img.width)
            return img
        }).then(img=>{
            console.log(img.height)
        }).catch(err=>{
            console.log(err)
        })

九十三、property和attribute区别

https://www.cnblogs.com/lmjZone/p/8760232.html

Attribute就是dom节点自带的属性,例如html中常用的id、class、title、align等

Property是这个DOM元素作为对象,其附加的内容,例如childNodes、firstChild等

attributes是属于property的一个子集

九十四、跨域

同源策略

发起请求时,当前网页和server必须同源,也就是协议,域名,端口三者必须一致
加载js。图片等,可以直接跨域,无视同源策略

跨域可以通过JSONP

  1. script可以绕过跨域限制
  2. 服务器可以任意动态拼接数据返回
  3. script可以获取跨域的数据,只要服务端愿意返回

跨域还可以通过后端的cros,不需要了解

九十五、浏览器输入url地址会发生什么

DNS解析,将域名解析成IP地址
浏览器根据IP地址向对应的服务器发出请求
服务器处理http请求,并返回给浏览器进行渲染
根据html代码,生成DOM tree
根据CSS代码,CSSOM(css代码放head中,否则会造成二次渲染)
DOM tree和CSSOM进行整合,生成Render tree开始渲染页面
遇到script代码,则暂停渲染,优先加载js代码(js和页面渲染是同一个进程,所以js放最下面)

window.onload,会在所有页面内容加载完后执行
window.onDOMContentLoaded,会在DOM结构生成后执行,不用等待图片,视频等

九十六、[10 , 20 , 30].map(parseInt)

结果:[10 , NaN , NaN] 

parseInt('1', 0) // 1 ,radix === 0 按 10 进制处理
parseInt('2', 1) // NaN ,radix === 1 非法(不在 2-36 之内)
parseInt('3', 2) // NaN ,2 进制中没有 3

九十七、如何实现可过期的localstorage数据

惰性删除

惰性删除是指某个键值过期后,该键值不会被马上删除,而是等到下次被使用的时候,才会被检查到过期,此时才能得到删除。

实现方法是,存储的数据类型是个对象,该对象有两个key,一个是要存储的value值,另一个是当前时间。获取数据的时候,拿到存储的时间和当前时间做对比,如果超过过期时间就清除Cookie

定时删除

定时删除是指,每隔一段时间执行一次删除操作,并通过限制删除操作执行的次数和频率,来减少删除操作对CPU的长期占用。另一方面定时删除也有效的减少了因惰性删除带来的对localStorage空间的浪费。

实现过程,获取所有设置过期时间的key判断是否过期,过期就存储到数组中,遍历数组,每隔1S(固定时间)删除5个(固定个数),直到把数组中的key从localstorage中全部删除

九十八、前后端如何保持通信

前后端一般通过HTTP协议进行交互,但HTTP协议是基于“问答模式”的,即客户端发起询问,服务端才会响应。但对于一些实时的场景,比如股票趋势图、直播...等,服务端更新数据的速度很快,如果每次都要客户端询问,这样传输数据的效率十分低下,所以得通过其它交互模式支持实时通信。以下是主要方式:

短轮询

轮询是客户端和服务器之间会一直进行连接,每隔一段时间就询问一次。

缺点:

  • 连接数会很多,一个接受,一个发送。而且每次发送请求都会有Http的Header,会很耗流量,也会消耗CPU的利用率。
  • 轮询的间隔过长,会导致用户不能及时接收到更新的数据;
  • 轮询的间隔过短,会导致查询请求过多,增加服务器端的负担

优点:

  • 实现简单,无需做过多的更改。

长轮询

长轮询是对轮询的改进版,客户端发送HTTP给服务器之后,如果没有新消息,就一直等待。有新消息,才会返回给客户端。

缺点:

  • 由于http数据包的头部数据量往往很大(通常有400多个字节),但是真正被服务器需要的数据却很少(有时只有10个字节左右),这样的数据包在网络上周期性的传输,难免对网络带宽是一种浪费。
  • 缺点是保持连接会消耗资源
  • 服务器没有返回有效数据,程序超时

优点:

  • 相较于短轮询,做了优化,有较好的时效性。在某种程度上减小了网络带宽和CPU利用率等问题。

iframe

在页面中插入一个隐藏的iframe,利用其src属性在服务器和客户端之间创建一条长连接,服务器向iframe传输数据(通常是HTML,内有负责插入信息的javascript),来实时更新页面。

优点

  • 是消息能够实时到达
  • 浏览器兼容好。

缺点

  • 服务器维护一个长连接会增加开销
  • IE、chrome、Firefox会显示加载没有完成,图标会不停旋转。

WebSocket

一种全双工通信协议,客户端和服务端处于相同的地位。通过客户端与服务端建立的HTTP连接进行切换,客户端会发送一个带update:websocket字段的HTTP请求请求协议切换,服务端会回复带101状态码的响应表示协议切换成功。接着它们使用websocket进行通信,一旦有新的数据服务端可以直接发送给客户端。

优点

  • 在客户端断开WebSocket连接或Server端断掉连接前,不需要客户端和服务端重新发起连接请求。
  • 在海量并发和客户端与服务器交互负载流量大的情况下,极大的节省了网络带宽资源的消耗,有明显的性能优势,
  • 客户端发送和接受消息是在同一个持久连接上发起,实时性优势明显。

缺点

  • 浏览器支持程度不一致
  • 不支持断开重连

SSE(Server-Sent Event)

建立在浏览器与服务器之间的通信渠道,然后服务器向浏览器推送信息。

缺点

  • SSE 是单向通道,只能服务器向浏览器发送,因为 streaming 本质上就是下载。

优点

  • 使用 HTTP 协议,现有的服务器软件都支持
  • 属于轻量级,使用简单
  • 默认支持断线重连;

九十九、CSRF与XSS

CSRF跨站点请求伪造(Cross Site Request Forgery),攻击者盗取用户的身份,发送恶意请求

用户打开浏览器,访问目标网站A,输入用户名和密码请求登录 - 用户信息在通过认证后,网站A产生一个cookie信息返回给浏览器,这个时候用户以可正常发送请求到网站A - 用户在没有退出网站A之前在同一个浏览器打开了另一个新网站B。 - 新网站B收到用户请求之后返回一些攻击代码,并发出一个请求要求访问返回cookie的网站A - 浏览器收到这些攻击性代码之后根据新网站B的请求在用户不知道的情况下以用户的权限操作了cookie并向网站A服务器发起了合法的请求

 预防CSRF攻击主要有以下策略

  1. 使用验证码,在表单中添加一个随机的数字或者字母验证码,强制要求用户和应用进行直接的交互。
  2. HTTP中Referer字段,检查是不是从正确的域名访问过来,它记录了HTTP请求的来源地址。
  3. 使用token验证,在HTTP请求头中添加token字段,并且在服务器端建立一个拦截器验证这个token,如果token不对,就拒绝这个请求

XSS是跨站脚本攻击(Cross Site Scripting),不写为CSS是为了避免和层叠样式表(Cascading Style Sheets)的缩写混淆,所以将跨站脚本攻击写为XSS 。攻击者可以通过向Web页面里面插入script代码,当用户浏览这个页面时,就会运行被插入的script代码,达到攻击者的目的

泄露用户的登录信息cookie

直接在页面中插入window.location.href进行恶意跳转。

预防XSS攻击主要有以下策略(不能信任用户输入内容,需要对输入内容做处理)

  1. 防御HTML节点内容,通过转义<为<以及>为>来实现防御HTML节点内容。
  2. 预防HTML属性,通过转义"->&quto来实现防御,一般不转义空格,但是这要求属性必须带引号。 
  3. 预防JavaScript代码,通过将数据进行JSON序列化
  4. 开启浏览器XSS防御,Http Only cookie,禁止 JavaScript 读取某些敏感 Cookie,攻击者完成XSS注入后也无法窃取此 Cookie

一百、vue 中使用了哪些设计模式

1、工厂模式 - 传入参数即可创建实例
虚拟 DOM 根据参数的不同返回基础标签的 Vnode 和组件 Vnode。
2、单例模式 - 整个程序有且仅有一个实例
vuex 和 vue-router 的插件注册方法 install 判断如果系统存在实例就直接返回掉。
3、发布-订阅模式。(vue 事件机制)
4、观察者模式。(响应式数据原理)
5、装饰器模式(@装饰器的用法)
6、策略模式,策略模式指对象有某个行为,但是在不同的场景中,该行为有不同的实现方案

一百零一、自适应和响应式的区别

自适应和响应式都是为了适应不同设备的屏幕大小而设计的。但是它们的实现方式不同。

自适应设计是指在设计时,为不同的设备设置不同的布局。例如,您可以为台式电脑设计一个布局,为平板电脑设计一个布局,为手机设计一个布局。这些布局是在设计时创建的,并且在不同的设备上显示不同的布局。

响应式设计是指在设计时,为不同的设备设置一个布局,但是该布局会根据设备的屏幕大小进行调整。这意味着您只需创建一个布局,该布局将自动适应不同的设备。这是通过使用媒体查询和流式布局来实现的。

因此,自适应设计需要为每个设备创建不同的布局,而响应式设计只需要创建一个布局,该布局将自动适应不同的设备。

一百零二、js模块化开发规范

总体上区分两大规范 CommonJS模块规范和ES6模块规范,node遵循的是CommonJS规范

1.module.exports 和exports 是Commonjs的规范
2.export 和export default 是es6 规范
3.require 是amd规范引入方式
4.import 是es6 的一个语法标准

ES6,export 或 export default  导出,import导入
CommonJS,module.exports 或 exports导出,require导入

JS模块导入导出规范-CommonJS | ES6 -规范案例_js导入规范有哪几种_JackieDYH的博客-CSDN博客

一百零三、vue路由守卫

  1. 导航被触发。
  2. 在失活的组件里调用 beforeRouteLeave 守卫。
  3. 调用全局的 beforeEach 守卫。
  4. 在重用的组件里调用 beforeRouteUpdate 守卫 (2.2+)。
  5. 在路由配置里调用 beforeEnter
  6. 解析异步路由组件。
  7. 在被激活的组件里调用 beforeRouteEnter
  8. 调用全局的 beforeResolve 守卫 (2.5+)。
  9. 导航被确认。
  10. 调用全局的 afterEach 钩子。
  11. 触发 DOM 更新。
  12. 调用 beforeRouteEnter 守卫中传给 next 的回调函数,创建好的组件实例会作为回调函数的参数传入。

完整的流程图如下 

一百零四、echarts相关面试题

有些公司有要求,只是一个小点,不再逐一大点列出

1. 请简述 ECharts 的核心思想是什么?
ECharts 的核心思想是数据驱动,即将数据转换为图表的视觉元素
2. 请简述 ECharts 的基本组成部分是什么?
数据、坐标系、系列和标记等。其中,数据是图表的基础,坐标系用于定义图表的坐标轴,系列是图表中的数据系列,标记用于标注图表中的特定点或区域。
3. 请简述 ECharts 的常用图表类型有哪些?
ECharts 支持多种类型的图表,包括折线图、柱状图、散点图、饼图、雷达图等。每种图表都有其特定的用途和优势,用户可以根据需要选择合适的图表类型
4. 请简述 ECharts 的数据格式是什么?
ECharts 的数据格式采用了一种简单的 JSON 格式,其中包含了数据系列、坐标轴、标记等信息。用户可以通过配置数据格式来实现不同类型的图表展示。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
React的生命周期是指组件在不同阶段会触发的一系列方法。下面是一些常见的有关React生命周期的面试题: 1. React组件的生命周期分为三个阶段,请问这三个阶段是什么? 答:React组件的生命周期分为挂载阶段(Mounting)、更新阶段(Updating)和卸载阶段(Unmounting)。 2. 请列举一些在组件挂载阶段触发的生命周期方法。 答:在组件挂载阶段,会触发以下生命周期方法: - constructor:组件实例化时调用,用于初始化状态和绑定事件。 - static getDerivedStateFromProps:从props中派生出新的state。 - render:渲染组件内容。 - componentDidMount:组件渲染完成后调用,通常用于发送网络请求或添加订阅。 3. 在组件更新阶段,哪些生命周期方法会被触发? 答:在组件更新阶段,会触发以下生命周期方法: - static getDerivedStateFromProps:接收新的props并返回一个新的state。 - shouldComponentUpdate:决定是否重新渲染组件,默认返回true。 - render:重新渲染组件内容。 - getSnapshotBeforeUpdate:获取更新前的DOM快照。 - componentDidUpdate:组件更新完成后调用,通常用于处理更新后的DOM操作或发送网络请求。 4. 当组件被卸载时,哪个生命周期方法会被触发? 答:组件被卸载时会触发 componentWillUnmount 生命周期方法,用于清理组件产生的副作用,如取消订阅或清除计时器。 这些是React生命周期的一些常见面试题,希望对你有帮助!如果还有其他问题,请继续提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值