闭包函数

闭包函数有3个特点:

  1. 函数嵌套函数
  2. 函数内部可以引用外部的参数和变量
  3. 参数和变量不会被垃圾回收机制回收

优点:可以避免全局变量的污染。

缺点:闭包会常驻内存,会增大内存使用量,使用不当很容易造成内存泄露。

定义:当一个函数A的返回值是另一个函数B,而返回的那个函数B如果调用了父函数A的内部变量,如果返回的这个函数B再外部被执行,就产生了闭包。(有权访问 另一个 函数 作用域中变量的函数。)

表现形式:使函数外部能够调用函数内部的定义的变量。(涉及到了作用域

例1:根据作用域链的规则来看,底层作用域没有声明的变量,会向上一级查找,如果找到就返回,如果没有的话就会一直找到window的变量,没有的话就会返回undefined。所以例子1中B函数中没有声明变量name,很明显返回的是函数A中的name变量。

// 例1
function A() {
  let name = 'hello'
  function B() {
    console.log(name)
  }
  B()
}
A() // hello

在看例2前先看MDN中的代码

function makeFunc() {
    var name = "Mozilla";
    function displayName() {
        alert(name);
    }
    return displayName;
}

var myFunc = makeFunc();
myFunc();

MDN中解释说:

原因在于,JavaScript中的函数会形成了闭包。 闭包是由函数以及声明该函数的词法环境组合而成的。该环境包含了这个闭包创建时作用域内的任何局部变量。在本例子中,myFunc 是执行 makeFunc 时创建的 displayName 函数实例的引用。displayName 的实例维持了一个对它的词法环境(变量 name 存在于其中)的引用。因此,当 myFunc 被调用时,变量 name 仍然可用,其值 Mozilla 就被传递到alert中。

例2:与例1不同的是,此时调用的函数B只是内部函数的方法, 所以我们定义一个变量name调用闭包函数对象调用后,将B函数赋值给C变量;然后使用C()方式进行调用。

个人理解:通俗易懂的讲就是函数B只是一个方法,执行到var myFunc = makeFunc();这一段代码发生的是将函数A执行后赋值给C变量,函数A正常执行到return之前,B函数中就已经查找并保存了name这个变量,函数A执行到return后便得到了函数B方法,但是还没有调用,所以赋值给变量C,C就引用了这个方法(上文下划线中提到函数实例的引用)但是需要C()调用这个方法。(!!!若有不妥的地方还望请教技术大佬留言纠正!!!)

// 例2
function A() {
  let name = 'hello'
  function B() {
    console.log(name)
  }
  return B
}
const C = A()
C() // hello

// 可以执行一下下面这段代码
function makeFunc() {
    var name = "Mozilla";
    console.log(name, '1');
    function displayName() {
        console.log(name,'2');
    }
    console.log(name,'3');
    console.log(displayName,'4')
    return displayName;
    
}

var myFunc = makeFunc();
console.log(myFunc)
myFunc();

// Mozilla 1
// Mozilla 3
// ƒ displayName() {
//    console.log(name,'2');
// } '4'
// ƒ displayName() {
//    console.log(name,'2');
// }
// Mozilla 2

例3:当我们调用闭包hello对象时,一个传入1 一个传入2 将返回的函数对象分别给变量a b,也就是说 a b 都是闭包 他们共享相同的函数定义,但是保存在了不同的环境中。

function hello(x) {
  return function fun(y) {
    console.log(x + y)
  }
}
var a = hello(1) // 返回函数对象
var b = hello(2) // 返回函数对象
console.log(a(2)) // 3
console.log(b(3)) // 5
posted @ 2022-02-25 16:48  AvenCheung  阅读(29)  评论(0编辑  收藏  举报