前端面试题集锦-2021年前端面试题收集题库2 1.Javascript延迟加载有哪些方式 2.call和apply的区别和作用? 3. 哪些操作会造成内存泄漏

  • 浏览器解析html全过程

    • 解析HTML结构
    • 遇到script脚本标签(无async,defer)直接执行,或者加载,并且执行script(会阻塞HTML)
    • 解析并执行完脚本
    • Dom树构建完成,加载图片等外部资源
    • 加载结束
  • 延迟加载或者异步加载有什么作用

    • 不阻塞HTML解析,用户体验更好
  • 具体有哪些异步(延迟)加载Javascript的方式

    • 外部script标签 增加async标签或者defer标签
      • 相同点是都可以不阻塞html解析
      • 不同点是:defer是延迟执行async是异步加载,defer会确保在html解析完毕之后再按defer顺序执行js,而async是异步加载,加载完成之后,会直接执行js,并且执行时,此时会阻塞HTML解析
    • 使用js,create Script标签,并且可以设置延迟加载
    • 因为HTML的解析是自上而下的,所以把script标签放到最后面,也会使js在最后加载,也是很多页面js标签写在最后优化体验的最简单的方式

2.call和apply的区别和作用?

  • 作用:改变this(函数内部上下文)指向,很多函数内部会直接使用this指针,指向内部自身对象,并且进行一系列操作,但是如果希望用另一个对象作为该函数的上下文时就需要用到callapply

  • 相同点:

    • 都可以用来改变函数this(函数内部上下文)指向
    • 第一个参数,都是上下文入参
    • 都属于Function.prototype,所有函数类方法
    • 如果第一个参数为 null时,函数体内部this指向默认上下文,可能是window
  • 不同点

    • 除了第一个参数外,后面的参数:都是传入原函数的入参,但是入参接收形式不一样,apply 后面接收的是一个
      类数组,而call接受的后面参数是单个的参数会原封的传入原函数
  • ES6语法的 ...延展语法,可以更方便的使用call,数组也可以直接解构 function.call(obj,...[arry])


3. 哪些操作会造成内存泄漏

  • 什么是内存泄漏

    • 指代码执行时,变量或者代码语句分配的内存空间,无法被自动回收,也不能被继续使用,一直到该进程结束
  • JS中的垃圾回收机制

    • GC garbage collection,自动执行,定时执行,
    • 引用计数: 变量进入环境时(一般是函数作用域),进入环境时,增加标记,环境执行之后,离开环境,标记为:离开环境,变量被回收
    • 标记清除:根据变量被引用次数计数,被引用一次+1,移除引用-1,为0时表示没有变量访问该值,可以被清理
  • 那些操作会造成内存泄漏

    • 函数内部声明的全局变量
      • function(){ test = xxx }
    • 闭包导致的引用计数无法被清除
    • 没有清除的DOM元素引用
    • 忘记clear的定时器和回调
    • DOM元素获取时,子元素的引用(在获取DOM节点时,在直接操作子元素时,父元素也会被内存加载,但是并不会被自动回收,或者经常忘记回收)