(必背):从浏览器地址栏输入 url 到请求返回发生了什么
- 输入 URL 后解析出协议、主机、端口、路径等信息,并构造一个 HTTP 请求。
- 强缓存。
- 协商缓存。
-
DNS 域名解析。(字节面试被虐后,是时候搞懂 DNS 了)
-
TCP 连接。
总是要问:为什么需要三次握手,两次不行吗?其实这是由 TCP 的自身特点可靠传输决定的。客户端和服务端要进行可靠传输,那么就需要确认双方的接收和发送能力。第一次握手可以确认客服端的发送能力,第二次握手,确认了服务端的发送能力和接收能力,所以第三次握手才可以确认客户端的接收能力。不然容易出现丢包的现象。
-
http 请求。
-
服务器处理请求并返回 HTTP 报文。
-
浏览器渲染页面。
-
- 解析HTML,构建DOM树
-
- 解析CSS,生成CSS规则树
-
- 合并DOM树和CSS规则,生成render树
-
- 布局render树(Layout/reflow),负责各元素尺寸、位置的计算
-
- 绘制render树(paint),绘制页面像素信息
。
- 绘制render树(paint),绘制页面像素信息
。
- 断开 TCP 连接。
1、get和post的请求的区别?
答: 区别:
- 应用场景: Get请求一般用于对服务器资源不会产生影响的场景,比如请求一个网页资源,而Post一般用于对服务器有影响的操作,比如注册用户
- 是否缓存: 浏览器一般会对Get请求进行缓存,很少对post请求缓存。
- 发送报文的格式: Get请求的报文中实体部分为空,Post请求的报文中实体部分一般为向服务器发送的数据。
- 安全性: Get请求将请求参数放在url中相对post而言不太安全。url会被保留在历史记录中。
- 请求长度: get请求url长度限制1024字节。
2.post和put请求的区别?
答:
- put请求是向服务器端发送请求,从而修改数据的内容,但是不会增加数据的种类,也就是更新操作。
- post是向服务器端发送数据,他可以创建新的内容。
5.常见的HTTP请求方法?
答:
-
GET: 向服务器获取数据;
-
POST:将实体提交到指定的资源,通常会造成服务器资源的修改;
-
PUT:上传文件,更新数据;
-
DELETE:删除服务器上的对象;
-
HEAD:获取报文首部,与GET相比,不返回报文主体部分;
-
OPTIONS:询问支持的请求方法,用来跨域请求;
- 1.实现预检请求(preflight request):在进行跨域请求时,浏览器会先发送一个OPTIONS请求,询问服务器是否可以发送真实的请求。服务器通过返回合适的响应头来告知浏览器是否允许跨域访问。
- 2.查询服务器支持的方法:通过发送OPTIONS请求,客户端可以了解服务器对某个资源支持的HTTP方法,从而决定后续的请求如何发送。
-
CONNECT:要求在与代理服务器通信时建立隧道,使用隧道进行TCP通信;
-
TRACE: 回显服务器收到的请求,主要⽤于测试或诊断。
7.HTTP和HTTPS协议的区别?
答: 主要区别如下:
-
1.HTTPS协议需要CA证书,费用较高,而HTTP协议不需要。
-
2.HTTP协议是超文本传输协议,信息是明文传输的,HTTPS则具有安全性的SSL加密传输。
-
3.HTTP协议端口是80,HTTPS协议端口是443
14. HTTPS是如何保证安全的?
答:结合两种加密方式,将对称加密的秘钥使用非对称加密的公钥进行加密,然后发送出去,接受方使用私钥进行解密,得到对称加密的秘钥,然后双方可以使用对称加密进行沟通。
17.TCP和UDP协议的区别?
答;
- TCP是可靠的、面向连接的协议,提供了可靠的数据传输机制,保证了数据的完整性和有序性,TCP使用三次握手建立连接,通过流控制、拥塞控制、错误检测和重传机制来确保数据的可靠传输,TCP适合传输可靠性比较高的场景,比如电子邮件、网页游览
- UDP是一种不可靠、无连接的协议,UDP不提供数据的可靠性保证,不进行数据重传和流量控制。适合实时性比较高的场景,比如视频通话,直播等。
22. 浏览器跨域问题是什么?怎么解决跨域问题?
答:
1.为什么会产生跨域?
跨域问题是由于浏览器的同源策略(same origin policy)所导致的,同源策略是一种安全策略,用来限制一个源的脚本如何与另一个源的资源进行交互。以下情况会导致跨域问题:
- 1.协议不同:如http和https。
- 2.域名不同:如www.example.com 和 api.example.com。
- 3.端口不同:如 www.example.com:8080 和 www.example.com:9090。 任何两个页面的协议、域名、端口号中只要有一个不同,就会产生跨域问题。
1.介绍一下闭包是什么?
答:闭包是指一个能够访问外部函数自由变量的函数,并且持续性的对这个变量进行引用。即使外部函数执行上下文被销毁,被引用的自由变量仍然在内存中
2.闭包是怎么形成的?
答:在某个内部函数的执行上下文创建时,会将父级函数的活动对象加到内部函数的[[scope]]中,形成作用域链,所以即使父级函数的执行上下文销毁,但是因为其活动对象还是实际存储在内存中可被内部函数访问到的,从而实现了闭包。
6.js是一门什么语言?
答:javascript是一门单线程语言,也就是说,同一个时间只能做一件事,不管是什么新框架新语法糖实现的所谓异步,其实都是用同步的方法去模拟的。
7.宏任务(macro-task)和微任务(micro-task)有哪些?他们执行顺序是怎么样的?
答:macro-task(宏任务):包括整体代码script,setTimeout,setInterval,setImmediate,UI交互时间,I/O事件,requestAnimationFrame micro-stask(微任务):Promise(then、catch、finally里面的代码),process.nextTick,MutationObserver
执行顺序: 事件循环的顺序,决定js代码的执行顺序。进入整体代码(宏任务)后,开始第一次循环。接着执行所有的微任务。然后再次从宏任务开始,找到其中一个任务队列执行完毕,再执行所有的微任务。
9. 介绍一下 async/await ,和Promise有什么关系?
答:async/await是ES2017引入的一种异步编程的解决方案,它基于Promise对象实现,使得异步编程更加简洁、易读和可维护。 执行 async 函数,返回的一定是 Promise 对象。await 相当于 Promise 的 then。try...catch 可捕获异常,代替了 Promise 的 catch。
14.给我介绍一下cookie、localstorage和sessionStorage?
1. Cookie
Cookie是浏览器存储少量数据的一种机制,通常用于存储用户的身份认证、会话标识等,Cookie可以设置过期时间,且会随着http请求发送至服务器端,会导致网络性能问题。Cookie是无法跨域名的,也就是说a域名和b域名下的cookie是无法共享的。
**Cookie的使用场景:**
- 最常见的使用场景就是Cookie和session结合使用,我们将sessionId存储到Cookie中,每次发请求都会携带这个sessionId,这样服务端就知道是谁发起的请求,从而响应相应的信息。
- 可以用来统计页面的点击次数
2. localStorage
localStorage是HTML5提供的一种本地存储机制,可以用于存储较大量的数据,存储大小为5M,localStorage可以设置key-value对,存储的数据类型为字符串。localStorage存储的数据是永久性的,除非用户手动清除,否则会一直存在浏览器中。LocalStorage受到同源策略的限制,即端口、协议、主机地址有任何一个不相同,都不会访问。
3. sessionStorage
sessionStorage是HTML5提供的一种本地存储机制,但是他与localStorage的区别在于,sessionStorage存储的数据是会话级别的,刷新页面时不会删除,关闭窗口或标签页之后将会删除这些数据。
15.给我介绍一下http状态码?
- 1xx - 服务器收到请求。
- 2xx - 请求成功,如 200。
- 3xx - 重定向,如 302。
- 4xx - 客户端错误,如 404。
- 5xx - 服务端错误,如 500。
16.常见的http状态码分别代表什么含义?
- 200 - 成功
- 301 - 永久重定向
- 302 - 临时重定向
- 304 - 资源未被修改
- 403 - 没有权限
- 404 - 资源未找到
- 500 - 服务器错误
- 504 - 网关超时
17. 什么是http缓存?
HTTP缓存是一种机制,用于在客户端(如浏览器)和服务器之间缓存HTTP响应,以提高性能和减少网络流量。HTTP缓存可以存在多个地方,包括浏览器缓存、代理服务器缓存和CDN缓存等。比如,游览器会将下载的资源(HTML、CSS、JavaScript、图片等)缓存在本地,下次再访问同一资源时,游览器可以直接从本地缓存中读取,而不必重新下载。
18.为什么需要缓存?
答:网络请求相比于CPU的计算和页面渲染是非常非常慢的。
19.缓存分为哪几种?
强制缓存: 当游览器第一次请求资源时,服务器会返回资源的同时,告诉游览器这个资源在一段时间内不需要再次请求,这个时间就是缓存时间,当游览器再次请求该资源时,会先检查本地缓存是否过期,如果没有过期,就直接使用本地缓存,如果过期了才会重新向服务器请求该资源。
协商缓存: 当游览器第一次请求资源时,服务器会返回资源的同时,告诉游览器这个资源在一段时间内不需要再次请求,并且返回一个标识该资源的唯一标识符(如ETag)。当游览器再次请求该资源时,会向服务器发送一个请求头信息,包含上次请求时服务器返回的唯一标识符,并询问该资源是否有更新,如果服务器发现该资源已经更新,则返回一个新的资源,并更新唯一标识符,让游览器重新缓存该资源。
20.GET和POST区别?
答: 1.GET请求会将请求参数通过URL传递,而POST请求会将请求参数放在请求体中传递。 2.GET请求的参数的长度有限制,一般是1024字节左右,而POST请求的参数无限制。 3.GET请求会被游览器缓存,POST请求不会被游览器缓存。 总之,GET 请求适用于请求数据量小、请求参数简单、安全性要求不高的场景,而 POST 请求适用于请求数据量大、请求参数复杂、安全性要求高的场景。
21.什么情况会导致跨域?(跨域是什么)
答:跨域问题是指浏览器限制了从一个源(协议+域名+端口)加载的文档或脚本如何与来自其他源的资源进行交互。以下情况会导致跨域问题:
- 1.协议不同:如http和https。
- 2.域名不同:如www.example.com 和 api.example.com。
- 3.端口不同:如 www.example.com:8080 和 www.example.com:9090。 任何两个页面的协议、域名、端口号中只要有一个不同,就会产生跨域问题。
30.有哪些方式可以优化前端性能?
代码层面:
-
防抖和节流
-
减少重排和重绘
-
事件委托
-
css放js脚本的最底部
-
减少DOM操作
-
按需加载,比如React中使用React.lazy和React.Suspense。通常需要与webpack中 splitChunks配合。 构建方面:
-
压缩代码文件,在 webpack 中使用 terser-webpack-plugin 压缩 Javascript 代码;使用 css-minimizer-webpack-plugin 压缩 CSS 代码;使用 html-webpack-plugin 压缩 html 代码。
-
开启 gzip 压缩,webpack 中使用 compression-webpack-plugin ,node 作为服务器也要开启,使用 compression。 其他:
-
图片压缩。
-
使用 http 缓存,比如服务端的响应中添加 Cache-Control / Expires 。
40.typeof能正确区分原始值吗?
答:typeof是能正确区分出来原始值和对象类型的,原始值包括undefied、null、布尔值、数字和字符串。对象类型是数组、对象、函数等。 例如对于原始值undefined,typeof返回'undefined',对于原始值true,返回'boolean',对于原始值123,返回'number',对于原始值'hello',返回'string', 但是对于null的话,会返回object,属于js的遗留问题,对于null,最好使用===来判断。 typeof是不能区分对象类型的,比如[]和{}返回的都是object;
41.typeof的返回值有哪些?
答:
- 'undefined':表示变量未定义和未赋值
- 'boolean': 表示布尔类型
- 'string': 表示字符串类型
- 'number': 表示数字类型
- 'object':[]和{}和null
- 'function': 表示函数类型
48.判断数据类型的方法?
答:
1.typeof可用于判断基本数据类型。(除了null)
2.instanceof用于判断对象的类型,返回值为布尔值。
3.Object.prototype.toString.call()用于判断数据类型,包括基本数据类型和引用数据类型。返回值是字符串。
4.Array.isArray(): 用于判断是否是数组,返回值为布尔值。
5.isNaN(): 用于判断是否为NaN,返回布尔值。
52."=="和"==="的区别是什么?
答:
- "=="运算符用于比较两个值是否相等,但是会进行类型转换,如果两个值类型不同,javascript会尝试将他们转换为相同的类型,然后进行比较。 例如:
console.log(1 == '1'); // 输出 true,因为 '1' 被转换为数字 1
console.log(true == 1); // 输出 true,因为 true 被转换为数字 1
console.log(null == undefined); // 输出 true,因为它们都是 falsy 值,被转换为 false
- "==="运算符也用于比较两个值是否相等,不会进行类型转换,只有当两个值的类型和值完全相等时,才会返回true。例如:
console.log(1 === '1'); // 输出 false,因为它们的类型不同
console.log(true === 1); // 输出 false,因为它们的类型不同
console.log(null === undefined); // 输出 false,因为它们的类型不同
72.let const var的区别是什么?
答: var-ES5变量声明方式
- var可以在声明之前使用,
- 作用域var的作用域为方法作用域,只要在方法内定义了,整个方法都可以用。
let-ES6变量声明方式
- 在变量声明前使用会报错。
- let为块级作用域,也就是{}
- let禁止重复声明,var允许重复声明
const-ES6常量声明方式
- const为常量声明方式,声明时必须初始化赋值,后续不得修改该值。
73.箭头函数和普通函数的区别?
答:
- 箭头函数没有this,它的this是通过作用域链查到外层作用域的this,且指向函数定义时的this,而非执行时。普通函数this是执行时动态绑定的。
- 箭头函数不可作为构造函数,不能使用new命令。
- 箭头函数没有arguments对象,如果要用,使用rest参数代替。
- 不可以使用yield命令,因此箭头函数不能用作Generator函数。
- 不能用call/bind/apply修改this指向,但是可以通过修改外层作用域this来间接修改。
- 箭头函数没有prototype属性。
74.Map与WeakMap的区别?(Set和WeakSet的区别?)
答:Map的键名可以是任意类型,包括基本类型和对象类型,而WeakMap的键名只能是引用类型,Map中键或值没有其他引用时,不会被垃圾回收,而WeakMap只要键没有其他引用,就会被垃圾回收。Map有keys()、values()、entries()方法的迭代器,而WeakMap没有迭代器。
75.map和object的区别?
答:object的属性值只能是字符串和Symbol类型。而map的键值可以是基本类型和对象类型。object只能通过遍历获取键值对数量,而map可以直接通过size属性。Object适合存储简单的键值对,不需要使用迭代器的场合,而Map使用存储复杂的键值对,需要使用迭代器和获取键值对数量的场合。
92.隐藏元素的方法有哪些?介绍一下?
答:
- display:none:渲染树不会包含该渲染对象,因此该元素不会在页面中占据位置,也不会响应绑定的监听事件。
- visibility: hidden:元素在页面中仍然占据位置,但是不会响应绑定的监听事件。
- opacity:0 :将元素的透明度设置为0,以此来实现元素的隐藏,元素在页面中仍然占据空间,并且能够响应元素绑定的监听事件。
- position:absolute: 通过使用绝对定位将元素移除可视区域内,以此来实现元素的隐藏。
- z-index:负值: 来使用其他元素遮盖住该元素,以此来实现隐藏。
- transform:scale(0,0):将元素缩放为0,来实现元素的隐藏,这种方法中,元素仍在页面中占据位置,但是不会响应绑定的监听事件。
96.display:none与visibility:hindden的区别?
答“”这两个属性都是让元素隐藏,不可见,区别如下:
- display:none会让元素完全从渲染树中消失,渲染时不会占据任何空间,且display:none是非继承属性,子孙节点会随着父节点从渲染树消失,通过修改子孙节点属性也无法显示。修改display会导致文档重排。
- visibility:hidden不会让元素从渲染树中消失,渲染的元素还会占据相应的空间,只是内容不可见。且是继承属性,可以通过修改子孙的visibility:visible让子孙显示出来。修改visibility属性会导致元素的重绘。
150.call()和apply()的区别?
答:
- apply()接收两个参数,第一个参数是指定函数体内this的指向,第二个参数是一个带下标的集合,可以是数组和类数组,集合中的元素被作为参数传入给调用的函数。
- call()传入的参数数量是不固定的,第一个参数是函数图this的指向,第二个参数开始,每个参数依次传入给调用的函数。
补充:call\apply\bind 中的thisArg参数是null、undefined 不起效果的,依然会指向外面的window.
但是在严格模式下,然是输出null或者 undefined
158.深度优先遍历和广度优先遍历的区别?
深度优先遍历(Depth First Search,DFS)是一种用于遍历或搜索树或图的算法。它从起始节点开始,递归地访问节点的所有未访问过的邻居节点,直到所有节点都被访问为止。在深度优先遍历中,会先探索最深的节点,因此得名深度优先。
广度优先遍历(Breadth First Search,BFS)也是一种用于遍历或搜索树或图的算法。它从起始节点开始,依次访问起始节点的所有邻居节点,再访问邻居节点的邻居节点,直到所有节点都被访问为止。在广度优先遍历中,会先探索离起始节点最近的节点,因此得名广度优先。