在讲闭包之前,我们先来复习一下函数
1.函数的声明
我们知道函数的声明有三种:
1. function f1() {console.log(1)}2. var f2 = function() {console.log(2)}3. var f3 = new Function('console.log(3)') //这一种由于很不直观,所以很少使用复制代码
2.函数的作用域
作用域:
就是这个变量存在的范围,出了这个范围,就没办法找到这个变量了。 如
function f1() { var a = 22;}console.log(a) //ReferenceError: a is not defined变量a的作用域在函数f1内部,所以在函数f1外部去读取这个变量是读取不到的复制代码
js作用域:
1. 全局作用域,在任何地方都可以读取2. 函数作用域,只在函数体内部可以读取3. 块级作用域复制代码
那么,函数本身也是一个值,他也是有作用域的。
划重点: 函数的作用域与变量一样,是函数声明时所在的作用域,跟函数在哪儿运行是没有关系的。
举个例子:
var a = 22;var f1 = function() { console.log(a)}function f2 () { var a = 33; f1();}f2() // 22复制代码
以上代码中,为什么打印出的是22而不是33呢? 因为函数在全局环境声明,作用域是全局,所以去取a的时候,在自己的作用域里面发现没有a,就往上找a,就找到了全局的a
再看个例子:
function f1() { var x = 22; function f2() { console.log(x) } return f2;}var x = 33;var f3 = f1();f3() // 22复制代码
以上代码中,变量x是在函数f1内部的,可是为什么我们在函数外部取到了他的值呢? 那就是因为 我们利用了f2函数。
f2函数是在f1内部声明的,他是可以取到f1内部的变量x的值的,因为我们的作用域链就是一层层往上,
我们将f2函数return 出去之后,再执行他,
他会记住自己的作用域,所以在执行f2函数的时候,他就可以将变量x的值打印出来了。
因此 我们就可以在外部读到这个变量的值了。
以上 函数 f2就是闭包。
闭包,其实就是 可以读取其他函数内部变量的函数。
只有函数内部的子函数才可以读取内部的变量,所以 也可以简单把闭包理解为,“定义在一个函数内部的函数”