12、js的设计原理是什么
13、js中关于this指向的问题
JavaScript 的 this 原理 - 阮一峰的网络日志
14、script标签里的async和defer有什么区别
15、setTimeout最小执行时间
16、ES6和ES5有什么区别
883a7a4259534f68b98d7b4d9c7e63b9.png
17、ES6的新特性有哪些
5623ce0859d84427a1135b95b0ef91af.png9b1124adc4b94b56a70ef8d257d750e3.png
18、call、apply、bind三者的区别
19、用递归的时候有没有遇到什么问题
20、*set和map的区别
Set和Map的主要区别在于数据结构、操作方式、应用场景等。
数据结构。Set是一种存储唯一值的集合,每个元素只出现一次,不重复;Map是一种键值对集合,每个键与一个值相关联,键是唯一的,值可以重复。
操作方式。Set提供迭代器接口,可以使用for…of循环或forEach方法进行迭代;Map也提供迭代器接口,可以使用for…of循环或forEach方法进行迭代。
应用场景。Set适用于需要存储一组唯一值且不关心顺序的场景,如去重、判断元素是否存在等;Map适用于需要将值与特定键关联的场景,如存储键值对配置信息、构建字典、缓存等。
性能。对于大型数据集合,Set的查询性能较好;Map的查询性能取决于键值对的数量。
修改限制。Set的迭代器是const的,不允许修改元素的值;Map允许修改value,但不允许修改key。
21、说一下事件循环
JavaScript的事件循环机制是一种用于处理异步任务的系统,它确保代码能够顺序执行,同时处理异步操作如定时器和事件监听。事件循环机制主要由以下三个部分组成:
当代码遇到一个异步任务时,该任务的回调函数会被添加到任务队列中。当主线程中的代码执行完毕,事件循环线程会从任务队列中取出一个任务并添加到调用栈中执行。这个过程会一直重复,直到任务队列中没有任何任务为止。需要注意的是,任务队列中的任务是按照先进先出的原则执行的。
在浏览器环境中,主线程运行在浏览器渲染进程中,而渲染进程中还有一个I/O线程和网络进程,它们会产生新的任务。这些任务会被I/O线程放入消息队列中,由渲染进程维护。主线程的事件循环线程会不断地从消息队列中取出新的任务去执行,以处理由I/O线程和其他进程产生的异步任务。
总结来说,JavaScript的事件循环机制通过一个循环系统来处理主线程内部产生的任务以及由其他进程产生的任务,确保代码能够顺序执行并处理异步操作。
*宏任务和微任务的区别
**宏任务和微任务的区别主要在于它们执行的顺序和优先级。**12345
宏任务通常包括整体代码、定时器(例如
setTimeout
和setInterval
)、网络请求、用户交互事件(例如点击和滚动)以及浏览器渲染任务(例如页面重绘或重新布局)。这些任务会在事件循环的每个阶段执行一次,而微任务则包括Promise的resolve
或reject
回调、MutationObserver回调以及某些特定环境(如Node.js的process.nextTick
)。微任务通常在当前宏任务执行完毕后立即执行,不会加入到事件队列中,因此在下一个宏任务开始之前执行。这意味着微任务具有更高的优先级,可以在用户交互或渲染操作之前得到及时处理,例如更新DOM或处理异步操作的结果。总结来说,宏任务是事件循环中的较大任务,而微任务是较小的任务,它们的执行顺序不同,微任务的优先级高于宏任务
22、ajax是什么?怎么实现的
23
24
25
26
27
28
29
30
三、vue相关
1、Vue的事件绑定原理
- 原生
DOM
的绑定:Vue在创建真实DOM时会调用**createElm**
,默认会调用**invokeCreateHooks**
。会遍历当前平台下相对的属性处理代码,其中就有**updateDOMListeners**
方法,内部会传入**add()**
方法- 组件绑定事件,原生事件,自定义事件;组件绑定之间是通过Vue中自定义的
$on
方法实现的。(可以理解为:组件的**nativeOnOn**
等价于 普通元素on 组件的on会单独处理)
2、vue是如何实现响应式数据的呢?(响应式数据原理)❗
Vue2:Object.defineProperty
重新定义data
中所有的属性,Object.defineProperty
可以使数据的获取与设置增加一个拦截的功能,拦截属性的获取,进行依赖收集。拦截属性的更新操作,进行通知。
具体的过程:首先Vue使用 initData
初始化用户传入的参数,然后使用 new Observer
对数据进行观测,如果数据是一个对象类型就会调用this.walk(value)
对对象进行处理,内部使用 defineeReactive
循环对象属性定义响应式变化,核心就是使用Object.defineProperty
重新定义数据。
🌸刚刚如果你说了对象的检测,然后又没说清楚数组的处理的话,我就会问下面这个问题
那vue中是如何检测数组变化的呢?
数组就是使用
object.defineProperty
重新定义数组的每一项,那能引起数组变化的方法我们都是知道的,pop
、push
、shift
、unshift
、splice
、sort
、reverse
这七种,只要这些方法执行改了数组内容,我就更新内容就好了,是不是很好理解。
- 是用来函数劫持的方式,重写了数组方法,具体呢就是更改了数组的原型,更改成自己的,用户调数组的一些方法的时候,走的就是自己的方法,然后通知视图去更新。
- 数组里每一项可能是对象,那么我就是会对数组的每一项进行观测,(且只有数组里的对象才能进行观测,观测过的也不会进行观测)
vue3:改用
proxy
,可直接监听对象数组的变化。
3、为什么Vue采用异步渲染呢?
Vue
是组件级更新,如果不采用异步更新,那么每次更新数据都会对当前组件进行重新渲染,所以为了性能,Vue
会在本轮数据更新后,在异步更新视图。核心思想nextTick
。
dep.notify()
通知 watcher进行更新,subs[i].update
依次调用 watcher 的update
,queueWatcher
将watcher 去重放入队列, nextTick(flushSchedulerQueue
)在下一tick中刷新watcher队列(异步)。
了解nextTick吗?
异步方法,异步渲染最后一步,与JS事件循环联系紧密。主要使用了宏任务微任务(
setTimeout
、promise
那些),定义了一个异步方法,多次调用nextTick
会将方法存入队列,通过异步方法清空当前队列。
4、vue组件间传值的多种方式
Vue 组件间通信只要指以下 3 类通信:父子组件通信、隔代组件通信、兄弟组件通信,下面我们分别介绍每种通信方式且会说明此种方法可适用于哪类组件间通信。
(1)props / $emit 适用 父子组件通信
这种方法是 Vue 组件的基础,相信大部分同学耳闻能详,所以此处就不举例展开介绍。
(2)ref 与 $parent / $children 适用 父子组件通信
ref:如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例
$parent / $children:访问父 / 子实例
(3)EventBus ($emit / $on) 适用于 父子、隔代、兄弟组件通信
这种方法通过一个空的 Vue 实例作为中央事件总线(事件中心),用它来触发事件和监听事件,从而实现任何组件间的通信,包括父子、隔代、兄弟组件。
(4) a t t r s / attrs/ attrs/listeners 适用于 隔代组件通信
a t t r s :包含了父作用域中不被 p r o p 所识别 ( 且获取 ) 的特性绑定 ( c l a s s 和 s t y l e 除外 ) 。当一个组件没有声明任何 p r o p 时,这里会包含所有父作用域的绑定 ( c l a s s 和 s t y l e 除外 ) ,并且可以通过 v − b i n d = " attrs:包含了父作用域中不被 prop 所识别 (且获取) 的特性绑定 ( class 和 style 除外 )。当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定 ( class 和 style 除外 ),并且可以通过 v-bind=" attrs:包含了父作用域中不被prop所识别(且获取)的特性绑定(class和style除外)。当一个组件没有声明任何prop时,这里会包含所有父作用域的绑定(class和style除外),并且可以通过v−bind="attrs" 传入内部组件。通常配合 inheritAttrs 选项一起使用。
l i s t e n e r s :包含了父作用域中的 ( 不含 . n a t i v e 修饰器的 ) v − o n 事件监听器。它可以通过 v − o n = " listeners:包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on=" listeners:包含了父作用域中的(不含.native修饰器的)v−on事件监听器。它可以通过v−on="listeners" 传入内部组件
(5)provide / inject 适用于 隔代组件通信
祖先组件中通过 provider 来提供变量,然后在子孙组件中通过 inject 来注入变量。provide / inject API 主要解决了跨级组件间的通信问题,不过它的使用场景,主要是子组件获取上级组件的状态,跨级组件间建立了一种主动提供与依赖注入的关系。
(6)Vuex 适用于 父子、隔代、兄弟组件通信
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。每一个 Vuex 应用的核心就是 store(仓库)。“store” 基本上就是一个容器,它包含着你的应用中大部分的状态 ( state )。
Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化。
5、diff算法
【面试进阶核心,10张图,带你吃透 “Diff” 算法核心原理(图文详解)_diff算法原理-优快云博客】
时间复杂度: 个树的完全diff
算法是一个时间复杂度为O(n*3)
,vue进行优化转化成O(n)
。
理解:
-
最小量更新,
key
很重要。这个可以是这个节点的唯一标识,告诉diff
算法,在更改前后它们是同一个DOM节点- 扩展
v-for
为什么要有key
,没有key
会暴力复用,举例子的话随便说一个比如移动节点或者增加节点(修改DOM),加key
只会移动减少操作DOM。
- 扩展
-
只有是同一个虚拟节点才会进行精细化比较,否则就是暴力删除旧的,插入新的。
-
只进行同层比较,不会进行跨层比较。
diff算法的优化策略:四种命中查找,四个指针
- 旧前与新前(先比开头,后插入和删除节点的这种情况)
- 旧后与新后(比结尾,前插入或删除的情况)
- 旧前与新后(头与尾比,此种发生了,涉及移动节点,那么新前指向的节点,移动到旧后之后)
- 旧后与新前(尾与头比,此种发生了,涉及移动节点,那么新前指向的节点,移动到旧前之前)
6、Vue性能优化
编码优化:
- 事件代理
keep-alive
- 拆分组件
key
保证唯一性- 路由懒加载、异步组件
- 防抖节流
Vue加载性能优化
- 第三方模块按需导入(
babel-plugin-component
) - 图片懒加载
用户体验
app-skeleton
骨架屏shellap
p壳pwa
SEO优化
- 预渲染
四、react相关
1、*常用的hooks
useState、useEffect、useMemo、useCallback、useSelector、useLocation、useParams、useSearchParams、useReducer、useDispatch、useContext、useRef、useLayoutEffect。。。
2、*useCallback和useMemo区别
**useCallback和useMemo的区别主要在于它们缓存的内容和优化场景不同。**以下是详细介绍:
使用场景不同。useCallback主要用于优化传递给子组件的回调函数,避免不必要的重新创建和渲染;而useMemo主要用于优化计算操作,避免不必要的重复计算。
缓存内容不同。useCallback缓存的是函数本身;而useMemo缓存的是回调函数中return回来的值。
依赖性不同。两者都依赖于依赖项的变化来触发重新计算或缓存的更新,但useCallback更侧重于函数本身是否需要更新,而不是依赖项的直接变化。
此外,使用useCallback时,建议与React.memo一起使用,以确保最佳性能。
3、*不能在循环中使用hooks的原因
为什么hooks不能在循环、条件或嵌套函数中调用_hooks 为什么不能放在条件判断里-优快云博客
Hooks为什么不能写在条件语句或循环语句里_hooks为什么不能写在条件语句中-优快云博客为什么 Hooks 必须写在函数的顶部呢?
原因是因为 React 需要保证在每次组件渲染时,Hooks 的执行顺序都是一致的。
如果将 Hooks 写在循环或条件语句中,那么每次渲染时,Hooks 的执行顺序都可能会发生变化。例如,当循环重新运行时,React 将无法确定哪个 Hook 应该先运行,哪个应该后运行。这样会导致组件状态发生不可预测的变化,从而影响组件的正确性。
PS:为了保证执行顺序及代码易读性
4、*循环中没有key会怎样
2
5、受控组件和非受控组件
在React中,表单元素(如input、select、textarea)可以被设计为受控组件或非受控组件。
受控组件:表单数据由React状态中的单一真实来源控制。每当表单的数据变化时,React状态也会相应更新。可以通过配合e.target.value给react变量赋值。
非受控组件是一种不由React状态控制的组件,表单数据由DOM本身处理。即不受setState()的控制,与传统的HTML表单输入相似,input输入值即显示最新值。
在非受控组件中,可以使用一个ref来从DOM获得表单值。
五、常见项目问题
web浏览器中的javascript
- 客户端javascript
- 在html里嵌入javascript
- javascript程序的执行
- 兼容性和互用性
- 可访问性
- 安全性
- 客户端框架
window对象
-
计时器
-
浏览器定位和导航
-
浏览历史
-
浏览器和屏幕信息
-
对话框
-
错误处理
-
作为window对象属性的文档元素