春招前端笔试面试合集3
事件循环机制
首先要聊聊进程和线程,进程就是CPU执行指令和加载保存上下文的一次活动,线程就是进程中的一个小单位,负责一段指令的执行,在浏览器中,打开一个页面就是一个进程,而js加载是一个线程,UI渲染是一个线程,http请求是一个线程,然后聊聊执行栈,执行栈主要存储函数调用,遵循先进后出原则,事件循环机制,就是遇到异步代码,会被挂起,并在需要执行的时候放入任务队列中,执行栈的函数为空时,把任务队列的代码放入执行栈,开始执行,而不同的任务有不同的队列,分为宏任务和微任务,宏任务包括script
, setTimeout
,setInterval
,setImmediate
,I/O
,UI rendering
,微任务有process.nextTick
,promise
,MutationObserver
,而事件循环的机制就是按照下面的规则进行执行事件,首先执行宏任务的同步任务,然后检查有没有异步任务,把异步放入执行栈,执行微任务,结束后会进行渲染,然后执行异步任务。
对于非空整数数组numList,数组中有且只有一个元素只出现一次,其他的元素都出现两次,请找出那个只出现了一次的元素,
function findSingleNumber(numList) { // 将数组中的所有元素进行异或运算 // 相同的数异或后为0,0和任何数异或后为该数本身 let result = 0; for (let i = 0; i < numList.length; i++) { result ^= numList[i]; } return result; }
var data=[]
for (var i=0;I<3;I++){(function(){Promise.resolve().then(()=>{data[i]=function(){console.log(i)}})})()}
data[0]()
data[1]()
data[2]()
输出结果是什么
定义了一个空数组 data,并使用 for 循环向其中添加了三个函数。这些函数的功能是打印它们的索引值 i,在循环中使用了立即调用函数表达式(IIFE)来创建一个新的作用域,以便在每次迭代中创建一个新的闭包,从而避免了变量 i 的共享。在每个 IIFE 中使用了一个异步函数 Promise.resolve().then(() => {...})。这个函数会在下一个微任务中执行,而不是立即执行。由于 JavaScript 的事件循环机制,这意味着循环会先执行完毕,而 then 回调函数会在循环结束之后才被调用。因此,当 then 回调函数被调用时,变量 i 的值已经变成了循环结束时的值,即 3。所以最终结果时3,3,3
输入网址到获得页面的过程可以分为以下几个步骤:
DNS 解析
用户在浏览器中输入网址后,浏览器首先需要将域名解析成对应的 IP 地址,以便能够建立 TCP 连接。解析过程通常是通过 DNS 服务器进行的,浏览器会向本地 DNS 缓存、本地 DNS 服务器、根域名服务器等依次发送 DNS 解析请求,直到找到目标主机的 IP 地址。
TCP 连接
一旦浏览器获得了目标主机的 IP 地址,它就会与目标主机建立 TCP 连接。这个过程通常包括三次握手,即浏览器向服务器发送 SYN 数据包,服务器收到后回应 SYN-ACK 数据包,浏览器再回应 ACK 数据包,完成连接的建立。
发送 HTTP 请求
TCP 连接建立后,浏览器会向服务器发送 HTTP 请求,请求中包含了请求的方法、URI、HTTP 版本、请求头等信息。
服务器处理请求并返回响应
服务器接收到请求后,会根据请求的信息进行处理,并返回对应的 HTTP 响应。响应中包含了状态码、响应头和响应体等信息。
浏览器渲染页面
浏览器收到响应后,会将响应中的 HTML、CSS、JavaScript 等内容解析并渲染成页面,最终呈现给用户。
四次挥手
当浏览器不再需要与服务器保持连接时,它会向服务器发送一个 FIN 数据包,请求关闭连接。服务器收到请求后,会回应一个 ACK 数据包,表示已经收到请求。然后服务器也会向浏览器发送一个 FIN 数据包,请求关闭连接。浏览器收到请求后,也会回应一个 ACK 数据包,表示已经收到请求。这个过程通常被称为四次挥手,表示关闭连接的过程。