Js中闭包的几种写法

1.定义

闭包就是能够读取其他函数内部变量的函数。例如在javascript中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数“。在本质上,闭包是将函数内部和函数外部连接起来的桥梁。

2.实例

实例1

function init () {
  let name = 'gaodda' // name 是一个被 init 创建的局部变量
  function showName () { // showName() 是内部函数,一个闭包
    alert(name) // 使用了父函数中声明的变量
  }
  showName()
}
init()
/**
* init() 创建了一个局部变量 name 和一个名为 showName () 的函数。
* showName () 是定义在 init() 里的内部函数,仅在该函数体内可被获取。
* 请注意,showName () 内没有自己的局部变量,然而它可以访问到外部函数的变量,
* 所以 showName () 可以使用父函数 init() 中声明的变量 name 。
*/

实例2

function makeAdder (x) {
  return function (y) {
    return x + y
  }
}
var add5 = makeAdder(5)
var add10 = makeAdder(10)

console.log(add5(2)) // 7
console.log(add10(2)) // 12
/**
* 定义了 makeAdder(x) 函数,它接受一个参数 x ,并返回一个新的函数。返回的函数接受一个参数 y,并返回x+y的值。
* 从本质上讲,makeAdder 是一个函数工厂 — 他创建了将指定的值和它的参数相加求和的函数。
* 在上面的示例中,我们使用函数工厂创建了两个新函数 — 一个将其参数和 5 求和,另一个和 10 求和。
* add5 和 add10 都是闭包。它们共享相同的函数定义,但是保存了不同的词法环境。
* 在 add5 的环境中,x 为 5。而在 add10 中,x 则为 10。
*/

用闭包模拟私有方法

var Counter = (function() {
 var privateCounter = 0
 function changeBy(val) {
   privateCounter += val
 }
 return {
   increment: function() {
     changeBy(1)
   },
   decrement: function() {
     changeBy(-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.increment,Counter.decrement 和 Counter.value。
* 共享环境创建于一个立即执行的匿名函数体内。这个环境中包含两个私有项:名为 privateCounter 的变量和名为 changeBy 的函数。
* 这两项都无法在这个匿名函数外部直接访问。必须通过匿名函数返回的三个公共函数访问。
*
*/

/**
* 创建多个计数器
*/
var makeCounter = function() {
  var privateCounter = 0
  function changeBy(val) {
    privateCounter += val
  }
  return {
    increment: function() {
      changeBy(1)
    },
    decrement: function() {
      changeBy(-1)
    },
    value: function() {
      return privateCounter
    }
  }  
}
var Counter1 = makeCounter()
var Counter2 = makeCounter()
console.log(Counter1.value()) /* logs 0 */
Counter1.increment()
Counter1.increment()
console.log(Counter1.value()) /* logs 2 */
Counter1.decrement()
console.log(Counter1.value()) /* logs 1 */
console.log(Counter2.value()) /* logs 0 */
/**
* 每次调用其中一个计数器时,通过改变这个变量的值,会改变这个闭包的词法环境
* 然而在一个闭包内对变量的修改,不会影响到另外一个闭包中的变量。
*/

在循环中创建闭包:一个常见错误

/** 不能正常输出想要结果 */
for (var i = 0; i < 5; ++i) {
 setTimeout(function () {
   console.log(i + ' ')
  }, 100);
}
/** 正常输出想要结果 */
for (var i = 0; i < 5; ++i) {
  (function (i) {
	setTimeout(function () {
	  console.log(i + ' ')
	}, 100)
  }(i))
}
发布了22 篇原创文章 · 获赞 2 · 访问量 2866

猜你喜欢

转载自blog.csdn.net/gaodda/article/details/103145599