面试js高级知识

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

垃圾回收

什么是垃圾回收?

function fun1() {
    const a = 'cc'
    console.log(a)
    const obj = { x: 100 }
    console.log(obj)
}
fun1()//垃圾回收:执行完了,a obj就会被回收


function fun2() {
    const obj = { x: 100 }
    window.obj = obj//回收不了,符合用户预期
}
fun2()

function getDataFns() {
    const data = {}//闭包
    return {
        get(key) {
            return data[key]
        },
        set(key, val) {
            data[key] = val
        }
    }
}
垃圾回收的算法:
  • 引用计数(早期算法)
    看看对象的引用数,为0就回收
//对象被a引用
let a = {x:100}
let a1 = a
a = 10
a1 = null//此时,{x:100}引用数为0,被回收

//引用计数缺点,循环引用,不能清除
function fun3(){
    const obj1 = {}
    const obj2 = {}
    obj1.a = obj2
    obj2.a = obj1
}
fun3()
  • 标记清除(现代)
    定期遍历JS根window所有的子属性,得到保留,没有清除
闭包是内存泄漏吗?

其实闭包是不可以被垃圾回收
内存泄漏是非预期的情况
闭包是符合预期的,不是内存泄漏

检测工具

使用performance检测内存
在这里插入图片描述

内存泄漏的场景(Vue为例)
  • 被全局变量、函数引用,组件销毁时未清除
  • 被全局事件、定时器引用,组件销毁时未清除
  • 被自定义事件引用,组件销毁时未清除
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
WeakMap WeakSet(点击有更详细的解释)
  • weakSet里面的对象是弱引用
    在weakSet里引用了对象,垃圾回收机制不会考虑该对象的引用,若外面已经没有该对象的引用了,则垃圾回收机制会回收该对象,weakSet内部引用的该对象也会自动消失
    所以weakSet内部的对象不适合被引用,也不允许遍历,因为有可能遍历的过程,内部的对象被垃圾回收机制回收了
    用处:
    1、在weakSet中存储一些临时的对象,当外部该对象的引用消失了,weakSet内部该对象的引用也自动消失了,不用担心内存泄漏
    2、存储一些DOM节点,这样就不用DOM节点从文档中移除时,产生内存泄漏

  • weakMap键名指向的对象(注意:不是键值)不会对垃圾回收机制造成影响
    在网页的 DOM 元素上添加数据,就可以使用WeakMap结构。当该 DOM 元素被清除,其所对应的WeakMap记录就会自动被移除

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

单线程和异步
  • js是单线程的(无论在浏览器还是在node.js)
  • 浏览器中js执行和DOM渲染共用一个线程
  • 异步
宏任务和微任务
  • 宏任务,如setTimeout setInterval网络请求
  • 微任务,如promise async/await
  • 微任务是在下一轮DOM渲染之前执行,宏任务是之后执行
    在这里插入图片描述
nodejs异步
  • nodejs同样使用ES语法,也是单线程,也需要异步
  • 异步任务分:宏任务+微任务
  • 但是,它的宏任务和微任务,分不同的类型,有不同的优先级

在这里插入图片描述

nodejs宏任务类型和优先级
  • Timer-setTimeout setInterval
  • I/O callbacks - 处理网络、流、TCP的错误回调
  • Idle、prepare-闲置状态(nodejs内部使用)
  • poll轮询-执行poll中的I/O队列
  • check检查-储存setImmediate回调
  • close callbacks-关闭回调,如socket.on(‘colse’)
nodejs微任务类型和优先级
  • promise,async/await、process.nextTick(优先级最高)
nodejs的eventloop
  • 执行同步代码
  • 执行微任务(process.nextTick优先级最高)
  • 按顺序执行6个类型的宏任务(每个开始之前都执行当前的微任务)
    在这里插入图片描述
    浏览器和nodejs的eventloop流程基本相同
    nodejs宏任务和微任务分类型、有优先级

虚拟DOM真的很快吗

vdom
  • Virtual DOM,虚拟DOM
  • 用js对象模拟DOM节点数据
  • 最先由React推广使用
    vdom并不快,js直接操作DOM才是最快的
    但是‘数据驱动视图’要有合适的技术方案,不能全部DOM重建

遍历数组,for…和forEach哪个更快

const arr = []
for (let i = 0; i < 100 * 10000; i++) {
    arr.push(i)
}
const length = arr.length
console.time('for')
let n1 = 0
for (let i = 0; i < arr.length; i++) {
    n1++
}
console.timeEnd('for')//2.7ms

console.time('forEach')
let n2 = 0
arr.forEach(ele => { n2++ })
console.timeEnd('forEach')//3.5ms
  • for更快
  • forEach每次创建一个函数来调用,而for不会创建函数
  • 函数需要独立的作用域,会有额外的开销
  • 越低级的代码,性能会越好

nodejs如何开启进程,进程如何通讯?

进程process vs 线程thread
  • 进程,OS进行资源分配和调度的最小单位,有独立空间
  • 线程,OS进行运算调度的最小单位,共享进程内存空间
  • js是单线程,但是可以开启多个进程执行,如WebWoker
为何需要多进程?
  • 多核CPU,更适合处理多进程
  • 内存较大,多个进程才能更好的利用(单进程有内存上限)
  • 总之是为了压栈机器资源,更快,更省

主进程
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

  • 开启子进程child_process.fork和cluster.fork
  • 使用send和on通讯

请描述JS Bridge原理

什么是JS Bridge

  • JS无法直接调用native API
  • 需要通过一些特定的“格式”来调用
  • 这些格式就统称为JS Bridge,例如微信的JSSDK
    在这里插入图片描述

JS Bridge的常见实现方式

  • 注册全局API(适用于简单的异步通讯,不适用于异步的情况)
  • URL Scheme(自造协议,主要是通过iframe)
const sdk = {
    invoke(url,data,onSuccess,onError){
        const iframe = document.createElement('iframe')
        iframe.style.visibility = 'hidden'
        document.body.appendChild(iframe)
        iframe.onload=()=>{
            const content = iframe.contentWindow.document.body.innerHTML
            onSuccess(JSON.parse(content))
            iframe.remove()
        }
        iframe.onerror=()=>{
            onError()
            iframe.remove()
        }
        iframe.src= `wexin://${url}?data=${JSON.stringify(data)}`
    }
}

是否了解过requestIdleCallback和requestAnimationFrame有什么区别?

由React fiber引起的关注
  • 组建树转链表,可分段渲染
  • 渲染时可以暂停,执行其他高优的任务,空闲时再继续渲染
  • 如何判断是空闲呢?——requestIdleCallback
    如图链表结构
    在这里插入图片描述

区别:

  • requestAnimationFrame每次渲染都会执行,高优
  • requestIdleCallback空闲时才会执行,低优
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>requestAnimationFrame</title>
</head>
<style>
  #box{
    width: 100px;
    height: 100px;
    border: 2px solid black;
  }
</style>
<body>
  <p>requestAnimationFrame</p>
  <button id="btn1">change</button>
  <div id="box"></div>

  <script>
    const box = document.getElementById('box')
    document.getElementById('btn1').addEventListener('click',()=>{
      let curWidth =100
      const maxWidth = 400
      function addWidth(){
        curWidth = curWidth +3
        box.style.width = `${curWidth}px`

        if(curWidth<maxWidth){
          window.requestAnimationFrame(addWidth)//时间不用自己控制
        }
      }
      addWidth()
    })  
  </script>
</body>

</html>
是宏任务还是微任务?

是宏任务,在dom渲染后执行
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

  • 14
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值