当前位置:   article > 正文

2023前端面试题合集(附答案)持续更新中..._前端面试题大全2023

前端面试题大全2023

js基础类

1.什么是原型链及原型链存在的意义

(1).什么是原型链

答:原型链就是每个对象拥有一个原型对象,对象以其原型为模板、从原型继承方法和属性。原型对象也可能拥有原型,并从中继承方法和属性,一层一层、以此类推。这种关系就被称为原型链。
简单理解:原型链就是在当前对象中找不到定义的话,会在当前对象的原型对象上继续查找,直至undefined。

(2).原型和原型链存在的意义是什么?

答:实例对象可以共享构造函数原型属性和方法,节省内存。构造函数原型上的属性和方法越多,节省内存越大。

2.什么是作用域?

作用域分为:1.全局作用域,2. 函数作用域, 3.块级作用域

答:作用域是在运行时代码中的某些特定部分变量,函数和对象的可访问性,作用域决定了代码区块中变量和其他资源的可见性。

3.什么是闭包?

能够访问其他函数内部变量的函数,被称为闭包。
那种场景会用到,一些事件函数的封装.
闭包本身会带来常驻内存,引用后不会及时销毁.

4.浏览器的渲染过程

当我们在浏览器里输入一个 URL 后,最终会呈现一个完整的网页。会经历以下几个步骤:

1、HTML 的加载

页面上输入 URL 后,会先拿到 HTML 文件。HTML是一个页面的基础,所以会在最开始的时候下载它,下载完毕后就开始对它进行解析

2、其他静态资源的下载
HTML 在解析的过程中,如果发现 HTML 文本里面有一些外部的资源链接,比如 CSS、JS 和图片等,会立即启用别的线程下载这些静态资源。在 head 中遇到 JS 文件时,HTML 的解析会停 下来,等 JS 文件下载结束并且执行完,HTML 的解析工作再接着来,防止 JS 修改已经完成的解析结果

由上得知,JS 文件放在 head 中属于同步加载,会阻塞 DOM 树的构建,进而影响页面的加载。当 JS 文件较多时,页面白屏的时间也会变长

5.数据类型简介:

js常用的基本数据类型包括undefined - - (未定义)、null- - (空的)、number - - (数字)、boolean- - (布尔值)、string- - (字符串)、Symbol - - (符号);

js的引用数据类型也就是对象类型Object- - (对象),比如:array - - (数组)、function - - (函数)、date - - (时间)等;

6.深浅拷贝

浅拷贝:浅拷贝是会将对象的每个属性进行依次复制,但是当对象的属性值是引用类型时,实质复制的是其引用,当引用指向的值改变时也会跟着变化

深拷贝: 深拷贝和浅拷贝是针对复杂数据类型(对象及数组)来说的,浅拷贝只拷贝一层,而深拷贝是层层拷贝。深拷贝复制变量值,对于非基本类型的变量,则递归至基本类型变量后,再复制。 深拷贝后的对象与原来的对象是完全隔离的,互不影响,对一个对象的修改并不会影响另一个对象。

7.css水平居中的几种方法

  1. margin和width实现,在容器上定义一个固定的宽度,配合margin左右的值为auto。
  2. 内容设置inline-block和父元素text-align:center。
  3. 绝对定位实现水平居中,我想大家也非常的熟悉了,并且用得一定不少。
  4. css3的flex实现。
  5. css3的fit-content 。

8.你知道数组有哪些实用高阶函数吗?

数组有很多的方法,都很简单方便,向push,pop等等,但是对于高阶函数在实际使用用的很多,现在就来总结一下方法使用及场景首先,什么是高阶函数:高阶函数,就是函数中可以传入另一个函数作为参数的函数。
点击查看案例详解

  1. forEach
  2. filter
  3. map
  4. sort
  5. some
  6. every
  7. reduce
  8. find

9.call、apply、bind的区别

  • call、apply、bind相同点:都是改变this的指向,传入的第一个参数都是绑定this的指向,在非严格模式中,如果第一个参数是nul或者undefined,会把全局对象(浏览器是window)作为this的值,要注意的是,在严格模式中,null 就是 null,undefined 就是 undefined
  • call和apply唯一的区别是:call传入的是参数列表,apply传入的是数组,也可以是类数组
  • bind和call、apply的区别: bind返回的是一个改变了this指向的函数,便于稍后调用,不像call和apply会立即调用;bind和call很像,传入的也是参数列表,但是可以多次传入,不需要像call,一次传入
  • 值得注意:当 bind 返回的函数 使用new作为构造函数时,绑定的 this 值会失效,this指向实例对象,但传入的参数依然生效 (new调用的优先级 > bind调用)

Vue类

10.vue2和vue3的区别

  1. 双向数据绑定原理不同
  2. 是否支持碎片;
  3. API类型不同;
  4. 定义数据变量和方法不同;
  5. 生命周期钩子函数不同;
  6. 父子传参不同;
  7. 指令与插槽不同;
  8. main.js文件不同。

vue2:vue2不支持碎片。
vue3:vue3支持碎片(Fragments),就是说可以拥有多个根节点。
vue2:vue2的双向数据绑定是利用ES5的一个APIObject.definePropert() 对数据进行劫持,结合发布订阅模式的方式来实现的。
vue3:vue3中使用了ES6的Proxy API对数据代理。相比vue2.x,使用proxy的优势如下:
(1).defineProperty只能监听某个属性,不能对全对象监听
(2).可以省去for in,闭包等内容来提升效率(直接绑定整个对象即可)
(3).可以监听数组,不用再去单独的对数组做特异性操作vue3.x可以检测 到数组内部数据的变化。

11.route和router的区别

router为VueRouter的实例,相当于一个全局的路由器对象,里面含有很多属性和子对象,例如history对象。经常用的跳转链接就可以用this.$router.push,和router-link跳转一样。

route相当于当前路由对象。可以获取到一些参数,每一个路由都会有一个router对象,可以从里面获取name,path,params等。

12.vue路由两种模式的区别

hash模式
就是指 url 后面的 # 号以及后面的字符。每次刷新页面时是直接更改 # 后的东西。

hash 原理:灵活运用了 html的瞄点功能,改变 # 后的路径本质上是更换了当前页面的瞄点,所以不会刷新页面。通过监听浏览器的 onhashchange()事件变化,查找对应的路由规则。

由于 hash 值变化不会导致浏览器向服务器发出请求,而且 hash 改变会触发 hashchange事件(hashchange只能改变 # 后面的 url片段);虽然 hash路径出现在URL中,但是不会出现在 HTTP请求中,对后端完全没有影响,因此改变 hash值不会重新加载页面,基本都是使用 hash 来实现前端路由的。

history模式
history 原理: 利用 H5的 history中新增的两个API :pushState()和 replaceState()和一个事件onpopstate监听URL变化。

包含 back、forward、go方法;history 模式 URL就要和后端进行一致,所以要改为 history也需要后端的配合,否则会报错;history 每次刷新会重新向后端请求整个网址,也就是重新请求服务器。如果后端没有及时响应,就会报错404!。

13.keep-alive的生命周期

在组件切换过程中 把切换出去的组件保留在内存中,防止重复渲染DOM,减少加载时间及性能消耗,提高用户体验性

被包含在 keep-alive 中创建的组件,会多出两个生命周期的钩子: activated(组件激活时使用) 与 deactivated(组价离开时调用)

钩子的触发顺序created-> mounted-> activated,退出时触发deactivated。当再次进入(前进或者后退)时,只触发activated

keep-ailve用法:

  • 如果需要缓存整个项目,直接在app.vue中用keep-alive包裹router-view即可
  • 要缓存部分页面,需要在路由地址配置中,在meta属性中添加一个状态,在app.vue中判断一下包裹的router-view即可
  • 也可以使用exclude和include规定缓存哪个组件不缓存哪个组件

14.mvvm的优势:

  1. mvc和 mvvm 都是一种设计思想,主要就是 mvc 中 controller 演变成 mvvm 中的 viewModel。mvvm 主要解决了 mvc 中大量 dom 操作提高了页面 渲染性能和加载速度的问题
  2. mvvm 和 mvc 最大的区别就是:它实现了 view 和 Model 的自动同步,当 model 的属性改变时,我们不用在手动操作 dom 元素来改变 view 的显示,它会自动变化dom
  3. 整体看来,mvvm 比 mvc 精简很多,我们不用在用选择器来频繁的操作 dom

15.虚拟DOM的作用

  • 维护视图和状态的关系
  • 复杂视图情况下提升渲染性能
  • 虚拟 DOM 在更新真实 DOM 之前会通过 Diff 算法来对比两个新旧两个虚拟 DOM 树之间的差异,实现局部更新,最终把差异更新到真实 DOM

16.vue如何实现性能优化

1.代码模块化,常用的地方封装成单独的组件,在需要用到的地方引用,而不是写过多重复的代码,每一个组件都要明确含义,复用性越高越好,可配置型越强越好,包括咱们的css也可以通过less和sass的自定义css变量来减少重复代码。
2.Vue路由设置成懒加载,当首屏渲染的时候,能够加快渲染速度。
3.打包优化,修改vue.config.js中的配置项,把productionSourceMap设置为false,不然最终打包过后会生成一些map文件,如果不关掉,生成环境是可以通过map去查看源码的,并且可以开启gzip压缩,使打包过后体积变小。
4.减少图片使用,可以用一些css3的效果来代替图片效果,或者使用雪碧图来减少图片的体积。
5.按需引入,咱们使用的一些第三方库可以通过按需引入的方式加载。避免引入不需要使用的部分,无端增加项目体积
6.使用cdn的方式外部加载一些资源,比如vue-router、axios等Vue的周边插件,在webpack.config.js里面,externals里面设置一些不必要打包的外部引用模块

17.路由的守卫

对路由守卫的认识

路由守卫分为三种:全局导航守卫,路由守卫,组件内导航守卫。路由跳转本身是一个比较复杂的过程,但是可以通过导航守卫把这个过程进行细化,可以在每个细化的过程(钩子函数)中进行相应的操作。

路由导航守卫:导航守卫就是在路由跳转前后的一些钩子函数
路由拦截:在路由跳转到指定的路有前,可以手动让其跳转到其他的路由界面,并且也可以让跳转停止掉。

路由守卫的分类
1 全局守卫

  • 全局前置守卫:beforeEach 会多次触发,
  • 全局解析守卫:beforeResolve 解析守卫
  • 全局后置守卫:afterEach 把组件实例对象传入到组件beforeRouteEnter守卫的next回调中

2.路由守卫

  • beforeEnter 路由内的独享守卫

3.组件内的守卫

  • beforeRouteEnter 进入组件之前触发,只在进入组件时触发一次
  • beforeRouterUpdate 组件更新之前触发(动态参数变化查询字符串变化)进入组件后参数变化可多次触发
  • beforeRouterLeave 离开路由组件之前触发 只在离开组件时触发一次

18.Vue 组件中 data 为什么必须是函数?

因为一个组件是可以共享的,但他们的data是私有的,所以每个组件都要return一个新的data对象,返回一个唯一的对象,不要和其他组件共用一个对象。

如果是对象形式,所有的实例都将共享同一份data的数据对象,一旦某个组件修改了data,所有的实例都将受到影响,这是我们不想要的结果。

这样每一个实例的data属性都是独立的,不会相互影响了。所以,你现在知道为什么vue组件的data必须是函数了吧。这都是因为js本身的特性带来的,跟vue本身设计无关。

19.ES6的新特性有哪些?

 - 新增了块级作用域(let,const)
 - 提供了定义类的语法糖(class)
 - 新增了一种基本数据类型(Symbol)
 - 新增了变量的解构赋值
 - 函数参数允许设置默认值,引入了rest参数,新增了箭头函数。
 - 数组新增了一些API,如isArray / from / of 方法;数组实例新增了 entries(),keys() 和 values() 等方法。
 - 对象和数组新增了扩展运算符
 - ES6新增了模块化(import / export)
 - ES6新增了Set和Map数据结构。
 - ES6原生提供Proxy构造函数,用来生成Proxy实例
 - ES6新增了生成器(Generator)和遍历器(Iterator) 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

说说解构赋值

 - 解构:分解数据结构。
 - 赋值:为变量赋值。
 - 解构赋值:从数组或者对象中提取值,按照对应的位置,对变量赋值(在数组解构中,只 要解构的目标可以遍历,就可以实现解构赋值)。
  • 1
  • 2
  • 3

20.模块化开发的好处:

  1. 避免变量污染,命名冲突
  2. 提高代码复用率
  3. 提高了可维护性
  4. 方便依赖关系管理

21.JSON.stringify深拷贝的缺点

1、如果obj里面有时间对象,则JSON.stringify后再JSON.parse的结果,时间将只是字符串的形式,而不是对象的形式
2、如果obj里面有RegExp,则打印出来是空对象
3、如果对象中有函数或者undefined,则会直接被丢掉
4、如果json里有对象是由构造函数生成的,则会丢掉对象的constructon
5、如果对象中存在循环引用的情况也无法正确实现深拷贝
6、如果对象中存在NAN,则序列化后会变成null

22.防抖和节流,有什么区别?

开发中,经常会遇到以下场景:监听鼠标移动 onmousemove,监听页面滚动 onscroll,监听大小变化 onresize,监听 input 输入,按钮的搜索、提交功能等。这些场景下,事件会被频繁触发,但我们并不想事件被频繁触发,这时就需要通过防抖和节流来限制频繁操作。

防抖和节流都是为了解决事件频繁触发的问题,但在实现原理上有些不同,具体实现原理看下文。

1.防抖(debounce):

防抖触发高频率事件时n秒后只会执行一次,如果n秒内再次触发,则会重新计算。

简单概括:每次触发时都会取消之前的延时调用。

应用场景:
1.scroll事件滚动
2.浏览器窗口的缩放resize事件
3.搜索框输入查询的时候
4.表单验证
5.按钮的提交事件

代码:

function debounce (fn, delay = 1000) {
  let time = null
  return function () {
    // 获取当前this
    let that = this
    // 判断是否已经存在,如果存在直接清除
    if (time) {
      clearTimeout(time)
    }
    time = setTimeout(() => {
      // 使fn 中this,执行当前调用者,并传入参数
      fn.apply(that, arguments)
    }, delay)
  }
}
// 测试demo
function logger(e){
	console.log('log -----')
}
btn.addEventListener('click',debounce(logger, 1000))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

2.节流(thorttle):

高频事件触发,每次触发事件时设置一个延迟调用方法,并且取消之前延时调用的方法。

简单概括:每次触发事件时都会判断是否等待执行的延时函数。

代码:

function throttle (fn, delay = 1000) {
	let time = null;
	return function () {
		let that = this;
		// 如果已经存在定时器了,则 不做处理
		if (!time) {
			time = setTimeout(() => {
				fn.apply(that, arguments);
				// 完结时,将time改为null
				time = null;
			}, delay);
		}
	};
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

区别: 降低回调执行频率,节省计算资源。

  • 防抖和节流本质是不一样的。防抖是将多次执行变为最后一次执行,节流是将
    多次执行变成每隔一段事件执行
  • 函数防抖一定连续触发的事件,只在最后执行一次,而函数节流一段时间内只执行
    一次。

23.JS中promise对象的作用与使用

Promise 它是一个ES6提出一个新语法,用来优化异步代码的写法。
promise的作用:ajax是异步请求,多层嵌套会造成回调地狱,promise模拟同步,将异步回调类似于同步来处理业务逻辑。

promise的then方法是异步方法,但会优先于定时器执行。

1、promise参数是一个函数,这个回调函数有两个形参(自定义,一般约定写为resolve,reject)
2、Promise的三种状态: pending、fulfilled、rejected(未决定,履行,拒绝),同一时间只能存在一种状态,且状态一旦改变就不能再变
3、当状态一旦发送改变 就不会重新改变
4、成功执行.then里的回调函数,失败执行.catch内的回调函数

特点:

将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。
流程更加清晰,代码更加优雅。
Promise对象提供统一的接口,使得控制异步操作更加容易。

缺点:

无法取消Promise,一旦新建它就会立即执行,无法中途取消。
如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。
当处于pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。

24.async-await语法

async,await 是es7中新增的语法,用来进一步改进异步代码的写法,是promise升级版!

async

  • async函数返回一个 Promise 对象。
  • async函数内部return语句返回的值是Promise 对象的值
function f1 () {
  return 1
}
async function f2 () {
  return 1
}
async function f3 () {}
const r1 = f1()
const r2 = f2()
const r3 = f3()
console.log(r1) // 1
console.log(r2) // Promise, resolved(1)
console.log(r3) // Promise, resolved(undefined)
r2.then(res => { console.log(res) })
r3.then(res => { console.log(res) })
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

await 命令

  • await的外层函数必须有一个async.
  • 正常情况下,await命令后面是一个 Promise 对象,返回该promise的值。如果不是 Promise 对象,就直接返回对应的值。

async函数内部的执行流程

  1. 在执行async函数(设名为asyncF)时,进入函数内部:
  2. 按序执行同步代码
  3. 遇到await,跳出asyncF函数,
  4. 继续执行后续代码。
  5. 当await后的异步代码执行完成之后,接着执行asyncF中的后续代码。

25.宏任务和微任务

为什么任务要分为同步任务和异步任务

试想一下,如果js的任务都是同步的,那么遇到定时器、网络请求等这类型需要延时执行的任务会发生什么?

页面可能会瘫痪,需要暂停下来等待这些需要很长时间才能执行完毕的代码

所以,又引入了异步任务。

● 同步任务:同步任务不需要进行等待可立即看到执行结果,比如console
● 异步任务:异步任务需要等待一定的时候才能看到结果,比如setTimeout、网络请求

异步任务,又可以细分为宏任务和微任务。下面列举目前学过的宏任务和微任务。
在这里插入图片描述
● 先执行同步代码
● 遇到宏任务,放入队列
● 遇到微任务,放入微任务队列
● 执行栈为空
○ 将微任务入栈执行
● 所有的微任务完成之后,取出宏任务队列来执行

宏任务和微任务谁先执行 答:宏任务
(其实这个问法是不够严谨的,因为script是宏任务,说宏任务先执行是没毛病的,毕竟代码都被包裹在script里。而如果站在执行过程中的视角来看,则当然是先执行微任务,微任务全部执行完了才会去执行剩下的宏任务当然如果你遇到面试官实在这么问,那就把问题反抛给他,给他来个三连问。)
-script是不是宏任务?
-那是不是宏任务先执行?
-执行宏任务过程中遇到微任务和宏任务难道不是先执行微任务?

26.v-model和sync修饰符有什么区别

相同点:都是语法糖,都可以实现父子组件中的数据的双向通信。
区别点:格式不同:v-model=“num”, :num.sync=“num”

v-model:@input + value
:num.sync: @update:num

另外需要特别注意的是: v-model只能用一次;.sync可以有多个。

27.typescript和javascript区别

首先是类型系统不同。TypeScript引入了静态类型检查,这意味着在编译阶段,TypeScript会检查变量的类型,而不是在运行时。这有助于捕捉潜在的错误,同时也使代码更易于理解和维护。

包括数据绑定,模块化编程,应用方向,编译期间发现错误时间

28.ts中type和interface的区别

概念:
type:类型别名,为类型创建一个新名称。它并不是一个类型,只是一个别名。
interface:接口,TS 设计出来主要用于定义对象类型,可以对对象的形状进行描述。

区别:

  • 1.interface可以重复声明,type定义后不能重复声明
  • 2.interface可以通过“extends”来继承接口,这样既高效又不用重新定义。而type只能通过&来实现类似于继承的功能
  • 3.type 能够表示非对象类型, 而 interface 则只能表示对象类型。

type

  • 可以定义基本类型别名,如type StringType = string
  • 可以声明联合类型,如 type paramType = number | string;
  • 可以声明元组类型,如type arrType = [string, string, number]
  • 定义对象时严谨的来说,type 是引用,而 interface是定义

29.JS的原型与原型链

1、原型,所有的函数默认都有一个“prototype”这样公有且不可枚举的属性,它会指向另一个对象,这个对象就是原型。

2、原型链,当访问对象的属性或方法时,首先对象会从自身去找,找不到就会往原型中去找,也就是它构造函数的“prototype”中,如果原型中找不到,即构造函数中也没有该属性,就会往原型后面的原型上去找,这样就形成了链式的结构,称为原型链。

30.什么是虚拟DOM

虚拟DOM就是用普通js对象来描述DOM结构,因为不是真实DOM,所以称之为虚拟DOM。

虚拟 dom 是相对于浏览器所渲染出来的真实 dom而言的,在react,vue等技术出现之前,我们要改变页面展示的内容只能通过遍历查询 dom 树的方式找到需要修改的 dom 然后修改样式行为或者结构,来达到更新 ui 的目的。

这种方式相当消耗计算资源,因为每次查询 dom 几乎都需要遍历整颗 dom 树,如果建立一个与 dom 树对应的虚拟 dom 对象( js 对象),以对象嵌套的方式来表示 dom 树及其层级结构,那么每次 dom 的更改就变成了对 js 对象的属性的增删改查,这样一来查找 js 对象的属性变化要比查询 dom 树的性能开销小。

31. vuex Mutations为什么必须是同步

mutation内部必须是同步函数,异步会导致内部状态难以追踪,devtool难以追踪state的状态.

从官方解释来看,修改state数据必须只能mutations中修改,而假设mutions内部有异步,那么会带来devtool无法准确追踪state变化,因为多个异步并不知道哪个异步会先执行完。但是话说回来,mutations中有异步,依然可以修改state啊,因为业务中我并不太需要知道devtool是如何追踪state的变化,但是为了遵从规范,所有的异步都在actions中处理,mutations只集中干一件事,直接修改state值

actions是异步操作的,actions中可以有多个异步操作,但是最终的结果依然是交给mutations去修改的,也就是说actions中异步操作的副作用统一交给了mutations去记录

多个异步任务可以在actions中触发,dispatch(‘xxx’)返回的是一个Promise

32.js堆与栈

js堆与栈的概念
js堆栈是指JavasSript运行时的一个概念,它是一种数据结构,用于存储函数调用时的上下文信息,
当一个函数被调用时,它的上下文信息也就是局部变量和和一些函数参数等会被排入堆栈中,当函数调用结束后这些信息会被弹出堆栈,因此,js堆栈理解为一个先进后出的数据结构

栈: 先进后出
堆: 先进先出
队列: 先进先出
栈内存: 在编译时已经定好了大小,存储一些局部变量和指针 ,静态变量是在静态数据区
堆内存: 大小在运行时是动态变化的,远大于栈,存储一些函数和引用数据

33.js事件循环

JS 在解析一段代码时,会将同步代码按顺序排在某个地方,即执行栈,然后依次执行里面的函数。当遇到异步任务时就交给其他线程处理,待当前执行栈所有同步代码执行完成后,会从一个队列中去取出已完成的异步任务的回调加入执行栈继续执行,遇到异步任务时又交给其他线程,…,如此循环往复。而其他异步任务完成后,将回调放入任务队列中待执行栈来取出执行。

JS 按顺序执行执行栈中的方法,每次执行一个方法时,会为这个方法生成独有的执行环境(上下文 context),待这个方法执行完成后,销毁当前的执行环境,并从栈中弹出此方法(即消费完成),然后继续下一个方法。

可见,在事件驱动的模式下,至少包含了一个执行循环来检测任务队列是否有新的任务。通过不断循环去取出异步回调来执行,这个过程就是事件循环,而每一次循环就是一个事件周期或称为一次 tick。

34.Nginx代理以及node代理跨域原理

为什么会出现跨域问题呢?那就不得不讲浏览器的同源策略了,它规定了协议号-域名-端口号这三者必须都相同才符合同源策略

如有有一个不相同,就会出现跨域问题,不符合同源策略导致的后果有

1、LocalStorge、SessionStorge、Cookie等浏览器内存无法跨域访问
2、DOM节点无法跨域操作
3、Ajax请求无法跨域请求
注意点:一个IP是可以注册多个不同域名的,也就是多个域名可能指向同一个IP,即使是这样,他们也不符合同源策略
同源策略,满足协议号-域名-端口号这三者都相同就是同域,反之就是跨域,会导致跨域报错

注意:跨域是请求发出去到后端,后端返回数据,在浏览器接收后端数据时被浏览器的跨域报错拦下来(大多数人理解为请求一发出就被浏览器的跨域报错拦下来了)

node代理

先说同源策略,同源策略它只是浏览器的一个策略而已,它是限制不到后端的,也就是前端-后端会被同源策略限制,但是后端-后端则不会被限制,所以可以通过Node接口代理,先访问已设置Cors的后端1,再让后端1去访问后端2获取数据到后端1,后端1再把数据传到前端

Nginx代理

其实Nginx跟Node接口代理是一个道理,只不过Nginx就不需要我们自己去搭建一个中间服务
先下载nginx,然后将nginx目录下的nginx.conf修改进行代理

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/算法编织者/article/detail/62504
推荐阅读
相关标签
  

闽ICP备14008679号