前端面试题-知识深度(整理)

357 阅读5分钟

JS 内存泄漏如何检测?场景有哪些?

  1. 检测: 1.1 浏览器的控制台->performance->勾选 Memory->左侧红点开始->stop 结束->clear 清除; 1.2 观察 HEAP 数据(正常为锯齿状,泄漏一直升高);
  2. 场景 2.1 被全局变量,函数引用,组件销毁时未清除; 2.2 被全局事件,定时器引用,组件销毁时未清除; 2.3 被自定义事件引用,组件销毁时未清除;

垃圾回收(GC)的算法:

  1. 引用计数(之前),但是循环引用会发生内存泄漏;
//IE6-IE7 内存泄漏的bug
var div1=docment.getElementById('div1');
div1.a=div1;

2.标记清除:不定时的从 window 遍历,看是否可以得到某个变量,可以得到/不可以得到,保留/删除;

闭包是内存泄漏吗?

闭包不属于内存泄漏,内存泄漏是预期之外的数据不可以被垃圾回收,而闭包的数据不可以被垃圾回收是预期范围内的;

weakMap 和 weakSet

weakMap 和 weakSet 是弱引用,有 get 方法,但是没有 forEach 和 size 方法; weakMap 和 weakSet 的 key 必须是引用类型,value 可以是值类型;

浏览器和 node.js 的时间循环又什么区别?

浏览器和 node.js 的 event loop 流程基本相同;

node.js 的宏任务和微任务分类型和优先级

单线程和异步

js 是单线程(无论浏览器还是 node.js),浏览器中的 js 执行和 DOM 渲染共用一个线程;

宏任务和微任务(浏览器)

宏任务,如 setTimeout,setInterval,网络请求等;

微任务,如 promise,async/await;

微任务在下一轮 DOM 渲染之前执行,宏任务在之后执行;

浏览器执行顺序

同步任务->微任务->网页渲染->宏任务;

先执行同步任务,遇到宏任务或者微任务分别放到两个队列里,当同步任务执行完后,触发 Event loop 机制,执行微任务,接着执行网页的渲染,再执行宏任务;

node.js 异步

Node.js 同样使用 ES 语法,也是单线程,也需要异步.异步任务也分为:宏任务,微任务.但是,它的宏任务和微任务分不同的类型,有不同的优先级;

node.js 宏任务类型和优先级(由高到低)

Timers-setTimeout,setInterval;

I/O callbacks-处理网络,流,TCP 的错误回调;

Idle,prepare-闲置状态(nodeJS 内部使用);

poll 轮训-执行 poll 中的 I/O 队列;

Check 检查-存储 setImmediate 回调;

Close callbacks- 关闭回调,如 socket.on('close');

node.js 宏任务类型和优先级

promise,async/await,process.nextTick;

process.nextTick 的优先级最高;

nodejs 执行顺序

执行同步代码-> 执行微任务(process.nextTick 优先级最高)->按照 6 个优先级的顺序执行宏任务

新版本 node.js 推荐使用 setImmediate 代替 process.nextTick;

vdom 真的很快吗?

vdom 并不快,JS 直接操作 DOM 才是最快的,但"数据驱动视图",要有合适的方案,不能全部 DOM 重建,vdom 就是目前最合适的技术方案.

vdom

Virtual DOM ,虚拟 DOM.用 JS 对象模拟实现 DOM 节点数据,由 React 最先推广使用.

Vue React 等框架的价值

组件化

数据视图分离,数据驱动视图(重要)

遍历数组,for 和 forEach 那个更快?

for 会更快,forEach 每次都要创建一个函数来调用,而 for 不会创建函数;函数需要独立的作用域,会有额外的开销;

nodejs 如何开启进程,进程如何通讯?(PM2)

进程:OS 进行资源分配和调度的最小单位,有独立的内存空间;

线程:OS 进行运算调度的最小单位,共享进程内存空间;

JS 是单线程的,但可以开启多进程执行,如 WebWorker;

答案:开启子进程 child_process.fork 和 cluster.fork,使用 send 和 on 传递信息;

为何需要多进程

多核 CPU,更适合处理多进程;

内存较大,多个进程 才好利用(单进程有内存上限)

什么是 js Bridge 实现原理?

常见的实现方式?

注册全局 API

URL Scheme

requestIdCallback 和 requestAnimationFrame 有什么区别?

requestAnimationFrame 每次渲染完都会执行,高优;

requestIdCallback 空闲时才会执行,低优;

由 React fiber 引起的关注

组件树转换为链表,可以分段渲染;

渲染时可以暂停,去执行其他高优任务,空闲时再继续渲染;

如何判断空闲?- requestIdCallback;

他们是宏任务还是微任务

都是宏任务,因为他们在 DOM 渲染完才会执行;

vue 每个生命周期都做了什么?

beforeCreate:创建一个空白的 vue 实例,data method 尚未被创建,不可以使用;

created:Vue 实例初始化完成,完成响应式绑定,data method 都已经初始化完成,可以调用,尚未创建模板;

beforeMount:编译模板,调用 render 生成 vdom,还没有开始渲染 DOM;

mounted:完成 DOM 渲染,组件创建完成;

beforeUpdate:data 发生变化,准备更新 DOM;

updated:data 发生变化,且 DOM 更新完成;(不要在 updated 中修改 data,可能会导致死循环)

beforeUnmount:组件进入销毁阶段(尚未销毁,可以正常使用),可以移除,解绑一些全局事件,自定义事件;

unmounted:组件被销毁了,所有子组件销毁;

Vue 什么时候操作 DOM 比较合适?

mounted 和 updated 都不能保证子组件全部挂载完成,使用$nextTick 渲染 DOM

mounted(){
    this.$nextTick(function(){
        <!-- 仅在整个视图都被渲染之后才会执行 -->
    })
}

Ajax 应该在那个生命周期

created 和 mounted 都可以,推荐 mounted

Vue3 Composition API 生命周期有何区别?

用 setup 代替了 beforeCreate 和 created;

使用 Hooks 函数的形式,如 mounted 改为 onMounted();

Vue2 Vue3 React 三者 diff 算法有何区别?

React diff 仅右移;

Vue2 双端比较;

Vue3 最长递增子序列;

diff 算法

diff 算法很早就有;

diff 算法应用广泛,例如 GitHub 的 pull Request 中的代码 diff;

如果要严格 diff 两棵树,时间复杂度 O(n^3),不可用;

Tree diff 的优化

只比较同一层级,不跨级比较;子节点通过 key 区分(key 的重要性)

Vue React 为何循环时必须使用 Key?

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

vue-router 的 MemoryHistory 是什么?

vue-router 三种模式

hash:网址中出现#号

webHistory

MemoryHistory(v4 之前叫做 abstract history):没有前进后退