前端开发面试-高频知识点汇总

我只是个小菜鸡,以下问题是我面试过程中的高频问题,有不对的地方欢迎批评指正~

HTML

1. src和href的区别

src用于替换当前元素,指向外部资源的位置,指向的内容将会嵌入到文档中标签所在位置,在请求资源时会将其指向的资源下载并应用到文档内,例如js脚本,img图片和frame等元素,浏览器解析该元素时,会暂停其他资源的下载和处理,直到该资源加载、编译、执行完毕(js简本挡在底部的原因);href用于在当前文档和引用资源之间确立联系,指向网络资源所在位置,建立链接。

2. 对HTML语义化的理解

根据内容的结构化,选择合适的标签,优点:对机器友好,带有语义的文字表现力丰富,适合爬虫爬取有效信息,有利于SEO;增强可读性,清晰地看到网页开发结构,便于团队的开发和维护。常见的语义化标签:header,nav,article,aside,footer,main。

CSS

1. css选择器及其优先级

!important达到最大优先级,内联样式:1000;id选择器:100;类选择器、伪类选择器、属性选择器:10;标签、伪元素选择器:1,继承的元素:0.1,通配符:0,

2. 行内和块级元素特点以及分别有哪些

行内元素:设置宽高无效,可以设置水平方向的margin和padding属性,不能设置垂方向的margin和padding,不会自动换行;块级元素:可以设置宽高,设置margin和padding都有效,可以自动换行。
行内元素:span,strong,em,br,img,input,label,select,textarea,cite
块级元素:div,p,from,ul,ol,dl,address,fieldset,hr,menu.table.

3. 对盒模型的理解

分为标准盒子模型和IE盒模型,由margin,border,padding和content组成,区别在于标准盒模型的width和height属性的范围只包含了content,IE盒模型的属性包含了border,padding和content,可以通过修改box-sizing属性来改变元素的盒模型,box-sizing:content-box表示标准盒模型,border-box表示怪异盒模型。

4. 两栏布局

一个定宽栏和一个自适应的栏并排展示存在,左侧宽度width一定,右侧width:100%;使用float左浮左边栏,右边模块使用margin-left撑出内容块做内容展示,为父级元素添加BFC,防止下方元素飞到上方内容;也可以使用flex弹性布局;侧边栏左浮动,正文overflow:auto,或者左侧定宽,右侧flex:1;绝对定位实现;纯浮动形式;浮动+常规流。

5. 伪元素和伪类的区别和作用

伪元素(::before/:before,::after,first-letter,first-line):在内容元素的前后插入额外的元或样式,但是这些元素实际上不在文档中生成,它们只在外部显示可见,但不会在文档的源代码中找到它们;伪类(:link,:hover,:focus,:first-child等):将特殊的效果添加到特定选择器上,它是已有元素上添加类别的,不会产生新的元素,区别在于:伪类是在元素选择器上加入伪类改变元素状态,而伪元素通过对元素的操作进行对元素的改变。

6. 什么是margin重叠问题,如何解决?

块级元素的上外边距和下外边距有时会合并(或折叠)为一个外边距,其大小取其中的最大者,这种行为称为外边距折叠,有时也翻译为外边距合并,浮动元素和绝对定位元素的外边距不会折叠。
原因:是由块级上下文决定的,垂直距离由margin决定。
解决方法:兄弟间重叠时,底部元素变为行内盒子(display:inline-block),底部元素设为float,底部元素position设为absolute或fixed;父元素与子元素重叠时,父元素加入(overflow:hidden),父元素添加透明框(border:1px solid transparent),子元素变为行内盒子(display:inline-block),子元素加入浮动属性或定位。

7. 重排和重绘

重排,也称回流,当DOM的变化影响了元素的集合信息(DOM对象的位置和尺寸大小),浏览器需要重新计算元素的几何属性,将其放在界面中的正确位置,这个过程叫重排,比如:添加或删除可见的DOM元素,元素尺寸改变;重绘指的是当一个元素的外观发生改变,但没有改变布局,重新把元素外观绘制出来的过程,叫做重绘,比如改变元素的color,background等属性。

javaScript

1. 数组有哪些原生方法

数组和字符串的转换方法:toString()、toLocalString()、join(),其中join()可以指定转换为字符串时的分隔符;
数组尾部操作的方法pop()和push()方法可以传入多个参数;
数组首部操作的方法shift()和unshift();
重排序的方法reverse()和sort(),sort()方法可以传入一个函数来进行比较,传入前后两个值,若返回值为正数,则交换两个数的位置;
数组连接的方法concat(),返回的是拼接好的数组,不影响原数组;
数组截取方法slice(),用于截取数组的一部分返回,不影响原数组;
数组插入方法splice(),影响原数组,与slice的区别是第一个参数都是截取数组的起始位置,但第二个参数不同,splice是截取的长度,而slice是结束的位置;查找特定项的索引的方法,indexOf()和lastIndexOf(),迭代方法every(),some(),filter(),map(),forEach();filter和map和forEach的区别是filter是指调用一个函数后过滤得到的元素,map指的是调用数组中每个元素都调用指定的函数返回的数组,forEach返回的是undefined。
数组归并方法reduce(),reduceRight(),前者从左到右,后者从右到左。
改变数组的方法有:fill(),pop(),push(), reverse(),shift(),unshift(),sort(),splice();
不改变数组的方法:slice,map,forEach,every,filter,reduce,entries,find.

2. 数组的遍历方法

forEach(),map(),fiter(),for...of..every(一个为false则返回false)和some(一个是true则返回true),find(返回第一个符合条件的值)和findIndex(返回的是第一个返回条件的值的索引值),reduce()和reduceRight()

3. js有哪些数据类型,它们的区别

js共有八种数据类型,分别是undefined,null,Boolean,number,string,object,symbol(代表创建后独一无二且不可变的数据类型,主要为了解决可能出现的全局变量冲突的问题),BigInt(表示任意精度格式的整数,可以安全地存储和操作大整数),后两者是ES6中新增的。
分为原始数据类型(栈),占据空间小、大小固定、频繁被使用数据;引用数据类型(堆),对象数组函数,占据空间大、大小不固定,若存在栈中,会影响程序运行的性能,引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址,当解释器寻找引用值时,会首先检索在栈中的地址,取得地址后从堆中获得实体。堆是一个优先队列,按优先级来排序,优先级可按照大小来规定。内存被分为栈区和堆区,栈区由编译器自动分配释放,存放函数的参数值,局部变量的值等,操作类似于数据结构中的栈,堆区内存一般由开发者分配释放,若开发者不释放,程序结束时可能由垃圾回收机制回收。
区别:声明变量时不同的内存分配;复制变量时不同,分别是值和地址;参数传递不同,分别是值和地址。

4. 数据类型检测的方式

typeof,其中数组、对象和null都会判断为object,其他正常,引用数据类型,除了函数之外,都会显示object;
object.prototype.toString.call()使用object对象的原型方法toString来判断数据类型;
instanceof,运行机制时判断在其原型链中能否找到该类型的原型,只能正确判断引用数据类型,不能判断类型,原理是测试一个对象在其原型链中是否存在一个构造函数的prototype属性;
constructor,判断数据类型,对象实例通过constructor对象访问它的构造函数,需注意,如果创建一个对象来改变它的原型,constructor就不能用来判断数据类型了。

5. 判断数组的方式

object.prototype.toString.call()object.prototype.toString.call(obj).slice(8,-1)==='Array';
通过ES6的Array.isArray()做判断,Array.isArray(obj);
of obj instanceof Array
instanceof obj instanceof Array

6. instanceof操作符的实现原理及实现

首先获取对象原型,接着获取构造函数的prototype对象,然后判断构造函数的prototype对象是否在对象的原型链上,如果没有找到,就继续从其原型上找,object.getPrototypeOf方法用来获取指定对象的原型。

7. 箭头函数和普通函数的区别

箭头函数,若没有参数,可以直接写一个空括号,若参数只有一个,可以省略括号,多个参数用逗号隔开,放在括号中;若函数体只有一句代码,即简单返回某个变量,则可省略大括号。区别:不会创建自己的this,会捕获自己在定义时所处的外层执行环境的this,并继承这个this值,之后不会再变,call(),apply(),bind()都不会改变this指向;箭头函数不能作为构造函数使用;没有自己的arguments;没有原型prototype;不能用作Generator函数,不能使用yield关键字。

8. 对原型、原型链的理解

js没有子类和父类,里面所有的数据类型都是对象。构造函数与其他函数唯一的区别在于调用方式不同,任何函数只要通过new来调用就可以作为构造函数,用来创建特定类型的对象。通过new创建实例后,该构造函数就是实例对象的原型,this关键字指的就是这个实例对象,每个new出来的实例有自己的属性,是独立的。每个构造函数都有一个prototype属性,指向原型对象(普通对象,存放着所有实例对象需要共享的属性和方法,搞早函数里存放不需共享的)。实例被创建后,属性和方法分为两种:自身的和引用prototype的,具体实现:代码读取带某个对象的属性,会执行一次搜索。首先从对象实例本身开始,若找到则返回,若没有则顺着原型链指针向上,到原型对象中查找,找到返回。若为对象添加了一个属性和原型中的同名,则该属性会屏蔽掉原型中的。

9. 对闭包的理解

闭包是指有权访问另一个函数作用域中变量的函数,创建闭包的最常见的方式就是在一个函数内创建另一个函数,创建的函数可以访问到当前函数的局部变量。两个用途:使我们在函数外部能够访问到函数内部的变化,通过使用闭包,可以通过在外部调用闭包函数,从而在外部访问到函数内部的变量,可以使用这种方法来创建私有变量;闭包的另一作用是使已经运行结束的函数上下文中的变量对象继续留在内存中,因为闭包保留了这个变量对象的引用,所以变量对象不会被回收。

10. 哪些情况会导致内存泄露

意外的全局变量:使用未声明的变量,意外创建了一个全局变量,一直在内存中无法回收;
被遗忘的计时器或回调函数:设置了定时器,如果循环函数有对外部变量的引用的话,那么这个变量会被一直留在内存中,而无法被回收;
脱离DOM的引用:获取一个DOM元素的引用,而后面这个元素被删除,由于一直保留了对这个元素的引用,所以无法被回收;
闭包:不合理使用闭包,从而导致某些变量一直被留在内存当中。

Vue

1. vue2.0响应式数据的原理

数据劫持+观察者模式,对象内部通过defineReactive方法,使用object.defineProperty将属性进行劫持(只会劫持已经已经存在的属性),数组则是通过重写数组方法来实现。当页面使用对应属性时,每个属性都拥有自己的dep属性,存放他所依赖的watcher(依赖收集),当属性变化后会通知自己对应的watcher去更新。

2. v-if和v-show的区别

手段:v-if是动态地向DOM树内添加或删除DOM元素,v-show是通过设置DOM元素的display样式属性控制显隐;编译过程:v-if切换有一个局部编译/卸载的过程,切换过程中合适地销毁和重建内部的事件监听和子组件,v-show只是简单地基于CSS切换;编译条件:v-if是惰性的,如果初始条件为假,则什么也不做,只有条件第一次变为真时才开始局部编译;v-show则是在任何条件下,无论首次条件是否为真,都被编译,然后被缓存,而且DOM元素保留;性能消耗:v-if有更高的切换消耗,v-show有更高的初始渲染消耗;使用场景:v-if适合运营条件不大可能改变的,v-show适合频繁切换的。

3. v-for为什么要加key

如果不使用key,vue会使用一种最大限度减少动态元素并且尽可能地尝试就地修改/复用当前相同类型元素的算法。key是vue种vnode的唯一标记,通过这个key,可以是diff操作更准确(因为带key就不是就地复用了)、更快速(利用key的唯一性生成map对象来获取对应节点,比遍历方式更快)。

4. 生命周期

从一个组件创建、数据初始化、挂载、更新、销毁,就是一个组件所谓的生命周期。生命周期钩子:生命周期事件的别名。
主要的生命周期函数分类:
创建期间的生命周期函数:beforeCreate(实例初始化之后,数据观测和event/watcher事件配置之前被调用。实例刚在内存中被创建出来,此时,还没有初始化好data和methods属性),created(实例已经完成了模板的编译,完成数据观测、属性和方法的运算,watch/event事件回调。但还没有挂载到页面中,$el属性目前还不可见),beforeMount(实例已经完成了模板的编译,但还没有挂载到页面中,相关render函数首次被调用),mounted(已经将编译好的模板挂载到了页面指定的容器中显示,真实的DOM挂载完毕,数据完成双向绑定,可以访问到DOM节点。当el被新创建的vm.$el替换,并挂载到实例上去之后调用该钩子);在执行vm._render()函数渲染VNode之前,执行了beforeMount钩子函数,在执行完vm._update()把VNode patch到真实DOM后,执行mounted钩子。

5. 对虚拟DOM的理解

从本质上来说,虚拟DOM时一个JS对象,通过对象的方式来表示DOM结构。将页面的状态抽象为JS对象的形式,配合不同的渲染工具,使跨平台成为可能。通过事物处理机制,将多次DOM修改的结果一次性更新到页面上,从而有效减少页面渲染的次数,减少修改DOM的重排和重绘的次数,提高渲染性能。代码渲染页面之前,vue或者react会把代码转换成一个对象(虚拟DOM),以对象的形式来描述真实的DOM结构,最终渲染到页面,在每次数据发生变化前,虚拟DOM都会缓存一份,变化之时现在的虚拟DOM会和缓存的虚拟DOM进行比较。vue和react内部封装了diff算法,通过这个算法,来进行比较,渲染时修改改变的变化,原先没有发生改变的通过原先的数据进行渲染。
为什么使用:保证性能下限,在不进行手动优化的情况下,提供过得去的性能,真实DOM,生成HTML字符串,重建所有的DOM元素;虚拟DOM,生成虚拟Node,通过DOMdiff算法,进行必要的DOM更新。跨平台,虚拟DOM本质上是JS对象,可以很方便地跨平台操作,比如服务端渲染、uniapp等。


计算机网络

1. HTTP状态码

100,继续,客户端继续请求;101,切换协议;200:OK,请求已正常处理;201,已创建,成功请求并创建了新的资源;202,已接受,已接收请求,但未处理完成;203,非授权信息,请求成功,但返回的信息不在原始的服务器;204:请求处理成功,但没有任何资源可以返回给客户端;206:对某一部分资源的请求;301:永久性重定向;302:临时重定向;303:与302有相同功能,但303明确表示客户端应当采用GET方法获取资源;304:资源已找到,但未符合条件请求;400:服务端无法理解客户端发送的请求;401:表示发送的请求需要有通过HTTP认证;403:不允许访问那个资源;404:服务器上没有请求的资源;500:内部资源出故障了:503:服务器暂时处于超负载或正在停机维护中,无法处理情求。

2. TCP的三次握手和四次挥手

第一次:客户端将TCP报文标志位SYN置为1,随机产生序号值seq,保存在TCP首部的序列号字段里,指明客户端打算连接的服务器的端口,并将数据包发送给服务器端,发送完毕后,客户端等待服务端确认;第二次:服务端收到收到数据包后有标志位知道客户端请求建立连接,服务端将TCP报文标志位SYN和ACK都置为1,ack=seq+1,随机产生一个序号值,将该数据包发送给客户端以确认连接请求;第三次:客户端收到确认后,检查ack,ACK,若正确则将ACK置为1,ack=seq'+1,将数据包发送给服务端,检查ack,ACK,正确则连接建立成功,客户端和服务端完成握手,之后可以开始传输数据。为什么三次:假设第一个连接请求报文段没有丢失,在某个节点滞留,本已失效,但是延时到达后服务端发出确认,那么新的连接建立,服务端等待发送资源,但客户端不会发送,因此浪费了很多资源。
四次挥手,由于TCP是全双工的,因此,每个方向都要单独进行关闭,即一方完成数据发送任务后,发送一个FIN来终止这一方向的连接,收到一个FIN只是意味着这一方向上没有数据流动了,知道另一方也发送了FIN,双方才能关闭。

3. HTTP1.1和HTTP2.0的区别

二进制协议:2.0是二进制协议,头信息和数据体都是二进制,统称为帧,可分为头信息帧和数据帧,帧的概念是它实现多路复用的基础;而1.1中,报文的头信息必须是文本(ASCII编码),数据体二者皆可。多路复用:2.0多路复用,复用TCP连接,同一连接里,客户和服务端可以同时发送多个请求或回应,不用按照顺序,避免队头阻塞。数据流:2.0,数据包不按顺序发送,同一个连接里连续的数据包,可能属于不同的请求,因此,需对数据包做标记,指出它属于哪个请求。2.0将每个请求或回应的所有数据包,称为一个数据流,每个数据流都有一个独一无二的编号,数据包发送时,都必须标记数据流ID,用来区分它属于哪个数据流。头信息压缩,1.1协议不带状态,每次请求需附上信息,所以很多字段是重复的,浪费带宽,影响速度;2.0引入头部压缩,用gzip或compress压缩后再发送,其次,客户端和服务端同时维护一张头信息表,所有字段会存入这个表,生成索引号,以后不用发字段只发送索引号,提高速度。

浏览器

1. 协商缓存和强缓存的区别

强缓存:不会向服务器发起请求,直接从缓存中读取资源,在chrome控制台的Network选项中可以看到该请求返回200的状态码,size显示from memory cache或from  disk cache,可以通过设置两种HTTP header 实现,Expires(缓存过期时间,用来指定资源到期的时间,是服务端的具体时间点,即Expires=max-age+请求时间,需要和Last-modified结合使用,在响应请求时告诉浏览器在过期时间前浏览器可以直接从浏览器缓存读取数据,无需再次请求)和Cache-control(控制网页缓存,多种指令,如max-age,设置缓存存储的最大周期)。
区别在于:前者是http1.0的产物,后者是1.1的,同时存在的话cache-control的优先级高,某些不支持1.1的情况下,Expires发挥作用。判断依据是是否超粗某个时间段,不关心服务器端文件是否已经更新,若要知道是否更新,则用到协商缓存。
协商缓存:强制缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存。协商缓存生效,返回304和Not Modified,表示资源无更新,在缓存中获取结果;协商缓存成功,返回200和请求结果,后将请求结果存入缓存中。可通过设置Last-Modified(资源文件在服务器最后被修改的时间,根据If-Modified-Since的字段值与最后修改时间对比,若最后被修改时间大于If-Modified-Since的值,则重新返回资源,状态码为200)和ETag(当前资源文件的一个唯一标识符,与If-None-Match作对比,一致则返回304,代表资源无更新,继续使用缓存,否则重新返回)实现,后者优先级高于前者。

2. 浏览器本地存储方式及使用场景

localStorage:生命周期永久,除非清除浏览器中的localStorage信息,否则永远存在,存放数据大小一般为5MB,仅在浏览器中保存,不参与服务器通信;sessionSorage:仅在当前会话下有效,关闭页面会浏览器后被清除,存放数据大小一般为5MB,仅在浏览器中保存,不参与服务器通信;Cookie:在设置的过期时间内一直有效,即使窗口或浏览器关闭,存放数据大小为4K,有存储个数限制(与浏览器有关),一般不超过20个,与服务端通信,每次都会携带在HTTP头中,Cookie存储数据过多会带来性能问题。
应用场景:localStorage的大容量和持久特性,可以存储一些内容稳定的资源,比如官网logo ,图片资源等。

3. 什么是同源策略

浏览器最核心、最基本的安全功能。同源指域名、协议、端口相同;同源策略又分为以下两种,DOM(禁止对不同源页面DOM进行操作,主要场景是iframe跨域的情况,不同域名的iframe是限制互相访问的)和XMLHttpRequest(禁止使用XHR对象向不同源的服务器地址发起HTTP请求)。
用于限制一个origin的文档或者它加载的文本如何能与另一个源的资源进行交互,出于防范跨站脚本的攻击,禁止客户端脚本对不同域的服务进行跨站调用,能帮助阻隔恶意文档,减少可能被攻击的媒介。cookie,localStorage和IndexDB无法读取,DOM无法获得Ajax请求不能发送。
为什么要有跨域限制:存在同源策略,就会有跨域问题,为了用户的上网安全。若没有DOM同源策略,不同域之间的iframe之间可以相互访问,若没有XHR同源策略,黑客可以进行CSRF。

4. 如何解决跨域问题

JSONP跨域:script标签不受浏览器同源的影响,允许跨域引用资源,过程就是:声明一个回调函数,其函数名做参数值,要传递给跨域请求数据的服务器,函数形参为要获取目标数据;创建script标签,把那个跨域的API数据接口地址赋值给script的src,还要在这个地址中向服务器传递该函数名;服务器接收到请求,进行处理,把传递进来的参数名和它需要给的数据连接成一个字符串;最后服务器把准备的数据通过HTTP协议返回给客户端,客户端再调用回调函数对返回的数据进行操作。

CORS:跨域资源共享,定义了在访问跨域资源时,浏览器与服务器应该如何沟通,浏览器自动完成,不需用户参与,浏览器发现跨域,则会添加一些附加的头信息。分为简单请求和非简单请求,简单请求同时满足两大条件,请求条件是HEAD、GET、POST三者之一,HTTP的头信息不超出Accept、Accept-Language、Content-Language,Last-Event-ID,Content-Type这几种。复杂请求会在正式通信之前,增加一次HTTP请求,称为“预检”请求,该请求是option方法的,通过该请求来知道服务端是否允许跨域请求。

node中间件代理(两次跨域):同源策略是浏览器需要遵循的标准,而如果是服务器向服务器请求就无需遵循同源策略,代理服务器需要做到如下步骤:接收客户端请求,将请求转发给服务器,拿到服务器响应数据,将响应转发给客户端。

nginx反向代理:通过nginx配置一个代理服务器(域名与domain1相同,端口不同)做跳板机,反向代理访问domain2接口,并且可以顺便修改cookie中domain信息,方便当前域cookie写入,实现跨域登录。是最简单的跨域方式,只需修改配置。

#高频知识点汇总##学习路径#
全部评论
🎉恭喜牛友成功参与 【创作激励计划·高频知识点汇总】专场,并通过审核! ------------------- 带【高频知识点汇总】话题发帖,瓜分总奖池29000元: ✅总结秋招期间常见面试题或高频考点; ✅分享某技术知识点或某方向学习路径 👉戳:https://www.nowcoder.com/discuss/802570了解更多活动详情~
点赞 回复
分享
发布于 2021-11-16 15:03

相关推荐

14 105 评论
分享
牛客网
牛客企业服务