未找到匹配的笔记

基础

基础

数据类型

原始类型(7种):

undefined, null, boolean, number, string, symbol, bigint

引用类型(1种):

object(含 Array、Function、Date 等)

判断类型

function getType(value) {
  if (value == null) return value + ''; // 'null' or 'undefined'
  return Object.prototype.toString.call(value).slice(8, -1).toLowerCase();
}

作用域

作用域就是变量的活动范围,决定了谁可以访问它。

  • 词法作用域: 是 作用域的查找规则,函数在定义时所在的位置决定了它能访问那些变量,而不是在调用时的位置。作用域在代码书写时就确定了。

作用域的边界单位:

  • 全局作用域:通常指的是window对象
  • 函数作用域:变量在函数执行时创建、在执行结束时销毁,除非被闭包引用,函数外部无法访问。
  • 块级作用域:在大括号{} if、for、switch 或使用let、const生命的变量,只在该代码块内可见

作用域链

作用域链是js引擎查找变量的路径机制,当访问一个变量的时候,会从当前作用域开始,如果找不到会逐层向外查找,直到全局作用域,找不到则报错。

作用域链的结构是在函数定义时就确定的,而不是在调用时,所以变量的查找路径是基于代码的书写结构。

闭包

首先 闭包的定义是:当函数可以记住并访问所在的词法作用域时,就产生了闭包,即使函数是在当前词法作用域之外执行。

更通俗地说:当内部函数引用了外部函数的变量,并且这个内部函数在外部函数执行完后仍然存在(比如被返回或传递出去),就形成了闭包。

闭包的产生有几个条件:

1.存在嵌套函数 
2.内部函数引用了外部函数的变量
3.外部函数返回了内部函数,或以某种方式使内部函数在外部函数执行结束后仍可被访问。

总结就是 闭包 = 内部函数 + 引用外部变量 + 被外部持有引用

闭包有什么作用?

  • 封装私有状态
  • 回调函数中保持上下文状态
  • 模块模式用IIFE+闭包实现命名空间和接口暴露
  • 防抖/节流函数也是通过闭包缓存定时器ID和上一次执行时间
  • 包括Reacthooks,useState的状态之所以能在re-render之间保持,也是靠闭包保存Fiber节点的状态。

闭包的缺点?

  • 内存泄漏:闭包会阻止被引用的变量被垃圾回收,如果闭包长时间存在,会导致内存占用持续增长。
  • 调试困难:由于闭包中的变量不在当前作用域可见,调试时可能难以追踪变量来源,尤其在复杂潜逃中。

内存泄漏

内存泄漏是指程序分配的内存无法被回收,导致可用内存逐渐减少,最终可能引发性能问题或程序崩溃。

导致内存泄漏的几种方式

  1. 意外的全局变量,在函数里面忘记使用var/let/const 导致变量挂在到全局对象,或者函数内部使用this,但函数被当作普通函数调用,this指向全局对象。
  2. 定时器、事件监听器等 没有被清除。
  3. 脱离DOM的引用,比如将DOM元素存储在对象中。
  4. 未清理的websocket或者EventSource
  5. 持有大对象或数组的引用,切不需要时未释放。

如何避免内存泄漏

  1. 使用严格模式
  2. 及时清除定时器和事件监听器、Websocket、EventSource等连接
  3. 谨慎使用闭包,并且注意释放
  4. 平时还可以用工具检测比如chrome DevTools的Memory面板