前端习题-知识深度

for 和 forEach 哪个更快?

for 更快。
for 直接在当前函数中执行,forEach 每次都要新创建一个函数。
函数有单独的作用域和上下文,创建函数需要额外的开销。

JS 垃圾回收、内存泄漏

正常情况下,一个函数执行完,其中的变量都会是会 JS 垃圾回收。但某些情况下(闭包,循环引用),变量是销毁不了的,因为可能会被再次使用。

垃圾回收算法:

  • 引用计数
    早起的垃圾回收算法,以“数据是否被引用”来判断要不要回收。但这个算法有一个缺陷 —— 循环引用无法进行垃圾回收。
  • 标记清除
    现代浏览器使用“标记-清除”算法。根据“是否是否可获得”来判断是否回收。
    定期从根(即全局变量)开始向下查找,能找到的即保留,找不到的即回收。循环引用不再是问题。

变量销毁不了,不一定就是内存泄漏,要看是否符合开发者预期。
闭包的变量是无法被垃圾回收的。但闭包不是内存泄漏,因为它是符合开发者预期的,即本身就这么设计的。而内存泄漏是非预期的。
检测内存变化:使用 Chrome devTools Performance。

内存泄漏的场景:

  • 被全局变量、函数引用,组件销毁时未清除。
  • 被全局事件、全局定时器引用,组件销毁时未清除。
  • 被自定义事件引用,组件销毁时未清除。
  • 闭包(无定论)

扩展:WeakMap WeakSet 弱引用,不会影响垃圾回收。

js-bridge 原理

JS 无法直接调用 app 的 API ,需要通过一种方式 —— 通称 js-bridge ,它也是一些 JS 代码。
js-bridge实现的两种方式:

  • 注册全局API。这种方式一般都是同步的。
  • 劫持 url scheme。自造一个协议标准'my-app-name://api/getVersion' ,让app识别这个协议标准做拦截,不要发送网络请求。

Vue 生命周期

  • beforeCreate
    初始化一个空的 Vue 实例,data methods 等尚未被初始化,无法调用。
  • created
    Vue 实例初始化完成,data methods 都已初始化完成,可调用。
    但尚未开始渲染模板。
  • beforeMount
    编译模板,调用 render 函数生成 vdom ,但还没有开始渲染 DOM
  • mounted
    渲染 DOM 完成,页面更新。组件创建完成,开始进入运行阶段。
  • beforeUpdate
    在数据发生改变后,DOM 被更新之前被调用。这里适合在现有 DOM 将要被更新之前访问它,比如移除手动添加的事件监听器。
  • updated
    在数据更改导致的虚拟 DOM 重新渲染和更新完毕之后被调用。
    注意,尽量不要在 updated 中继续修改数据,否则可能会触发死循环。
  • onActivated
    keep-alive 缓存的组件激活时调用。
  • onDeactivated
    keep-alive 缓存的组件停用时调用。
  • beforeUnmount
    组件进入销毁阶段。
    卸载组件实例后调用,在这个阶段,实例仍然是完全正常的。
    移除、解绑一些全局事件、自定义事件,可以在此时操作。
  • unmounted
    卸载组件实例后调用。调用此钩子时,组件实例的所有指令都被解除绑定,所有事件侦听器都被移除,所有子组件实例被卸载。

连环问:如何正确的操作 DOM
mountedupdated 都不会保证所有子组件都挂载完成,如果想等待所有视图都渲染完成,需要使用 $nextTick

连环问:ajax 放在哪个生命周期合适?
一般有两个选择:createdmounted ,建议选择后者 mounted

连环问:vue3 Composition API 生命周期有何不同

  • setup 代替了 beforeCreatecreated
  • 生命周期换成了函数的形式,如 mounted -> onMounted

vdom 真的很快吗

Vue React 等框架的价值在于组件化、数据视图分离
vdom,Virtual DOM,虚拟 DOM ,即用 JS 对象模拟 DOM 数据。

  • jquery 时代:直接修改 DOM
  • 框架时代:生成 vdom ,进行 diff 运算 --> 修改 DOM

所以,vdom 并不比 DOM 操作更快(反而更慢,它做了 JS 运算),它只是在某个特定的场景下,无法做到精准 DOM 修改时,一个更优的选择。

Vue2、Vue3、React 的diff 算法有什么区别

  • React diff 特点 - 仅向右移动
  • Vue2 diff 特点 - 双端比较
  • Vue3 diff 特点 - 最长递增子序列

Vue React diff 不是对比文字,而是 vdom 树,即 tree diff 。对比虚拟dom。
传统的 tree diff 算法复杂度是 O(n^3) ,算法不可用。

Vue React 都是用于网页开发,基于 DOM 结构,对 diff 算法都进行了优化(或者简化)。最终把时间复杂度降低到 O(n) ,生产环境下可用。这一点 Vue React 都是相同的。

  • 只在同一层级比较,不跨层级 (DOM 结构的变化,很少有跨层级移动)
  • tag 不同则直接删掉重建,不去对比内部细节(DOM 结构变化,很少有只改外层,不改内层)
  • 子节点通过 key 区分

连环问: Vue和React为何循环时必须使用key

  • vdom diff算法会根据key判断元素是否要删除
  • 匹配了key,则只移动元素-性能较好
  • 未匹配key,则删除重建-性能较差

Vue-router 模式

  • hash - 使用 url hash 变化记录路由地址
  • history - 使用 H5 history API 来改 url 记录路由地址
  • MemoryHistory / abstract - 不修改 url ,路由地址在内存中,但页面刷新会重新回到首页。(没法前进后退)

浏览器和 nodejs 事件循环的区别

  • 单线程和异步
    JS 是单线程的,浏览器中 JS 和 DOM 渲染线程互斥。“异步”是单线程的解决方案。

  • 宏任务和微任务
    浏览器端异步的 API 有很多

    • 宏任务:setTimeout 网络请求
    • 微任务:promise、async、await

    两者表面的区别:
    第一,微任务比宏任务更快执行。
    第二,微任务在 DOM 渲染前执行,而宏任务在 DOM 显示后(即真正显示到页面上,肉眼可见)执行。

  • 浏览器事件循环

    • 执行同步代码
    • 将异步函数放入队列
    • 执行微任务队列
    • 网页渲染
    • 执行宏任务队列
  • nodejs 异步
    nodejs 也是用了 V8 引擎和 ES 语法,所以也有同步、异步,异步也分宏任务、微任务。但nodejs 的宏任务是分了如下类型,nodejs 事件循环中宏任务需要按照这个顺序来执行。

    • timers(计时器) - 执行 setTimeout 以及 setInterval 的回调
    • I/O callbacks - 处理网络、流、TCP 的错误回调
    • idle, prepare — 闲置阶段 - node 内部使用
    • poll(轮循) - 执行 poll 中的 I/O 队列,检查定时器是否到时间
    • check(检查) - 存放 setImmediate 回调
    • close callbacks - 关闭回调,例如 socket.on('close')
  • nodejs 事件循环

    • 执行同步代码
    • 执行 process.nextTick 和微任务(前者优先级更高)
    • 按照顺序执行 6 个类型的宏任务
  • 总结

    • 浏览器和nodejs的事件循环流程基本相同。
    • nodejs宏任务和微任务分类型,有优先级。

nodejs 进程之间如何通讯

进程,是操作系统进行资源调度和分配的基本单位,有独立的内存空间。
线程,是操作系统进行运算调度的最小单位。一个进程可以包含多个线程,多线程之间可共用进程的内存数据。
JS 是单线程的,但可以开启多进程执行。
现代服务器都是多核 CPU ,适合同时处理多进程。但操作系统对于一个进程的内存分配是有上限的(2G),所以多进程才能充分利用服务器内存。

  • 可使用 child_process.forkcluster.fork 开启子进程
  • 使用 send on 传递消息
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值