前端面试押题
  • HTML
    • 有哪些新标签?
    • SVG 的区别是什么?
    • 如何理解 HTML 中的语义化标签
  • CSS
    • 如何清除浮动?
    • CSS 选择器优先级如何确定?
    • BFC 是什么
    • 两种盒模型(box-sizing)的区别?
    • 如何实现垂直居中?
  • JavaScript 押题基础篇
    • new 做了什么?
    • JS 如何实现类?
    • JS 的闭包是什么?怎么用?
    • JS 如何实现继承?
    • JS 的立即执行函数是什么?
    • JS 的数据类型有哪些?
    • 原型链是什么?
    • 这段代码中的 this 是多少?
  • JavaScript 押题手写篇
    • 手写数组去重
    • 手写简化版 Promise
    • 手写 AJAX
    • 手写深拷贝
    • 手写节流 throttle、防抖 debounce
    • 手写发布订阅
    • 手写 Promise.all
  • DOM 押题
    • 请简述 DOM 事件模型
    • 手写可拖曳 div
    • 手写事件委托
  • HTTP 押题
    • 说说同源策略和跨域
    • POST 的区别有哪些?
    • TCP 三次握手和四次挥手是什么?
    • Session、Cookie、LocalStorage、SessionStorage 的区别
    • HTTP 缓存有哪些方案?
    • HTTPS 的区别有哪些?
    • HTTP/2 的区别有哪些?
  • React 押题
    • 什么是高阶组件 HOC?
    • React Hooks 如何模拟组件生命周期?
    • 你如何理解 Redux?
    • React 有哪些生命周期钩子函数?数据请求放在哪个钩子里?
    • React 如何实现组件间通信
    • 虚拟 DOM 的原理是什么?
    • Vue DOM diff 的区别?
    • DOM diff 算法是怎样的?
  • Node.js 押题
    • 浏览器里的微任务和任务是什么?
    • EventLoop 是什么?
    • koa.js 的区别是什么?
  • TypeScript 押题
    • JS 的区别是什么?有什么优势?
    • any、unknown、never 的区别是什么?
    • TS 工具类型 Partial、Required、Readonly、Exclude、Extract、Omit、ReturnType 的作用和实现?
    • interface 的区别是什么?
Powered by GitBook
On this page
  1. JavaScript 押题基础篇

JS 的闭包是什么?怎么用?

概念题,「是什么、怎么做、解决了什么问题、优点是、缺点是、怎么解决缺点」

是什么

闭包是 JS 的一种语法特性。

闭包 = 函数 + 自由变量

对于一个函数来说,变量分为:全局变量、本地变量、自由变量

怎么做

  let count
  function add (){ // 访问了外部变量的函数
    count += 1
  }

把上面代码放在「非全局环境」里,就是闭包。

注意,闭包不是 count,闭包也不是 add,闭包是 count + add 组成的整体。

怎么制造一个「非全局环境」呢?答案是立即执行函数:

const x = function (){
	var count
	function add (){ // 访问了外部变量的函数
	  count += 1
	}
}()

但是这个代码什么用也没有,所以我们需要 return add ,即:

const add2 = function (){
	var count
	return function add (){ // 访问了外部变量的函数
	  count += 1
	}
}()

此时 add2 其实就是 add,我们可以调用 add2

add2()
// 相当于
add()
// 相当于
count += 1

至此,我们就实现了一个完整的「闭包的应用」。

注意:闭包 ≠ 闭包的应用,但面试官问你「闭包」的时候,你一定要答「闭包的应用」,这是规矩。

解决了什么问题:

  1. 避免污染全局环境。(因为用的是局部变量)

  2. 提供对局部变量的间接访问。(因为只能 count += 1 不能 count -= 1)

  3. 维持变量,使其不被垃圾回收。

优点:

简单,好用。

缺点:

闭包使用不当可能造成内存泄露。

注意,重点是「使用不当」,不是闭包。

「闭包造成内存泄露」这句话以讹传讹很多年了,曾经旧版本 IE 的 bug 导致的问题,居然被传成这样了。

举例说明:

function test() {
  var x = {name: 'x'};
  var y = {name: 'y', content: "-----这里很长,有一万三千五百个字符那么长----" }
  return function fn() {
    return x;
  };
}

const myFn = test() // myFn 就是 fn 了
const myX = myFn() // myX 就是 x 了
// 请问,y 会消失吗?

对于一个正常的浏览器来说,y 会在一段时间后自动消失(被垃圾回收器给回收掉)。

但旧版本的 IE 并不是正常的浏览器,所以是 IE 的问题。

当然,你可以说

君子不立于危墙之下,我们应该尽量少用闭包,因为有些浏览器对闭包的支持不够好

但你不可以说「闭包造成内存泄露」。对吗?

怎么解决缺点:

慎用,少用,不用。(我偏要用)

建议熟读这篇文章:

PreviousJS 如何实现类?NextJS 如何实现继承?

Last updated 3 years ago