首先来说一下
什么是闭包:在JavaScript中,如果一个函数能够访问到它外部作用域的变量,就形成了这样一种特殊的结构,我们称之为闭包。
闭包的作用有:从外部读取函数内部的变量、将创建的变量的值始终保持在内存中、封装对象的私有属性和私有方法
将创建的变量的值始终保持在内存中:
例子看一下
function outer() { let count = 0; // count是一个外部变量,对于inner这是一个自由变量。 function inner() { count++; console.log(count); } return inner; } const counter = outer(); counter(); // 输出: 1 counter(); // 输出: 2
在这个例子中,outer函数返回了inner函数,而inner函数使用了outer函数的count变量,形成了一个闭包。
上面,函数 outer() 创建了一个变量 count 并定义了一个新的函数。这个新的函数可以增加 count 的值并打印。最后,函数 outer() 返回这个新的函数。
当你调用 outer(),这个新的函数就被创建并返回,但这并不直接执行这个返回的函数,所以你并没有看到 count 值的改变或任何内容被打印到控制台。
要看到这个新函数执行的效果,你需要另外再调用这个返回的函数。所以
let myNewFunction = outer(); // 'outer' 返回一个新的函数,我们将其保存到 'myNewFunction' myNewFunction(); // 现在,我们调用 'myNewFunction' ,它会增加 'count' 并打印 myNewFunction(); // 再次调用 'myNewFunction' ,它会再次增加 'count' 并打印
现在,每次当你调用 myNewFunction(),它就会执行 outer() 返回的那个新函数,增加 count 并打印。
这就是所谓的 "闭包" —— outer() 返回的那个新函数被称为闭包,因为它 “闭合”了对 count 的访问。也就是说,即使 outer() 已经执行完毕,这个新函数仍然可以访问和修改 outer() 中的 count 变量。这就是为什么调用 myNewFunction() 可以不断增加 count 的值。
这样说是不是一下子就开朗了。
封装对象的私有属性和私有方法:
function createPerson(name) { let _name = name; return { setName: function(name) { _name = name; }, getName: function() { return _name; } }; } let person = createPerson('mimiwuqi'); console.log(person.getName()); // mimiwuqi person.setName('com'); console.log(person.getName()); // com
在这个例子中,_name是createPerson函数的一个本地变量,对于getName和setName函数来说是一个自由变量,因此形成了一个闭包。由于从外部无法访问_name,所以_name就像是一个私有属性。同样,getName和setName就像是一个公共接口,实现了对私有属性的操作,但不能够直接操作,这就是封装。
自己运行试一下吧