前端面试题汇总(理论篇一)--页面加载及请求、网络

输入网址到页面渲染的全过程

1)输入URL

2) 检查缓存

3)DNS域名解析,获取IP地址

4)浏览器与服务器建立连接(TCP三次握手)

4)向服务器发送HTTP请求,服务器返回response

5)浏览器对response进行解析渲染页面

6)断开连接(四次挥手)

页面渲染及页面加载资源的顺序

1)一个页面的加载顺序是从上到下顺序加载的,并且加载与渲染同时进行。

2)引用外部js文件时,当在加载过程中遇到<script>标签时,浏览器会向服务器发送一个reques并等待该request的返回。

因为浏览器需要1个稳定的DOM树结构,而JS中很有可能有代码直接改变了DOM树结构,比如使用document.write 或 appendChild,甚至是直接使用的location.href进行跳转,浏览器为了防止出现JS修改DOM树,需要重新构建DOM树的情况,所以加载js就会阻塞其后内容的下载和呈现。

3)使用嵌入式js时,会阻塞所有内容的呈现。

4)当在加载过程中遇到<style>标签时,浏览器会发1个request去请求CSS或image,然后继续执行下面的转换,而不需要等待request的返回,当request返回后,只需要把返回的内容放入到DOM树中对应的位置就OK,所以正常来说CSS并不会诸塞页面(不阻塞DOM的解析,会阻塞Dom的渲染)。

但是也有例外:当CSS后面跟着嵌入的JS的时候,该CSS就会出现阻塞后面资源下载的情况。

原因:因为浏览器会维持html中css和js的顺序,样式表必须在嵌入的JS执行前先加载、解析完。而嵌入的JS会阻塞后面的资源加载,所以就会出现上面CSS阻塞下载的情况。

浏览器加载页面渲染流程:

浏览器渲染的流程如下:

1.渲染引擎首先通过网络获取所请求文档内容

2. 解析HTML文件生成DOM Tree

3. 解析CSS文件生成CSSOM(CSS对象模型)

4. 整合DOM Tree和CSSOM,生成Render Tree(渲染树)

5.根据Render Tree渲染绘制,将像素渲染到屏幕上。

6.layout布局(重排在这一步,确定大小位置等,可以想象成将页面切成一块一块的)

7. 渲染每一个节点(重绘在这一步,这也是为什么重排一定重绘,重绘不一定重排)

js为什么会阻塞浏览器渲染?

因为浏览器在构建DOM树时,如果遇到js,便会中断DOM树构建,把控制权交给js引擎,等js执行完毕,再继续构建DOM树。

css为什么会阻塞浏览器渲染?

1)css会阻塞渲染树生成。如果不阻塞的话,当css加载完后,又要重新绘制或回流,造成不必要的性能消耗。

2)css不会直接阻塞DOM树构建,但是会阻塞js执行,而js会阻塞DOM树构建,所以css会间接阻塞DOM树构建。

css为什么会阻塞js执行?

因为js要通过CSSOM读取和修改节点样式,所以等待CSSOM架构后才会执行。

重点总结:

  • DOM解析和CSS解析是两个并行的进程,所以这也解释了为什么CSS加载不会阻塞DOM的解析。
  • 然而,由于Render Tree是依赖于DOM Tree和CSSOM Tree的,所以他必须等待到CSSOM Tree构建完成,也就是CSS资源加载完成(或者CSS资源加载失败)后,才能开始渲染。因此,CSS加载是会阻塞Dom的渲染的。
  • 由于js可能会操作之前的Dom节点和css样式,因此浏览器会维持html中css和js的顺序。因此,样式表会在后面的js执行前先加载执行完毕。所以css会阻塞后面js的执行。

script标签async和defer属性作用和区别?

作用:脚本的加载不会阻塞浏览器渲染

区别:

1)defer是HTML4标准,async是HTML5标准

2)defer是按照文档顺序加载和执行,async是脚本先加载完成就先执行

3)defer等DOM树构架完再执行,async不等DOM树构架完就执行

重排和重绘

发生重排:

1)页面初始渲染

2)添加/删除可见DOM元素

3)改变元素位置

4)改变元素尺寸(宽、高、内外边距、边框等)

5)改变元素内容(文本或图片等)

6)改变窗口尺寸

发生重绘:outline,visibility,colorbackground-color等

如何减少重排、重绘

由于回流和重绘会带来很大的性能开销,所以在开发中我们要尽量避免或减少回流和重绘的次数来提高性能

1.      避免频繁读取会引发回流/重绘的属性,如果确实需要多次使用,就用一个变量缓存起来。

2.     对具有复杂动画的元素使用绝对定位,使其脱离文档流,否则会引起父元素及后续元素频繁回流。

3.     要避免频繁的去操作DOM,可以通过创建documentFragment,完成所有所有DOM操作后,最后再把它添加到文档中。

4.     避免频繁操作样式,最好一次性重写style属性,或者将样式列表定义为class并一次性更改class属性。

基础类型和引用类型有哪些?哪些在栈?哪些在堆?

基础类型:基本数据类型是存放在栈中的简单数据段(比较是值的比较)

String  Number  Boolean  undefined   null  symbol

引用类型:引用数据类型是存放在堆内存中的对象,在栈内存中存放的是堆内存中具体内容的引用地址,通过这个地址可以快速查找到对象(比较是引用的比较)

Array Object   Function  Date

当一个变量向另一个变量赋值引用类型的值时,同样也会将栈内存中的值复制一份放到新变量分配的空间中,但是引用类型保存在栈内存中的变量是一个地址,这个地址指向的是堆内存中的对象,所以这个变量其实复制了一个地址,两个地址指向同一个对象,改变其中任何一个变量都会互相影响。

栈内存中存放地址指向堆内存中的对象

JavaScript中基本数据类型与引用类型_js原始数据类型和引用数据类型_小憨憨不敢。的博客-CSDN博客

为什么js是单线程?

JavaScript的单线程,与它的用途有关。JavaScript的主要用途是与用户互动,以及操作DOM,这决定了它只能是单线程,否则会带来很复杂的同步问题。比如,假定JavaScript同时有两个线程,一个线程在某个DOM节点上添加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线程为准?

js解决单线程阻塞问题

        单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。如果前一个任务耗时很长,后一个任务就不得不一直等着。 如果排队是因为计算量大,CPU忙不过来,倒也算了,但是很多时候CPU是闲着的,因为IO设备(输入输出设备)很慢(比如Ajax操作从网络读取数据),不得不等着结果出来,再往下执行。

        JavaScript语言的设计者意识到,这时主线程完全可以不管IO设备,挂起处于等待中的任务,先运行排在后面的任务。等到IO设备返回了结果,再回过头,把挂起的任务继续执行下去。

        于是,所有任务可以分成两种,一种是同步任务(synchronous),另一种是异步任务(asynchronous)。同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;异步任务指的是,不进入主线程、而进入"任务队列"(task queue)的任务,只有"任务队列"通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。

事件循环EventLoop

同步和异步任务分别进入不同的执行环境,同步的进入主线程,即主执行栈,异步的进入任务队列 (Event Queue,机制为先进先出)。主线程内的任务执行完毕为空,会去任务队列读取对应的任务,推入主线程执行。 上述过程的不断重复就是我们说的 Event Loop (事件循环)。

(执行JS的时候,遇见同步任务,直接推入调用栈中执行,遇到异步任务,该任务挂起,等异步任务有返回之后推入到任务队列中,等调用栈中所有任务执行完成,将任务队列一个个推入并执行,重复这一系列的行为叫事件循环)

同步任务(synchronous)

又叫做非耗时任务,指的是在主线程上排队执行的那些任务

只有前一个任务执行完毕,才能执行后一个任务

异步任务(asynchronous)

又叫做耗时任务,异步任务由 JavaScript 委托给宿主环境进行执行

当异步任务执行完成后,会通知 JavaScript 主线程执行异步任务的回调函数
 

同步任务:主线程上排队执行的任务,只有前一个任务执行完毕,才能继续执行下一个任务。

异步任务:不进入主线程、而进入"任务队列"的任务,只有等主线程任务全部执行完毕,"任务队列"的任务才会进入主线程执行

  1.宏任务:setInterval()   setTimeout()  setImmediate()  ajax   事件绑定

  2.微任务:new Promise()后的then与catch函数、new MutationObserver 、process.nextTick

process.nextTick()与 Promise回调谁先执行

process.nextTick(function(){

    console.log(7);

});

new Promise(function(resolve){

    console.log(3);

    resolve();

    console.log(4);

}).then(function(){

    console.log(5);

});

process.nextTick(function(){

    console.log(8);

});

//这段代码运行结果是3,4,7,8,5

process.nextTick()是Node环境下的方法, 所以我们基于Node谈论。

process.nextTick()是一个特殊的异步API,其不属于任何的Event Loop阶段。事实上Node在遇到这个API时,Event Loop根本就不会继续进行,会马上停下来执行process.nextTick(),这个执行完后才会继续Event Loop。

跨域问题解决方法

  • JSONP:jsonp的原理就是利用了script标签不受浏览器同源策略的限制,然后和后端一起配合解决跨域问题。
  • CORS:cors是跨域资源共享,是一种基于 HTTP 头的机制,该机制通过允许服务器标示除了它自己以外的其它 origin(域,协议和端口),使得浏览器允许这些 origin 访问加载自己的资源。服务端设置了Access-Control-Allow-Origin就开启了CORS,所以这种方式只要后端实现了CORS,就解决跨域问题,前端不需要配置。
  • 搭建Node代理服务器解决跨域:因为同源策略是浏览器限制的,所以服务端请求服务器是不受浏览器同源策略的限制的,因此我们可以搭建一个自己的node服务器来代理访问服务器。

    大概的流程就是:我们在客户端请求自己的node代理服务器,然后在node代理服务器中转发客户端的请求访问服务器,服务器处理请求后给代理服务器响应数据,然后在代理服务器中把服务器响应的数据再返回给客户端。客户端和自己搭建的代理服务器之间也存在跨域问题,所以需要在代理服务器中设置CORS。

  • Nginx反向代理解决跨域:nginx通过反向代理解决跨域也是利用了服务器请求服务器不受浏览器同源策略的限制实现的。

  • window.postMessage() 方法可以安全地实现跨源通信,此方法一种受控机制来规避此限制,只要正确的使用,这种方法就很安全。

    主要的用途是实现多窗口,多文档之间通信:

  1. 页面和其打开的新窗口的数据传递
  2. 多窗口之间消息传递
  3. 页面与嵌套的 iframe 消息传递

总结:
jsonp的原理是利用了script标签不受浏览器同源策略的限制,img和link标签也是不受浏览器同源策略限制的。
跨域是浏览器限制,服务端和服务端之间通信是不受浏览器同源策略限制的。
所有跨域的解决方案都是需要服务端配合的。
最常用的跨域解决方案是CORS、Node代理服务器和Nginx反向代理方式。
postMessage更多的是用在多个文档,窗口之间发送数据。
 

跨域什么时候出现

不同源策略时会导致出现跨域问题

首先URL由:协议 域名 端口三部分组成

当请求一个URL的协议、域名、端口三个任意一个与当前URL不同即为跨域

v-if与v-show的区别

1)v-if是动态向DOM树内增加或删除DOM元素

     v-show是设置DOM元素display属性控制显示隐藏

2)v-if切换有个局部编译、卸载的过程,切换过程合适的销毁和重建内部的事件监听和子组件。

     v-show只是简单的css切换

3)v-if更高切换消耗;v-show更高的初始渲染消耗

4)v-if是惰性的,初始条件为假什么也不做,只有条件第一次变为真局部编译

    v-show在任何条件都被编译,然后被缓存切DOM元素保留

5)v-if适合运营条件不太可能改变

    v-show适合频繁切换

bind,apply,call

 1) 调用fn.call时会将fn中的this指向修改为传入的第一个参数thisArg;将后面的参数传入给fn,并立即执行函数fn。

fn.call(thisArg, arg1, arg2, arg3, ...)

2) fn.apply的作用和call相同:修改this指向,并立即执行fn。区别在于传参形式不同,apply接受两个参数,第一个参数是要指向的this对象,第二个参数是一个数组,数组里面的元素会被展开传入fn,作为fn的参数。 

 apply(thisArg, [argsArr])

3) fn.bind的作用是只修改this指向,但不会立即执行fn;会返回一个修改了this指向后的fn。需要调用才会执行:bind(thisArg, arg1, arg2, arg3, ...)()。bind的传参和call相同。 

bind(thisArg, arg1, arg2, arg3, ...)

1、相同点
三个都是用于改变this指向;
接收的第一个参数都是this要指向的对象;
都可以利用后续参数传参。
2、不同点
call和bind传参相同,多个参数依次传入的;
apply只有两个参数,第二个参数为数组;
call和apply都是对函数进行直接调用,而bind方法不会立即调用函数,而是返回一个修改this后的函数

说说webscoket

webscoket是一种网络通信协议,因为http有缺陷,通信只可以由客户端发出,服务器无法主动向客户端发送消息。因为webscoket拥有全双工通信,可以实现多标签页之间的通信。

webscoket生命周期及心跳机制_Holly31的博客-CSDN博客

HTTP请求

HTTP请求是指从客户端到服务端的请求消息

HTTP是超文本传输协议,其定义了客户端与服务端之间文本传输规范

HTTP请求包含:协议、请求方法、请求头、请求体

1)请求方法:get、post、put、delete、options、head、connect

2)URL地址

3)协议名称及版本号

4)HTTP报文头

5)报文体

get和post的区别

  •  1、Get 是用来从服务器上获得数据,而 Post 是用来向服务器上传递数据。
  •  2、Get 将表单中数据的按照 variable=value 的形式,添加到 action 所指向的 URL 后面,并且两者使用“?”连接,而各个变量之间使用“&”连接;Post 是将表单中的数据放在 form 的数据体中,按照变量和值相对应的方式,传递到 action 所指向 URL。
  •  3、Get 是不安全的,因为在传输过程,数据被放在请求的 URL 中,而如今现有的很多服务器、代理服务器或者用户代理都会将请求URL记录到日志文件中,然后放在某个地方,这样就可能会有一些隐私的信息被第三方看到。另外,用户也可以在浏览器上直接看到提交的数据,一些系统内部消息将会一同显示在用户面前。Post 的所有操作对用户来说都是不可见的。
  •  4、Get 传输的数据量小,这主要是因为受 URL 长度限制;而 Post 可以传输大量的数据,所以在上传文件只能使用 Post(当然还有一个原因,将在后面的提到)。
  •  5、Get 限制 Form 表单的数据集的值必须为 ASCII 字符;而 Post 支持整个 ISO10646 字符集。
  •  6、Get 是 Form 的默认方法。

使用 Post 传输的数据,可以通过设置编码的方式正确转化中文;而 Get 传输的数据却没有变化。在以后的程序中,我们一定要注意这一点。

HTTP 方法:GET 对比 POST | 菜鸟教程

HTTP缓存

浏览器访问一个网站,如果第一次访问,需加载各种资源(html js css img等),之后我们再次访问,则不需要重新从服务器获取,可直接从缓存中获取,提高网站的访问速度。

客户端请求资源简单过程:

1)首次请求时,服务器返回资源,并在响应头中注明缓存参数,客户端缓存资源
2)再次请求时,会先访问浏览器缓存,若命中强缓存则直接提取资源,状态码返回 200
3)若未命中强缓存,则将请求发送给服务器,判断本地协商缓存是否失效,若有效返回 304
4)若未命中协商缓存,则服务器返回完整资源,并更新缓存

强制缓存:响应头设置cache-control:max-age=(单位是秒)。(cache-control:no-cache不缓存)浏览器在本地缓存存下文件,下次请求资源文件时,检查max-age是否过期

协商缓存:在浏览器访问网站时,服务器返回资源和资源标识,浏览器可把资源和资源标识保存在浏览器,当再次访问网站,浏览器把请求和资源标识发送给服务器,服务器根据资源标识判断当前版本和服务器版本是否一致,一致返回304,浏览器直接从缓存拿文件,不一致返回200,同时返回新的资源和资源标识,浏览器在进行缓存。

页面缓存(浏览器缓存)cookie、localStorage和sessionStorage三者的区别

1.存储的时间有效期不同

    1)cookie的有效期是可以设置的,默认的情况下是关闭浏览器后失效

    2)sessionStorage的有效期是仅保持在当前页面,关闭当前会话页或者浏览器后就会失效

    3)localStorage的有效期是在不进行手动删除的情况下是一直有效的

2.存储的大小不同

     1)cookie的存储是4kb左右,存储量较小,一般页面最多存储20条左右信息

     2)localStorage和sessionStorage的存储容量是5Mb(官方介绍,可能和浏览器有部分差异性)

3.与服务端的通信

   1)cookie会参与到与服务端的通信中,一般会携带在http请求的头部中,例一些关键密匙验证等

   2)localStorage和sessionStorage是单纯的前端存储,不参与与服务端的通信

4.读写操作的便捷程度

   1)cookie的相关操作,cookie操作起来较为繁琐,并且部分数据不可以读取操作

//JavaScript 中,创建 cookie 如下所示:
document.cookie="username=John Doe";
//您还可以为 cookie 添加一个过期时间(以 UTC 或 GMT 时间)。默认情况下,cookie 在浏览器关闭时删除:
document.cookie="username=John Doe; expires=Thu, 18 Dec 2043 12:00:00 GMT";
//您可以使用 path 参数告诉浏览器 cookie 的路径。默认情况下,cookie 属于当前页面。
document.cookie="username=John Doe; expires=Thu, 18 Dec 2043 12:00:00 GMT; path=/";
//cookie的读取
var x = document.cookie;

2) sessionStorage的相关操作

//存储一条数据
sessionStorage.setItem('数据名', '数据值');
//读取一条数据
let data = sessionStorage.getItem('数据名');
//清除一条数据
sessionStorage.removeItem('数据名');
//移除所有数据
sessionStorage.clear();

3)localStorage的相关操作

//存储一条数据
localStorage.setItem('数据名', '数据值');
//读取一条数据
let data = localStorage.getItem('数据名');
//清除一条数据
localStorage.removeItem('数据名');
//移除所有数据
localStorage.clear();

5.对于浏览器的支持

1、cookie出现的时间较早,目前见到的浏览器都支持

2、localStorage和sessionStorage出现的时间较晚,对于版本较低的浏览器不支持(比如IE8版本以下的都不支持)

cookie 与 session 的区别

①Cookie可以存储在浏览器或者本地,Session只能存在服务器
②session 能够存储任意的 java 对象,cookie 只能存储 String 类型的对象
③Session比Cookie更具有安全性(Cookie有安全隐患,通过拦截或本地文件找得到你的cookie后可以进行攻击)
④Session占用服务器性能,Session过多,增加服务器压力
⑤单个Cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个Cookie,Session是没有大小限制和服务器的内存大小有关。


        Session是另一种记录客户状态的机制,不同的是Cookie保存在客户端浏览器中,而Session保存在服务器上。客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上。这就是Session。客户端浏览器再次访问时只需要从该Session中查找该客户的状态就可以了。

cookie和session结合使用
web开发发展至今,cookie和session的使用已经出现了一些非常成熟的方案。在如今的市场或者企业里,一般有两种存储方式:

1、存储在服务端:通过cookie存储一个session_id,然后具体的数据则是保存在session中。如果用户已经登录,则服务器会在cookie中保存一个session_id,下次再次请求的时候,会把该session_id携带上来,服务器根据session_id在session库中获取用户的session数据。就能知道该用户到底是谁,以及之前保存的一些状态信息。这种专业术语叫做server side session。
2、将session数据加密,然后存储在cookie中。这种专业术语叫做client side session。flask采用的就是这种方式,但是也可以替换成其他形式。

三次握手原理:

第1次握手:客户端发送一个带有SYN(synchronize)标志的数据包给服务端;

第2次握手:服务端接收成功后,回传一个带有SYN/ACK标志的数据包传递确认信息,表示我收到了;

第3次握手:客户端再回传一个带有ACK标志的数据包,表示我知道了,握手结束。

四次挥手 

第1次挥手:客户端发送一个FIN,用来关闭客户端到服务端的数据传送,客户端进入FIN_WAIT_1状态;

第2次挥手:服务端收到FIN后,发送一个ACK给客户端,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),服务端进入CLOSE_WAIT状态;

第3次挥手:服务端发送一个FIN,用来关闭服务端到客户端的数据传送,服务端进入LAST_ACK状态;

第4次挥手:客户端收到FIN后,客户端t进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1,服务端进入CLOSED状态,完成四次挥手。
 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
前端面试中,常见的问题包括浏览器测试和主流浏览器内核、axios和fetch的特点等。关于浏览器测试,常用的几种浏览器包括Chrome、Firefox、Safari和Edge等。主流浏览器的内核有WebKit、Gecko和Trident等。\[1\] 关于axios,它是一个基于Promise的HTTP客户端,可以在浏览器和Node.js中使用。它封装了原生的XMLHttpRequest,并提供了一些方便的接口,支持防止CSRF攻击,可以拦截请求和响应,还可以自动转换JSON数据。\[2\] 而fetch是一种新的网络请求API,它基于Promise实现,支持async/await语法,语法简洁且更加语义化。它是ES规范中的新实现方式,相比于XHR,提供了更底层的API,包括request和response等。同时,fetch也可以在浏览器和Node.js中使用。\[3\] 这些是前端面试中可能会涉及到的一些问题和答案。当然,在面试中还会有其他的问题,涉及到HTML、CSSJavaScript等方面的知识。建议你在准备面试时,全面复习这些知识点,加强自己的理解和实践能力。 #### 引用[.reference_title] - *1* [前端面试题及答案汇总](https://blog.csdn.net/come0across/article/details/104895118)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [前端面试题汇总大全(含答案)-- 持续更新](https://blog.csdn.net/q95548854/article/details/98617043)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值