2024个人前端面试总结(八股文+项目情况)持续更新

JavaScript 

Js的数据类型有哪些他们的区别是什么

基本数据类型:Number String Boolean Null Undefined Symbol(ES6)

        (他们直接存储在内存中的,占用固定的内存空间。基本数据类型的赋值是通过将值直接复制给变量来完成的。)

引用数据类型 :Object Array Date Function()

        (它们存储的是对象在内存中的地址,而不是对象本身。引用数据类型的变量实际上存储的是对象在内存中的引用,通过引用可以访问和操作对象的属性和方法。引用数据类型的赋值是将对象的引用赋给变量。)

区别:
  1. 存储方式:基本数据类型直接存储数据值,而引用数据类型存储的是对象的引用
  2. 内存占用:基本数据类型占用固定的内存空间,而引用数据类型的大小取决于对象的大小。
  3. 赋值方式:基本数据类型的赋值是通过将值直接复制给变量,而引用数据类型的赋值是将对象的引用赋给变量。
  4. 传递方式:基本数据类型作为参数传递时,传递的是值的副本,而引用数据类型作为参数传递时,传递的是引用的副本。

判断数据类型有几种方法

        ypeof (缺点:typeof null的值为Object,无法分辨是null还是Object)         Object.prototype.toString.call(缺点:不能细分为谁谁的实例)

作用域和作用域链

        作用域:规定变量和函数的可使用范围称作作用域
        作用域链:每个函数都有一个作用域链,查找变量或者函数时,需要从局部作用域到全局作用域依次查找,这些作用域的集合称作作用域链

原型和原型链

        原型:原型分为隐式原型和显式原型,每个对象都有一个隐式原型,它指向自己的构造函数的显式原型
        原型链:当我们访问一个对象的属性时,如果这个对象内部不存在这个属性,那么他就会去prototype里找这个属性,这个prototype又会有自己的prototype,于是就这样一直找下去,也就是我们平时所说的原型链的概念

什么是闭包

        闭包是什么:JS中内层函数可以访问外层函数的变量,使内部私有变量不受外界干扰,起到保护保存的作用,我们把这个特性称作闭包。
好处:
  • 隔离作用域,保护私有变量;有了闭包才有局部变量,要不然都是全局变量了。
  • 让我们可以使用回调,操作其他函数内部;
  • 变量长期驻扎在内存中,不会被内存回收机制回收,即延长变量的生命周期;
        坏处:内层函数引用外层函数变量,内层函数占用内存。如果不释放内存,过多时,易引起内存泄露。
        引用场景: for循环中的保留i的操作 / 防抖和节流 

内存泄露、垃圾回收机制

内存泄露:

        是指不再用的内存没有被及时释放出来,导致该段内存无法被使用就是内存泄漏,内存泄漏指我们无法在通过js访问某个对象,而垃圾回收机制却认为该对象还在被引用,因此垃圾回收机制不会释放该对象,导致该块内存永远无法释放,积少成多,系统会越来越卡以至于崩溃

垃圾回收机制:

        就是垃圾收集器按照固定的时间间隔,周期性地寻找那些不再使用的变量,然后将其清楚或释放内存。(标记清除/引用计数)

Js获取dom

  1. getElementById:通过元素的ID属性获取DOM元素。

  2. getElementsByClassName:通过元素的class属性获取DOM元素

  3. getElementsByTagName:通过元素的标签名获取DOM元素

  4. querySelector:通过CSS选择器获取DOM元素

  5. querySelectorAll:通过CSS选择器获取DOM元素

浅拷贝与深拷贝

        浅拷贝:将原对象或原数组的引用直接赋给新对象,新数组,新对象只是对原对象的一个引用,而不复制对象本身,新旧对象还是共享同一块内存。(拓展运算符。。。)
        深拷贝:开辟一个新的栈,两个对象的属性完全相同,但是对应两个不同的地址,修改一个对象的属性,不会改变另一个对象的属性。(JSON.stringify和JSON.parse / 递归/Object.assgin )

        优点:方便,将字符串parse后创建新对象(新地址)

        缺点:如果被拷贝的对象中某个属性的值为undefined,则拷贝之后该属性会丢失,如果被拷贝的对象中有正则表达式,则拷贝之后的对象正则表达式会变成Object

route和router的区别详解

        router是用来操作路由

        route是用来获取路由信息的。 $route.path $route.params route.query等

如何改变this指向(call、apply与bind区别)

        call、bind、apply 都是 JavaScript 中用于改变函数执行上下文(即 this 指向)的方法。

        传参 call、bind可以传递无数个参数,apply只有两个参数,第二个参数为数组

        返回 call和apply方法是直接调用函数并改变函数上下文,而bind方法则是返回一个新函数,稍后调用时绑定指定的上下文。

箭头函数和普通函数的区别

  • 箭头函数是普通函数的简写,但是它不具备很多普通函数的特性
  • this指向问题,箭头函数的this指向它定义时所在的对象,而不是调用时所在的对象
  • 没有arguments对象,不能使用arguments
  • 不会进行函数提升
  • 不能new

浏览器存储,他们的区别?

  • localStorage:永久保存,以键值对保存,存储空间5M
  • sessionStorage:关闭页签/浏览器时清空
  • cookie:随着请求发送,通过设置过期时间删除
  • session:保存在服务端

(localStorage/sessionStorage是window的属性,cookie是document的方法)

继承方式有哪些

  • 原型继承:不能传参
  • 组合继承: 调用了两次父类的构造函数,不共享父类引用属性
  • 寄生组合继承:
  • ES6的extend:子类只要继承父类,可以不写 constructor ,一旦写了,则在 constructor 中的第一句话必须是 super

常用的数组方法有哪些?

  • 改变原数组:push、pop、shift、unshift、sort、splice、reverse
  • 不改变原属组:concat、join、map、forEach、filter、slice

slice切片的意思,根据传入的起始和终止下标,获取该范围数组。splice可根据传入参数个数不同实现删除、插入操作,直接操作原数组。第1个参数为起始下标,第2个为删除个数,第3个为要增加的数据)。

Vue

Vue的生命周期

  • beforeCreate:会在实例初始化完成、props 解析之后、data() 和 computed 等选项处理之前立即调用。此时不能获得DOM节点
  • created:在这个阶段vue实例已经创建,以下内容已经设置完成:响应式数据、计算属性、方法和侦听器。然而,此时挂载阶段还未开始,因此 $el 属性仍不可用。仍然不能获取DOM元素。
  • beforeMount:在组件内容被渲染到页面之前自动执行的函数,组件已经完成了其响应式状态的设置,但还没有创建 DOM 节点。
  • mounted:在组件被渲染之后自动执行的函数。一般我们的异步请求都写在这里。在这个阶段,数据和DOM都已被渲染出来。
  • beforeUpdate:数据变化的时候自动执行的函数,此时变化后的数据还未渲染到页面之上。.
  • updated:数据变化之后自动执行的函数,此时变化后的数据已经渲染到页面之上
  • beforeDestroy:当 Vue 应用被销毁时,自动执行的函数。
  • destroyed当 Vue 应用被销毁后,且 dom 完全销毁之后,自动执行的函数。

vue子组件的生命周期?

  • 父:beforeCreate    首先初始化父原素
  • 父:created              父原素挂载数据
  • 父:beforeMounte    父原素开始挂载dom,tpl里遇到子组件
  • 子:beforeCeate      子组件开始挂载数据
  • 子:created              子元素数据挂载成功
  • 子:beforeMount      子元素开始挂载dom
  • 子:mounted            子元素dom挂载结束
  • 父:mounted            父原素dom挂载结束
  • 父:beforeUpdate     下面开始类似于dom事件流
  • 子:beforeUpdate
  • 子:updated
  • 父:updated
  • 父:beforeDestory
  • 子:beforeDestory
  • 子:destroyed
  • 父:destoryed
     

Vue双向绑定:

        vue.js是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调,

  v-model是一个指令,双向绑定实际上是Vue 的编译器完成的,通过输出包含v-model模版的组件渲染函数,实际上还是value属性的绑定及input事件监听,事件回调函数中会做相应变量的更新操作。v-bind:value = "message" v-on:input = "message=event.target.value" 作用在组件上,本质是一个父子组件通信的语法糖,通过 prop 和 .emit 实现, 等同于:value = "message" @input = "$emit('input', $event.target.value)"

keep-alive

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

        生命周期(activated组件激活时调用/deactivated组件停用时调用)

nextTick

        在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM

Vue的Key的作用

        key主要用在虚拟Dom算法中,每个虚拟节点VNode有一个唯一标识Key,通过对比新旧节点的key来判断节点是否改变,用key就可以大大提高渲染效率

diff算法

        diff算法是指对新旧虚拟节点进行对比,并返回一个patch对象,用来存储两个节点不同的地方,最后利用patch记录的消息局部更新DOM

虚拟DOM的优缺点

        缺点:首次渲染大量DOM时,由于多了一层虚拟DOM的计算,会比innerHTML插入慢,优点:减少了dom操作,减少了回流与重绘

回流和重绘

        render树中一部分或全部元素需要改变尺寸、布局、或着需要隐藏而需要重新构建,这个过程叫做回流,回流必将引起重绘

Vue组件之间的通信方式

  • 父传子:子组件设置props + 父组件设置v-bind
  • 子传父:组件的$emit + 父组件设置 v-on
  • erf/refs:在子组件上,它的用用就指向了子组件的实例,可以通过实例来访问组件的数据和方法
  • eventBus事件总线:(不会用)

Vue路由传参的方式

        params 传参:刷新后会丢失数据
//编程式
this.$router.push({
    name: 'home', //注意使用 params 时一定不能使用 path
    params: { username: this.username },
  })

//声明式
<router-link :to="{ name: 'home', params: { username: username } }">
query 传参:
//编程式
this.$router.push({
    path: '/home',
    query: { username: this.username },
  })

//声明式
<router-link :to="{ path: '/home', query: { username: username } }">

computed和watch的区别

        computed是计算属性,依赖其他属性,当其他属性改变的时候下一次获取computed值时也会改变
  • 它支持缓存,只有依赖的数据发生了变化,才会重新计算。例如模板中多次用到数据拼接可以用计算属性,只执行一次计算,除非数据发生变化。
  • 不支持异步,如果有异步操作,无法监听数据的变化。
  • 如果属性值是函数,默认使用get方法,函数的返回值就是属性的属性值。还有一个set方法,当数据变化时就会调用set方法。
  • computed的值会默认走缓存,计算属性是基于它们的响应式依赖进行缓存的,也就是基于data声明过,或者父组件传递过来的props中的数据进行计算的。
     
        watch侦听器:
  • 它不支持缓存,数据变化时,它就会触发相应的操作。
  • 支持异步监听。
  • 接受两个参数,第一个是最新的值,第二个是变化之前的值。
  • 监听data或者props传来的数据,发生变化时会触发相应操作。有两个参(immediate/deep)

map和forEach的区别

        都是循环遍历数组中的每一项 forEach和map方法里每次执行匿名函数都支持3个参数,map方法返回一个新的数组,数组中的元素为原始数组调用函数处理后的值

v-if和v-show区别?

        v-if控制Dom是否存在,v-show控制样式

为什么避免 v-if 和 v-for 用在一起

        当 Vue 处理指令时,v-for 比 v-if 具有更高的优先级,这意味着 v-if 将分别重复运行于每个 v-for 循环中,带来性能方面的浪费。

单页面应用是什么?优缺点?如何弥补缺点

  • 单页面对一个入口DOM通过路由去更改内容,整个应用只有一个html页面
  • SPA优点:用户体验好,没有页面切换就没有白屏情况;
  • SPA缺点:首屏加载慢,不利于SEO
  • SPA弥补:通过压缩、路由懒加载缓解首屏慢;通过SSR 服务器端渲染解决SEO问题;

Vue首屏优化怎么做?

  • 使用较轻量的组件,比如echart对应有vue-chart

  • vue-cli开启打包压缩 和后台配合 gzip访问;

  • 路由懒加载,分包;

  • 打包时配置删掉log日志

  • 资源过大可以使用cdn模式引入,不再打包到本地

vue2的缺陷是什么?如何解决vue2.0数组中某一项改变,页面不改变的情况?


        缺陷:数据如果为对象直接新增属性,如果为数组通过下标操作数组项,页面无法触发更新。

        对策:关于对象可以通过Vue.$set(obj,key,value),组件中通过this.$set(obj,key,value)实现新增,修改属性vue可以相应更新视图。关于数组也可以通过Vue.$set(obj,key,value),或者作者重写的那些方法来操作;

Vue.use()是干什么的

  1. 首先 Vue.use 本身是一个函数;
  2. 判断插件是否注册;
  3. 如果插件自带insatll属性,执行它,同时传递一个Vue构造函数作为第一个参数,以及use中的其他参数;
  4. 如果插件本身就是函数,执行它,同时传递一个Vue构造函数作为第一个参数,以及use中的其他参数
  5. 记录这个插件已经注册;

Vuex

        vuex是一个状态管理工具,集中式的管理所有组件的状态数据。统一的去管理组件,将组件的状态抽象为一个store文件,通过commit方法触发mutation里的函数来改变组件属性。

        五个属性state(存储) getters(获取) mutations(同步操作 /this.$store.commit(“方法名”,数据)/mapMutations) actions(异步操作 /this.$store.dispatch(“方法名”,数据)/mapActions) modules(放多个vuex)

vue组件中data为什么必须是一个函数

        防止组件重用的时候导致数据相互影响;因为data会挂在组件的原型上;所有实例共有
如果不是函数,则两个实例都引用同一个对象,当其中一个实例属性改变时,另一个实例属性也随之改变

SE6

什么是Promise

        Promise异步编程的一种解决方案。Promise是一个构造函数,接收一个函数作为参数,返回一个 Promise 实例。
let p = new Promise(function(resolve, reject){
		//做一些异步操作
		setTimeout(function(){
			console.log('执行完成Promise');
			resolve('要返回的数据可以任何数据例如接口返回数据');
		}, 2000);
	});
  • Promise对象有三种状态,他们分别是 pending(等待中) resolved(已完成)rejected(拒绝)
  • Promise.all哪怕一个请求失败了也能得到其余正确的请求结果的解决方案
  • promise 的then会返回一个新的 promise 对象,能保证 then 方 可以进行链式调用

async、await

  • Async 和 await 是一种同步的写法,但还是异步的操作,两个必须配合一起使用
  • 函数前面的async关键字,表明该函数内部有异步操作。调用该函数时,会立即返回一个Promise对象,await 是个运算符,用于组成表达式,await 表达式的运算结果取决于它等的东西,如果是promise则会等待promaise 返回结果,接普通函数直接进行链式调用
  • 如果await后面不是Promise对象, 就直接返回对应的值,只能在async函数中出现, 普通函数直接使用会报错,await语句后的Promise对象变成reject状态时,那么整个async函数会中断,后面的程序不会继续执行

宏任务和微任务有哪些?执行顺序

        宏任务:script,setTimeout,setInterval。
        微任务:Promise,process.nextTick。

        微任务会优先于宏任务执行。这意味着在当前任务执行结束后,所有微任务都会被立即执行,而宏任务只有在所有微任务执行完毕后才会执行。

箭头函数

  • 箭头函数实现了一种更加简洁的书写方式。箭头函数内部没有arguments,也没有prototype属性,所以不能用new关键字调用箭头函数。
  • 箭头函数和普通函数最大的区别在于其内部this永远指向其父级对象的this。(重点)

var  let  const的区别

  • var声明的变量存在变量提升,即变量可以在声明之前调用,var允许重复声明变量var不存在块级作用域
  • letconst不存在变量提升,即它们所声明的变量一定要在声明后使用,否则报错
  • letconst存在块级作用域l
  • letconst在同一作用域不允许重复声明变量

ES6新特性

        模板字符串,箭头函数,拓展运输符,map和set,promise和proxy,数组方法Array.from(),map()、filter(),forEach(),some()、every()---------------记得啥说啥

网络原理

从浏览器输入url后都经历了什么

  •  先进行DNS域名解析,先查看本地hosts文件,查看有没有当前域名对应的ip地址,若有直接发起请求,没有的话会在本地域名服务器去查找,没找到的话就去根服务器查找最后查找到对应的ip地址后把对应规则保存到本地的hosts文件中。
  • 进行http请求,三次握手四次挥手建立断开连接
  • 服务器处理,可能返回304也可能返回200
  • 客户端自上而下执行代码渲染页面

TCP协议和HTTP 协议

        TCP协议在建立过程中会进行三次握手四次挥手,三次握手确保双方同步并避免无效连接,四次挥手则正常终止连接或异常终止连接。

        HTTP协议是超文本传输协议(Hyper Text Transfer Protocol),是用于从万维网服务器传输超文本到本地浏览器的传送协议。HTTP是一个基于TCP/IP通信协议来传递数据的。

HTTP与HTTPS有什么区别

        HTTP协议传输的数据都是未加密的,也就是明文的,因此使用HTTP协议传输隐私信息非常不安全,为了保证这些隐私数据能加密传输,于是网景公司设计了SSL(Secure Sockets Layer)协议用于对HTTP协议传输的数据进行加密,从而就诞生了HTTPS。

如何解决前端跨域问题

        JSONP跨域,CORS,nginx代理跨域,nodejs中间件代理跨域,WebSocket协议跨域

 WebSocket和webwork

        WebSocket作用是即使通信双向通信,webwork是多进程的

性能优化

  1. 异步组件:对于较大的组件,可以使用异步组件进行延迟加载,提高页面加载速度。

  2. 列表性能优化:对于大数据列表,使用虚拟滚动或分页加载来减少渲染的数据量。
  3. 图片优化:使用适当的图片压缩和懒加载,并提供多种分辨率的图片,以避免不必要的网络负载。
  4. 组件懒加载:将页面按需加载,只加载当前视图所需的组件,减少首次加载的体积和渲染时间。
  5. 减少重绘和回流:合理使用CSS样式,避免频繁的DOM操作,以减少页面的重绘和回流。
  6. 接口过慢:后端优化接口,分段式请求接口,对加载过慢的接口做过度动画提升用户体验。
  7. 使用浏览器缓存:在合适的情况下,使用浏览器缓存可以显著减少请求时间,提高页面加载速度。

Webpack是什么

  1. Webpack是一个模块打包工具,可以使用它管理项目中的模块依赖,并编译输出模块所需的静态文件。
  2. 它可以很好地管理、打包开发中所用到的HTML,CSS,JavaScript和静态文件(图片,字体)等,让开发更高效。
  3. 对于不同类型的依赖,Webpack有对应的模块加载器,而且会分析模块间的依赖关系,最后合并生成优化的静态资源。

Webpack的基本功能?

  1. 代码转换:TypeScript 编译成 JavaScript、SCSS 编译成 CSS 等等
  2. 文件优化:压缩 JavaScript、CSS、HTML 代码,压缩合并图片等
  3. 代码分割:提取多个页面的公共代码、提取首屏不需要执行部分的代码让其异步加载
  4. 模块合并:在采用模块化的项目有很多模块和文件,需要构建功能把模块分类合并成一个文件
  5. 自动刷新:监听本地源代码的变化,自动构建,刷新浏览器
  6. 代码校验:在代码被提交到仓库前需要检测代码是否符合规范,以及单元测试是否通过
  7. 自动发布:更新完代码后,自动构建出线上发布代码并传输给发布系统。

HTML&&CSS

盒模型和怪异和模型

  • 标准盒模型,总宽度 = width + border(左右) + padding(左右)+ margin(左右);高度同理。

  • 怪异盒模型(IE盒模型),总宽度 = width + margin(左右);高度同理。

让一个元素水平/垂直居中

  1. 水平居中 text-align: center;

  2. 垂直居中 margin 实现自适应居中 通过位移 transform 实现 设置 line-height 等于 height align-items: center;

  3. 对于宽度未知的块级元素 flex 布局 dispaly:flex;justify-content: center;align-item:center 绝对定位和 transform 实现, translateX 可以移动本身元素的50%

flex:1 到底代表什么 

        是一个简写方式,相当于同时设置了 `flex-grow: 1`、`flex-shrink: 1`、`flex-basis: 0` 这三个属性。满足项目的自适应需求。

算法题

回溯算法

数组arr[1,2,3] 输出结果[1, 2, 3] [1, 3, 2] [2, 1, 3] [2, 3, 1] [3, 1, 2] [3, 2, 1]

  1. 定义一个空数组res,用于存储所有的排列结果。
  2. 定义一个空数组path,用于存储当前的排列结果。
  3. 编写回溯函数backtrack,函数参数为当前的排列结果path和可选的数字列表nums。
  4. 如果nums为空,说明已经选完了所有的数字,将path加入到res中。
  5. 遍历nums中的每个数字,将其加入到path中,然后从nums中删除该数字,递归调用backtrack函数。
  6. 递归结束后,将path中的最后一个数字删除,将该数字加入到nums中,回溯到上一层。
  7. 调用backtrack函数,开始全排列。
def permute(nums):
    res = []
    path = []
    def backtrack(path, nums):
        if not nums:
            res.append(path[:])
            return
        for i in range(len(nums)):
            path.append(nums[i])
            backtrack(path, nums[:i]+nums[i+1:])
            path.pop()
    backtrack(path, nums)
    return res

arr = [1, 2, 3]
res = permute(arr)
for r in res:
    print(r)

冒泡算法排序

    // 冒泡排序
    /* 1.比较相邻的两个元素,如果前一个比后一个大,则交换位置。

   2.第一轮的时候最后一个元素应该是最大的一个。

   3.按照步骤一的方法进行相邻两个元素的比较,这个时候由于最后一个元素已经是最大的了,所以最后一个元素不用比较。 */
    function bubbleSort(arr) {
      for (var i = 0; i < arr.length; i++) {
        for (var j = 0; j < arr.length; j++) {
          if (arr[j] > arr[j + 1]) {
            var temp = arr[j]
            arr[j] = arr[j + 1]
            arr[j + 1] = temp
          }
        }
      }
    }

    var Arr = [3, 5, 74, 64, 64, 3, 1, 8, 3, 49, 16, 161, 9, 4]
    console.log(Arr, "before");
    bubbleSort(Arr)
    console.log(Arr, "after");

快速排序

    /*
    快速排序是对冒泡排序的一种改进,第一趟排序时将数据分成两部分,一部分比另一部分的所有数据都要小。
    然后递归调用,在两边都实行快速排序。  
    */
    
    function quickSort(arr) {
      if (arr.length <= 1) {
        return arr
      }
      var middle = Math.floor(arr.length / 2)
      var middleData = arr.splice(middle, 1)[0]

      var left = []
      var right = []
      
      for (var i = 0; i < arr.length; i++) {
        if (arr[i] < middleData) {
          left.push(arr[i])
        } else {
          right.push(arr[i])
        }
      }

      return quickSort(left).concat([middleData], quickSort(right))
    }

    var Arr = [3, 5, 74, 64, 64, 3, 1, 8, 3, 49, 16, 161, 9, 4]
    console.log(Arr, "before");
    var newArr = quickSort(Arr)
    console.log(newArr, "after");

  • 40
    点赞
  • 133
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
当谈到前端面试八股文时,以下是一些常见的问题及其答案: 1. 简要介绍一下前端开发的基本工作流程。 前端开发的基本工作流程包括需求分析、界面设计、编码实现、调试测试和部署上线。 2. 请解释一下浏览器的工作原理。 浏览器的工作原理主要包括四个步骤:解析HTML生成DOM树、解析CSS生成CSSOM树、合并DOM树和CSSOM树形成渲染树、将渲染树绘制到屏幕上。 3. 什么是跨域?如何解决跨域问题? 跨域是指在同源策略限制下,不同域之间进行资源请求或数据传输的过程。解决跨域问题可以通过代理服务器、JSONP、CORS等方式。 4. 请解释一下闭包的概念及其使用场景。 闭包是指函数可以访问和操作其词法作用域外的变量。闭包常用于创建私有变量、实现模块化等场景。 5. 请简要解释一下事件冒泡和事件捕获。 事件冒泡是指事件从最具体的元素开始触发,然后逐级向上传播至最不具体的元素。事件捕获则相反,是从最不具体的元素开始触发,然后逐级向下传播至最具体的元素。 6. 请解释一下防抖和节流函数的作用及其区别。 防抖函数用于减少触发频率,延迟执行函数。节流函数用于控制函数执行频率,限制单位时间内函数的执行次数。区别在于防抖函数在最后一次触发后会等待一段时间再执行,而节流函数在单位时间内只执行一次。 7. 请解释一下SPA(单页应用)的概念。 SPA是指通过动态加载页面内容并使用前端路由实现页面切换的一种应用模式。整个应用只有一个HTML页面,通过Ajax等技术加载数据并更新页面内容。 这些问题只是前端面试八股文的一小部分,你可以通过阅读相关的面试题和经验总结来进一步准备。记住,在面试中除了回答问题,也要展示自己的项目经验和解决问题的能力。祝你好运!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值