系列文章目录
面试真题
笔者正在每天争分夺秒准备着前端的面试中,这个系列是笔者每天看牛客网总结出来的各个前端大厂面试真题(主要会涉及到html,css,js,vue,计算机网络等前端必备知识)
一、如何实现跨域请求,原理是什么
跨域请求是指在 Web 开发中,一个网页的 JavaScript 代码试图向不同域名(或不同端口、不同协议)的服务器发送 HTTP 请求。由于浏览器的同源策略(Same-Origin Policy),默认情况下跨域请求是被禁止的,这是为了保护用户的隐私和安全。
要实现跨域请求,可以通过以下几种方法:
-
JSONP(JSON with Padding): JSONP 是一种利用
<script>
标签的跨域技术。通过在请求的 URL 中传递一个回调函数的名称,服务器端将数据包裹在该回调函数中返回,客户端利用 JavaScript 执行该回调函数来获取数据。JSONP 的缺点是只支持 GET 请求,并且容易受到安全漏洞的影响。 -
CORS(跨域资源共享): CORS 是一种现代的跨域解决方案,通过在服务器端设置响应头部,允许指定的源(域、协议、端口)来访问资源。服务器端可以通过设置
Access-Control-Allow-Origin
、Access-Control-Allow-Methods
、Access-Control-Allow-Headers
等头部来控制允许的跨域访问规则。CORS 支持各种类型的 HTTP 请求(包括 GET、POST 等),并且在安全性上比 JSONP 更加可靠。 -
代理服务器: 可以在同源的服务器端设置一个代理,将跨域请求转发给目标服务器,并将响应返回给客户端。由于代理服务器是在同源下运行的,因此不受同源策略的限制。这种方法需要额外的服务器资源和网络开销。
-
WebSocket: WebSocket 是一种全双工通信协议,不受同源策略的限制。通过 WebSocket 进行通信可以实现跨域请求,但需要服务器端支持 WebSocket 协议。
-
跨域资源代理(Cross-Origin Resource Sharing Proxy): 这是一种通过将跨域请求发送到同源服务器上的代理来实现跨域请求的方法。同源服务器上的代理将请求发送到目标服务器,并将响应返回给客户端。这种方法可以通过配置服务器端代理来实现,但可能会增加服务器负担和网络延迟。
原理: 跨域请求的原理是浏览器的同源策略,即浏览器限制在脚本中发起跨域请求,以防止恶意网站窃取用户信息。同源策略规定,JavaScript 只能访问与其来源相同的资源,包括协议、域名和端口号必须完全相同。跨域请求会触发浏览器的预检请求(OPTIONS 请求),服务器通过设置响应头部来决定是否允许跨域请求。
二、数组深浅拷贝
数组的深拷贝和浅拷贝是两种不同的拷贝方式,它们在拷贝对象时的行为有所不同:
-
浅拷贝(Shallow Copy):
- 浅拷贝会创建一个新的数组,新数组中的元素是原始数组中的引用。
- 修改原始数组中的元素会影响到新数组中对应位置的元素,因为它们引用的是同一个对
- 象。
- 常见的浅拷贝方法包括:
Array.prototype.slice()
,Array.prototype.concat()
, 扩展运算符...
等。
const arr1 = [1, 2, {a: 3}];
const arr2 = arr1.slice(); // 浅拷贝
arr1[2].a = 4;
console.log(arr2[2].a); // 输出: 4
深拷贝(Deep Copy):
- 深拷贝会创建一个新的数组,并且递归地复制原始数组中的所有嵌套对象,而不是只复制引用。
- 修改原始数组中的元素不会影响到新数组中对应位置的元素,因为它们引用的是不同的对象。
- 实现深拷贝的方法较复杂,通常需要使用递归或者第三方库,如 Lodash 中的
_.cloneDeep()
方法。
const arr1 = [1, 2, {a: 3}];
const arr2 = JSON.parse(JSON.stringify(arr1)); // 深拷贝
arr1[2].a = 4;
console.log(arr2[2].a); // 输出: 3
三、XSS和CSRF
XSS(Cross-Site Scripting)和CSRF(Cross-Site Request Forgery)都是Web安全领域中常见的攻击类型,但它们的攻击方式和目标不同。
-
XSS(跨站脚本攻击):
- 攻击原理:攻击者通过在受害者的浏览器中执行恶意脚本,从而获取用户数据、cookie等敏感信息,或者劫持用户会话。
- 攻击方式:通常通过向网页注入恶意脚本来实现,包括存储型XSS、反射型XSS和DOM-based XSS。
- 预防措施:输入验证和输出编码是预防XSS攻击的主要手段。对用户输入进行严格验证,并对输出到页面的内容进行适当的编码,以防止恶意脚本执行。
-
CSRF(跨站请求伪造):
- 攻击原理:攻击者利用受害者在已登录的情况下对目标网站发起未经授权的请求,从而执行某些操作,例如转账、更改密码等。
- 攻击方式:攻击者通常通过诱使受害者访问恶意网站、点击恶意链接或者在受害者登录的情况下向受害者发送包含恶意请求的邮件等方式来实施攻击。
- 预防措施:防范CSRF攻击的主要手段包括使用CSRF令牌(Token)、检查Referer头、使用同源策略(SameSite Cookie属性)等。
虽然XSS和CSRF都属于跨站攻击,但它们的攻击方式和防范措施有所不同,因此在开发和维护Web应用程序时,需要针对这两种攻击类型进行相应的防护措施。
四、http的缓存
HTTP 缓存通常分为两种类型:浏览器缓存和代理服务器缓存。
-
浏览器缓存: 浏览器可以将已获取的资源存储在本地缓存中,以备将来使用。常见的浏览器缓存策略包括强缓存和协商缓存。
-
强缓存:当客户端发起请求时,如果资源在浏览器的强缓存有效期内,则浏览器直接从缓存中获取资源,不发送请求到服务器。
-
协商缓存:当资源的强缓存失效时,浏览器将发送一个请求到服务器,通过与服务器协商确定是否可以使用缓存的副本。
-
-
代理服务器缓存: 代理服务器位于客户端和原始服务器之间,可以缓存客户端请求的资源,并在后续请求中直接提供缓存的副本,而无需再次向原始服务器请求。
为了有效利用 HTTP 缓存,开发者可以通过设置 HTTP 头部来控制缓存策略,包括 Cache-Control
、Expires
、Last-Modified
和 ETag
等。这些头部可以指定缓存的有效期、验证方式等,从而优化资源的缓存和更新策略,提高 Web 应用的性能和用户体验。
六、cookie储存着什么
Cookie是一种存储在用户计算机上的小型文本文件,由网站服务器发送到用户的浏览器,然后存储在用户的计算机上。它们通常包含与特定网站相关的信息,用于跟踪用户的活动、识别用户、保存用户首选项和登录状态等。网站可以使用Cookie来提供个性化的用户体验,例如记住用户的登录状态、购物车内容或网站偏好设置。保存用户的一些使用信息,会被浏览器添加到http请求字段中,方便服务器读取。
七、判断数据类型的方法
JavaScript 中的 typeof
和 instanceof
是用于检查对象类型的两个不同的操作符:
-
typeof 运算符:
typeof
运算符用于检查给定变量的数据类型,返回一个表示该变量数据类型的字符串。- 常用的返回值包括:"number"、"string"、"boolean"、"object"、"function"、"undefined"、"symbol"。
-
instanceof 运算符:
instanceof
运算符用于检查某个对象是否是指定类型的实例,返回一个布尔值。- 它检查指定对象的原型链中是否存在指定类型的构造函数。
八、call,apply区别
call
和 apply
都是 JavaScript 中用于调用函数的方法,它们的作用相似,但在参数传递上有所不同。
-
call 方法:
call
方法允许你调用一个函数,并且可以指定函数内部的this
值,以及传入一个参数列表。- 语法:
function.call(thisArg, arg1, arg2, ...)
thisArg
:在函数执行时指定的this
值。arg1, arg2, ...
:要传递给函数的参数列表。
function greet(name) {
return `Hello, ${name}!`;
}
const message = greet.call(null, 'John');
console.log(message); // 输出 "Hello, John!"
-
apply 方法:
apply
方法与call
类似,但是它接收的参数是一个数组或类数组对象。- 语法:
function.apply(thisArg, [argsArray])
thisArg
:在函数执行时指定的this
值。argsArray
:一个数组或类数组对象,包含要传递给函数的参数列表。
function greet(name, greeting) {
return `${greeting}, ${name}!`;
}
const message = greet.apply(null, ['John', 'Hello']);
console.log(message); // 输出 "Hello, John!"
九、进程和线程
当你在电脑上运行一个程序时,它就是一个进程。如果这个程序同时做很多事情,比如同时下载文件、播放音乐、显示图像等,那么它就会有多个线程,每个线程负责处理不同的任务。简而言之,进程是程序的运行实例,线程是进程中负责具体工作的小部分。
总结
例如:以上就是今天要讲的内容,本文算是我自己的一个日常总结,也是希望能够帮助到更多的前端er。