两分钟搞懂面试常问的闭包

1,955 阅读1分钟

前言

闭包经常在面试中被问到,但是有的同学总是回答的不好,阅读本文让你的回答得满分。

闭包

闭包可以理解为可以访问另一个函数的作用域的变量的函数。

在本质上闭包是连接外部函数和内部函数的桥梁。

闭包的示例

示例一

var Counter = (function () {
  var privateCounter = 0

  return {
    increment: function () {
      privateCounter += 1
    },
    decrement: function () {
      privateCounter += -1
    },
    value: function () {
      return privateCounter
    }
  }
})()

console.log(Counter.value()) // 0
Counter.increment()
Counter.increment()
console.log(Counter.value()) // 2
Counter.decrement()
console.log(Counter.value()) // 1

示例一中的闭包有Counter.value、Counter.increment、Counter.decrement。

示例二

let liDomList = document.querySelectorAll('li')
for (var i = 0; i < liDomList.length; i++) {
  (function (i) {
    liDomList[i].onclick = function () {
      console.log(i)
    }
  })(i)
}

示例二中的闭包有liDomList[i].onclick

闭包的作用

示例二中,内部函数a(liDomList[i].onclick),外部函数b((function (i) {})

外部函数b执行完后,闭包使得Javascript的垃圾回收机制不会收回a所占用的资源, 因为b的执行需要依赖a中的变量i。

延长变量生命周期

示例二中i的生命周期延长了,使得执行a的时候,依然可以获取到变量i。

模拟私有变量

示例一中,privateCounter变量就是一个私有变量,在其他函数中不能直接使用。

闭包的使用

闭包实现只读,只写,可读可写

var property = (function (opts) {
  var property = '闭包'
  var hasSet = opts.hasSet || false
  var hasGet = opts.hasGet || false
  var res = {}
  if (hasGet) {
    res.get = function () {
      return property
    }
  }
  if (hasSet) {
    res.set = function (v) {
      property = v
    }
  }
  return res
})({hasSet: true, hasGet: true})

console.log(property.get())
property.set('闭包DEMO')
console.log(property.get())

谢谢阅读!