前端面试题(持续更新)

目录

js面试题

事件冒泡和事件捕获的原理以及它们的区别与使用场景

防抖和节流

VUE面试题

vue中history和hash的区别是什么

vue的响应式原理 


HTML面试题

cookie,localStorage,sessionStorage的区别

  • 存储大小:cookie40kb左右,Storage20M左右。
  • 存储格式:cookie是字符串格式,Storage是键值对。
  • 通讯相关:cookie随请求携带,Storage不会自动携带。
  • 操作相关:cookie操作复杂,没有api前后端都可以操作;Storage操作简单,有api,只能前端操作。

输入一个url到页面渲染发生了什么

  1. 浏览器地址栏输入URL并回车
  2. 浏览器查找当前URL是否存在缓存,并比较缓存是否过期
  3. DNS解析URL对应ip
  4. 根据ip建立TCP连接
  5. 发送http请求
  6. 服务器处理请求,浏览器接收HTTP响应
  7. 浏览器解析并渲染页面
  8. 关闭TCP连接

如果要做优化,CSS提高性能的方法有哪些?

  1. 内联首屏关键css
  2. 异步加载css
  3. 资源压缩
  4. 合理使用选择器
  5. 不要使用@import

js面试题

检测数据类型的方法

  1. typeof检测基本数据类型
  2. Object.prototype.toString.call()
  3. A  instanceof B 

null 和 undefined 区别

首先undefinednull都是基本数据类型,这两个基本数据类型分别都只有一个值,就是undefinednull.

undefined代表的含义是未定义,null代表的含义是空对象.一般变量声明了但还没有定义的时候返回undefined,null主要用于赋值给一些可能会返回对象的变量,作为初始化.

console.log(typeof null) // object

console.log(null == null) // true

console.log(null === null) // true

setTimeout和setInterval定时器无法按时执行的原因

js是单线程,所以异步事件仅在空闲时才会被调用,代码执行异步事件时会按照将它们添加到队列的顺序执行,如果队列是空的,那么添加代码会立即执行,如果队列不是空的,那么就要等前面代码执行完在执行。

ES6新特性

  1. 新增块级作用域let定义变量和const定义常量。
  2. 变量的结构赋值。
  3. 模板字符串
  4. 箭头函数
  5. 扩展运算符
  6. 模块(import / export)
  7. 类(class / extends)

new操作符具体做了什么

  1. 在内存创建一个新对象
  2. 把构造函数中的this指向新建的对象
  3. 会在新对象上添加一个__proto__属性,指向函数的原型对象prototype
  4. 判断函数返回值,如果值是引用数据类型就直接返回值,否则就返回this(新建对象)

this指向的各种情况

  1. 全局作用域中的函数,在非严格模式下this的指向是window
  2. 对象内部函数,其内部this指向对象本身
  3. 构造函数:其内部this指向生成的实例对象
  4. apply,call,bind改变的this的指向,其this指向第一个参数
  5. 箭头函数指向它的上级对象

普通函数 箭头函数的区别

  1. 箭头函数没有原型 它原型是undefined
  2. 箭头函数的this应该是创建时所在作用域指向的对象
  3. call,apply,bind方法改变不了箭头函数的指向

call(),apply(),bind()的区别

  • call()的参数是直接放进去的,第二个参数之后的参数全部都用逗号分隔
  • apply()的所有参数都必须在一个数组中传进去
  • bind()除了返回的是函数以外,它的参数和call()一样
  • 三者都可以改变this的指向对象
  • 三者第一个参数都是this要指向的对象,如果没有这个参数或参数为undefined或null时,默认指向全局变量window
  • 三者都可以传参,但是apply()是数组,而call()是参数列表,且apply()和call()是一次性传入参数,而bind()可以分为多次传入
  • bind()是返回绑定this之后的函数,便于稍后调用;apply()和call()是立即执行

事件冒泡和事件捕获的原理以及它们的区别与使用场景

事件冒泡的原理:事件从触发的目标元素开始,然后逐级冒泡到上一个元素,直到达到DOM树的根节点.当事件冒泡时,父级元素的事件处理程序会在子级元素的事件处理程序之前被触发.

事件冒泡的使用场景:事件冒泡的一个常用场景是事件委托.通过事件委托我们可以将事件处理程序绑定到父元素上,而不是绑定到子元素上,从而减少事件处理程序的数量,提高性能和代码的可维护性.

事件捕获的原理:事件从DOM树的根节点开始,然后逐级向下捕获到最具体的元素(目标元素)。当事件捕获时,父级元素的事件处理程序会在子级元素的事件处理程序之后被触发。

事件捕获的使用场景:如果你需要在事件达到特定元素之前执行一些操作,例如在事件到达目标元素之前进行验证或修改事件的行为,可以使用事件捕获。通过在父级元素上使用事件捕获,你可以在事件到达目标元素之前拦截事件并进行处理。

事件冒泡和事件捕获区别:

  1. 触发顺序:事件捕获先于事件冒泡触发。在事件捕获阶段,事件从DOM树的根节点向下传播到目标元素;在事件冒泡阶段,事件从目标元素向上冒泡到根节点。
  2. 事件处理程序执行顺序:在事件捕获阶段,级元素的事件处理程序会先于子级元素的事件处理程序执行;在事件冒泡阶段,级元素的事件处理程序会先于父级元素的事件处理程序执行。
  3. 默认阶段:大多数事件处理程序默认情况下在事件冒泡阶段触发,因此它们通常在事件冒泡阶段被执行。但是,可以使用addEventListener的第三个参数来指定事件是在事件捕获阶段还是事件冒泡阶段处理

防抖和节流,应用场景

相同点:

  1. 都是为了减少事件触发频率,优化性能。

不同点:

  1. 节流是指在一段时间内最多触发一次事件,节流算法会在特定的时间间隔内判断是否触发事件;

  2. 防抖是指在一段时间内只要有事件触发,就重新计算时间,直到这段时间内没有事件触发,才真正的执行事件;
  3. 节流适用于持续的触发,防抖适用于短时间内的大量触发。

应用场景:

防抖(debounce):

       search搜索联想,用户在不断输入值时,用防抖来节约请求资源。

        window触发resize的时候,不断的调整浏览器窗口大小会不断的触发这个事件,用防抖来让 其只触发一次.在在.

节流(throttle):

鼠标不断点击触发,mousedown(单位时间内只触发一次)

监听滚动事件,比如是否滑到底部自动加载更多,用throttle来判断

闭包

在一个函数A内部有一函数B,并且将B函数return出去便使在外部的B函数能够访问A函数中的变量即形成了一个简单的变量闭包。

作用:

  1. 可以在函数外部访问到函数內部的变量
  2. 可以将某个函数内部的值保存下来
  3. 可以避免使用全局变量,赋值全局变量被污染

缺点:

每次外部函数执行前都会开辟出新的内存空间,并且函数的地址不同,开辟出的内存地址也不同,导致一块内存被长期占用而不会被垃圾回收机制释放,便会导致内存泄漏。

什么是原型

所有函数都有一个prototype(显示原型对象)属性.

所有对象都有一个__proto__(隐式原型对象)属性

所有内置函数都是function这个函数的实例对象

原型链

当js试图得到一个对象的属性时,会先去这个对象的本身去寻找,如果这个对象本身没有找到这个属性,那么js就会去它构造函数的’prototype’属性中去寻找,也就是去’proto‘中寻找,如果’prototype’属性本身中依旧没有找到,’prototype’中依旧有一个‘proto’。

对象查找属性或者方法的顺序:

先在对象本身查找–>构造函数中查找–>对象的原型中查找–>构造函数的原型中查找–>当前原型中查找.

原型链的最顶端是null

原型可以解决什么问题:

对象共享属性和方法

继承有哪些方法

  1. 原型链继承
  2. 构造函数继承
  3. 实列继承
  4. 组合式继承
  5. 寄生组合继承

VUE面试题

vue中history和hash的区别是什么

  1. hash路由url有"#",而history没有
  2. hash路由的实现原理是通过监听hashChange事件来实现的,history是通过调用history.pushState方法并且监听popstate事件来实现的.history.pushState会追加历史记录,并更换地址栏的地址信息,但页面不会刷新.

vue的响应式原理 

当vue组件被创建时,在生命周期的第一阶段(创建阶段)vue使用Object.defineProperty()对data选项进行遍历劫持并添加get/set钩子;在生命周期第二阶段(挂载阶段)指令与声明式变量touch时,会发生依赖收集,这时候再调用当前组件的watcher进行第一次Dom渲染,如果声明式变量发生变化时,vue会再次通知watcher更新视图。

动态给vue的data添加一个新的属性时会发生什么?怎样解决?

在vue2中,如果直接给data添加属性不会触发响应式.这是因为vue2是通过Object.defineProperty来实现响应式的.当对象的初始属性被设置为响应式数据后,后续直接添加的新属性并没有通过Object.defineProperty设置成响应式数据.

Vue3中是使用Proxy来实现响应式的,直接动态新增属性通常可以实现响应式的.

解决方法:

  1. 通过Vue.set()向响应式对象中添加一个属性,并确保这个新属性同样是响应式的.                   语法:   Vue.set(target,index,value)    target是要添加的属性或数组,index是属性名或索引 value是要这种的值
  2. 使用Object,assign()方法合并原对象和包含新属性的对象
  3. 使用$forceUpdate()方法:该方法会强制更新整个组件,重新触发响应式

computed和watch的区别

computed是计算属性,依赖其它属性值,并且computed的值有缓存,只有它依赖的属性值发生改变,下次获取的属性值才会重新计算。

watch更多的是观察的作用,类似于某些数据的监听回调,每当监听的数据变化时都会执行回调

组件中data为什么是一个函数,new Vue实例是一个对象

因为组件是用来复用的,且在js里的对象是引用关系,如果组件中的data是一个对象,那么作用域就没有隔离,子组件中的data属性值会互相影响,如果组件中的data是一个函数,那么每个实例都会返回一个对象,组件之间的data属性值不会互相影响;而new Vue的实例不会被复用的,所以不存在引用对象的问题

你知道vue中key的原理吗?说说你对它的理解

key是用于标识节点唯一性。

其主要原理及作用包括:

  1. 高效的更新渲染:Vue在对比新旧虚拟DOM的时,通过key来识别节点是否发生变化,如果没有key,Vue可能会进行不必要的重新渲染。
  2. 精准的节点复用:当有key时,Vue能够更准确的判断那些节点需要更新,那些可以复用,从而减少不必要的操作,提高渲染效率。
  3. 维护组件的状态:对于动态列表,key可以确保组件在数据变化时保持正确的状态和顺序.

Vue实例的生命周期讲一下, mounted阶段真实DOM存在了嘛?

Vue实例从创建到销毁的过程,就是生命周期。

开始创建->初始化数据->编译模板->挂载dom->数据更新重新渲染虚拟 dom->最后销毁。这一系列的过程就是vue的生命周期。

所以在mounted阶段真实的DOM就已经存在了。

beforeCreate:vue实例的挂载元素el和数据对象data都还没有进行初始化,还是一个 undefined状态.

created:vue实例的数据对象data已经有了,可以访问里面的数据和方法, el还没有,也没有挂载dom.

beforeMount:在这里vue实例的元素el和数据对象都有了,只不过在挂载之前还是虚拟的dom节点

mounted:vue实例已经挂在到真实的dom上,可以通过对 dom操作来获取dom节点

beforeUpdate:响应式数据更新时调用,发生在虚拟dom之前,适合在更新之前访问现有的 dom,比如手动移除已添加的事件监听器.

updated:虚拟dom重新渲染之后调用,组成新的 dom已经更新,避免在这个钩子函数中操作数据,防止死循环。

beforeDestroy:vue实例在销毁前调用,在这里还可以使用,通过this也能访问到实例,可以在这里对一些不用的定时器进行清除,解绑事件。

destroyed:vue实例销毁后调用,调用后所有事件监听器会被移除,所有的子实例都会被销毁。

v-bind和v-model的区别, v-model原理知道吗?

//语法糖写法
<input type="text" v-model="name" >
  
  //还原为以下实例
<input type="text" 
 v-bind:value="name" 
 v-on:input="name=$event.target.value"/>

v-bind用来绑定数据和属性以及表达式

v-model使用在表单中,实现双向数据绑定的。

v-model原理:

 通过结合数据绑定和事件监听,实现了视图和数据之间的双向通信,使得开发者能够更方便地处理表单数据的交互。

什么是虚拟DOM?如何实现一个虚拟DOM?说说你的思路

虚拟DOM本质上是一个javaScript对象,它描述了真实DOM节点的结构和属性。通过比较新旧虚拟DOM树的差异,只对实际发生变化的部分进行真实DOM的更新操作。

实现虚拟DOM:

  1. 定义节点类型:创建一个枚举或常量来表示不同的节点类型
  2. 构建虚拟节点:创建一个类来表示虚拟节点,包含节点类型,属性,子节点等信息
  3. 创建元素节点的方法:接收标签名,属性对象和子节点数组作为参数,创建并返回对应的虚拟元素节点
  4. 创建文本节点的方法:接收文本内容作为参数,创建并返回对应的虚拟文本节点
  5. 比较两个虚拟DOM树的差异:通过深度优先遍历两个DOM树,比较节点的类型,属性和子节点的差异
  6. 根据差异更新真实DOM:根据比较得到的差异,对真实DOM进行最小化的修改操作

webpack

1、webpack的作用是什么,谈谈你对它的理解?
现在的前端网页功能丰富,特别是SPA(single page web application 单页应用)技术流行后,JavaScript的复杂度增加和需要一大堆依赖包,还需要解决Scss,Less……新增样式的扩展写法的编译工作。
所以现代化的前端已经完全依赖于webpack的辅助了。
现在最流行的三个前端框架,可以说和webpack已经紧密相连,框架官方都推出了和自身框架依赖的webpack构建工具。
react.js+WebPack
vue.js+WebPack
AngluarJS+WebPack
2、webpack的工作原理?
WebPack可以看做是模块打包机:它做的事情是,分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(Sass,TypeScript等),并将其转换和打包为合适的格式供浏览器使用。在3.0出现后,Webpack还肩负起了优化项目的责任。
3、webpack打包原理
把一切都视为模块:不管是 css、JS、Image 还是 html 都可以互相引用,通过定义 entry.js,对所有依赖的文件进行跟踪,将各个模块通过 loader 和 plugins 处理,然后打包在一起。
按需加载:打包过程中 Webpack 通过 Code Splitting 功能将文件分为多个 chunks,还可以将重复的部分单独提取出来作为 commonChunk,从而实现按需加载。把所有依赖打包成一个 bundle.js 文件,通过代码分割成单元片段并按需加载
4、webpack的核心概念
Entry:入口,Webpack 执行构建的第一步将从 Entry 开始,可抽象成输入。告诉webpack要使用哪个模块作为构建项目的起点,默认为./src/index.js
output :出口,告诉webpack在哪里输出它打包好的代码以及如何命名,默认为./dist
Module:模块,在 Webpack 里一切皆模块,一个模块对应着一个文件。Webpack 会从配置的 Entry 开始递归找出所有依赖的模块。
Chunk:代码块,一个 Chunk 由多个模块组合而成,用于代码合并与分割。
Loader:模块转换器,用于把模块原内容按照需求转换成新内容。
Plugin:扩展插件,在 Webpack 构建流程中的特定时机会广播出对应的事件,插件可以监听这些事件的发生,在特定时机做对应的事情。
5、Webpack的基本功能有哪些?
代码转换:TypeScript 编译成 JavaScript、SCSS 编译成 CSS 等等
文件优化:压缩 JavaScript、CSS、html 代码,压缩合并图片等
代码分割:提取多个页面的公共代码、提取首屏不需要执行部分的代码让其异步加载
模块合并:在采用模块化的项目有很多模块和文件,需要构建功能把模块分类合并成一个文件
自动刷新:监听本地源代码的变化,自动构建,刷新浏览器
代码校验:在代码被提交到仓库前需要检测代码是否符合规范,以及单元测试是否通过
自动发布:更新完代码后,自动构建出线上发布代码并传输给发布系统。
6、gulp/grunt 与 webpack的区别是什么?
三者都是前端构建工具,grunt和gulp在早期比较流行,现在webpack相对来说比较主流,不过一些轻量化的任务还是会用gulp来处理,比如单独打包CSS文件等。grunt和gulp是基于任务和流(Task、Stream)的。
类似jQuery,找到一个(或一类)文件,对其做一系列链式操作,更新流上的数据, 整条链式操作构成了一个任务,多个任务就构成了整个web的构建流程。webpack是基于入口的。
webpack会自动地递归解析入口所需要加载的所有资源文件,然后用不同的Loader来处理不同的文件,用Plugin来扩展webpack功能。
7、webpack是解决什么问题而生的?
如果像以前开发时一个html文件可能会引用十几个js文件,而且顺序还不能乱,因为它们存在依赖关系,同时对于ES6+等新的语法,less, sass等CSS预处理都不能很好的解决……,此时就需要一个处理这些问题的工具。

如何解决页面请求接口大规模并发问题

 1.缓存策略

  • 利用浏览器,设置合适的http缓存头,让浏览器在一定时间内缓存静态资源和部分数据减少重复请求.

2.限流控制

  • 限制每秒或每分钟请求数量,超过阈值的请求进行排队或直接拒绝

3.异步处理

  • 将非关键请求异步化,不阻塞页面的主要渲染和交互

4.消息队列

  • 对于高并发操作,可以先将请求放入消息队列,然后异步处理,

  • 13
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值