一文搞定JS的闭包

67 阅读1分钟

闭包问题

循环中赋值为引用的问题

for (var i = 1; i < 5; i++) {
  setTimeout(function timer() {
    console.log(i)
  }, i * 1000)
}

解决方法有 3 种

第一种,使用立即执行函数方式

for (var i = 1; i < 5; i++) {
  (fuction(j){
    setTimeout(function timer() {
      console.log(j)
    }, j * 1000)
  })(i)
}

第二种,使用 ES6 的let

for (let i = 1; i < 5; i++) {
  setTimeout(function timer() {
    console.log(i)
  }, i * 1000)
}

第三种,使用setTimeout的第三个参数

for (var i = 1; i < 5; i++) {
  setTimeout(
    function timer(j) {
      console.log(j)
    },
    i * 1000,
    i,
  )
}

计数器

实现一个 foo 函数 可以这么使用:

a = foo()
b = foo()
c = foo()
// a === 1;b === 2;c === 3;
foo.clear()
d = foo() //d === 1;
function myIndex() {
  var index = 1

  function foo() {
    return index++
  }

  foo.clear = function () {
    index = 1
  }
  return foo
}

var foo = myIndex()

ES6 作用域

var x = 1
// 函数走默认值 函数内部执行默认是严格模式
function foo(
  x,
  y = function () {
    x = 2
  },
) {
  var x = 3
  y() // 由于函数内部存在闭包,这里的x是指的是函数foo的参数x,而不是局部变量x。
  console.log(x)
}
foo()
console.log(x)

闭包的链式调用问题

function fun(n, o) {
  console.log(o)
  return {
    fun: function (m) {
      return fun(m, n)
    },
  }
}
// 每次都是固定的对象a 意思是同一个闭包
// n = 0  o = undefined  undefined
// var a = fun(0);  a.fun(1);  a.fun(2);  a.fun(3);//undefined,0,0,0

// n = 0  o = undefined  undefineds
// var a = {        // a.fun里面存了n和o的闭包
//   fun:function(m){
//     return fun(m,n);
//   }
// }
// m = 1  n = 0          0   a.fun(1); 每次都会返回一个新的对象 形成新的闭包 通过旧的闭包的值给函数实参 传递给新的闭包的形式参数(就好像闭包接力)
// m = 2  n = 1          1
// m = 3  n = 2          2
var b = fun(0).fun(1).fun(2).fun(3) //undefined,?,?,?

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