本书未发布

闭包 (closure)

未匹配的标注

简介

  • 闭包可以理解为一个对象,是保存在内部函数中的,在这个函数中引用了外部函数的变量
  • 当内部函数引用了外部函数的变量(或函数)时,就产生了闭包 (外部函数需要执行才可以,内部函数可以不执行)
  • 产生了几个闭包,就看调用了几次外部函数

闭包的作用

  1. 使函数内部的变量在函数执行完成后,仍然存活在内存中(延长了局部变量的生命周期),正常情况下函数执行完成后,函数内部声明的局部变量就消失了,闭包除外
  2. 让函数外部可以操作(读写)到函数内部的数据(变量或函数),正常情况下是不能操作的,闭包除外
    • 即在函数内部再返回一个函数
function fn1() {
  var num = 10
  function fn2() {
    num++
    console.log(num)
  }

  return fn2
}

var f = fn1()
f()
  1. 可以使用闭包来定义 js 模块
    • 将所有的数据和功能都封装在一个函数内部(私有的)
    • 只向外暴露一个包含 n 个方法的对象或函数
    • 模块的使用者,只需要通过模块暴露的对象来调用方法即可
    • index.js
(function() {
  var msg = 'xiaoming'

  function doSomething() {
    console.log('doSomething', msg.toUpperCase())
  }

  function doOtherSomething() {
    console.log('doOtherSomething', msg.toLowerCase())
  }

  window.myModule = {
    doSomething: doSomething,
    doOtherSomething: doOtherSomething
  }

})()
  • 使用上面的模块
<script src='index.js'></script>

<script>
  myModule.doSomething()
  myModule.doOtherSomething()
</script>

闭包的缺点

  • 函数执行完成后,函数内部的局部变量没有释放,占用内存的时间会变长,容易造成内存泄露
  • 解决办法:能不用就不用或者及时释放

内存溢出

  • 当程序运行需要的内存超过了剩余的内存时,就会出现内存溢出的错误
  • 是一种错误,程序不能正常运行

内存泄露

  • 占用的内存没有及时释放进而就造成了内存泄露,程序仍然可以正常运行

  • 内存泄露积累多了就容易导致内存溢出

  • 常见的内存泄露:

  • 意外的全局变量

  • 没有及时清理的计时器或回调函数

  • 闭包

面试题

1.

<button>1</button>
<button>2</button>

<script>
  var btns = document.getElementsByTagName('button')
  // 此时不要这样写:i < btns.length,因为这样写的话,会导致
  // 每循环一次,就计算一次 btns.length 的值
  // 因此可以将 btns.length 的值先提取出来,然后再计算
  var len = btns.length
  for (var i = 0; i < len; i++) {
    console.log(btns[i])
  }
</script>

2.

function fn1() {
  var a = 2
  function fn2() {
    a++
    console.log(a)
  }

  return fn2
}

var f = fn1()
f() // 3
f() // 4

3.

var name = 'window'

var object = {
  name: 'my object',
  getNameFunc: function() {
    return function() {
      return this.name
    }
  }
}

// object.getNameFunc() 是拿到了函数,后面再加上括号,表示直接执行了该函数
console.log(object.getNameFunc()()) // window

// --------------------------------
var name2 = 'window'

var object2 = {
  name2: 'my object2',
  getNameFunc2: function() {
    var that = this
    return function() {
      return that.name2
    }
  }
}

console.log(object2.getNameFunc2()()) // my object2

4.

function fun(n, o) {
  console.log(o)
  return {
    fun: function(m) {
      return fun(m ,n)
    }
  }
}

var a = fun(0) // undefined
a.fun(1) // 0
a.fun(2) // 0
a.fun(3) // 0

var b = fun(0).fun(1).fun(2).fun(3) // undefined 0 1 2

var c = fun(0).fun(1) // undefined 0
c.fun(2) // 1
c.fun(3) // 1

本文章首发在 LearnKu.com 网站上。

上一篇 下一篇
讨论数量: 0
发起讨论 只看当前版本


暂无话题~