闭包及其作用

(一) 闭包是什么, 闭包形成的原因(背诵)

闭包的概念:闭包是指有权访问另一个函数作用域中的变量的函数,创建闭包最常用的方式就是在一个函数内部创建另一个函数(函数中的函数)。
简单概括: 闭包就是一个能访问另外一个函数内部变量的函数
闭包形成的原因:函数内部的局部变量一般在函数运行结束的时候就会被销毁, 但如果局部变量因为被外部引用而导致没有被销毁, 就形成了闭包
闭包的特性:
闭包可以让我们在函数外部访问函数内部的变量

  1. <script>
  2. function test() {
  3. var color = 'red';
  4. // demo函数是个闭包
  5. function demo() {
  6. console.log(color);
  7. }
  8. return demo;
  9. }
  10. // 调用test得到一个函数,使用变量fn存储起来
  11. var fn = test();
  12. // 调用fn函数
  13. fn(); // 调用结果:打印"red"
  14. test()();
  15. </script>

(二) 闭包有哪些作用(背诵)

或问: 闭包有哪些应用场景

  1. 封装私有变量(私有属性)
  2. 模仿块级作用域(ES5中没有块级作用域)
  3. 实现JS的模块

1.封装私有变量(私有属性)

私有变量(私有属性)是后台语言经常用的东西, 意思是这个属性是私有的,不能随意更改,要改,必须通过指定的set和get方法进行获取和修改

  1. <script>
  2. function getCatName() {
  3. var _catName = '小花';
  4. // 获取_catName
  5. function get() {
  6. return _catName;
  7. }
  8. // 修改_catName,需要传入新名字
  9. function set(newName) {
  10. _catName = newName
  11. }
  12. return {
  13. get:get,
  14. set:set
  15. }
  16. }
  17. // 调用getCatName(),得到一个对象, 对象包含了get方法和set方法
  18. var obj = getCatName();
  19. // 调用get方法获取catName
  20. var catName = obj.get();
  21. console.log('catName',catName);
  22. // 调用set方法来修改catName
  23. obj.set('小黑');
  24. var catName = obj.get();
  25. console.log('catName',catName);
  26. </script>

2.模仿块级作用域(ES5中没有块级作用域)

  1. js没有块级作用域
  2. 函数自调用
  1. // 1.js没有块级作用域
  2. <script>
  3. {
  4. var a = 2;
  5. }
  6. console.log(a);
  7. for(var i=0;i<5;i++) {
  8. }
  9. console.log(i);
  10. </script>
  11. // 2.函数自调用
  12. <script>
  13. (function() {
  14. console.log('我跟自己玩');
  15. })();
  16. </script>
  17. // 3.说出以下代码运行的结果
  18. <script>
  19. for(var i=0;i<5;i++) {
  20. setTimeout(function(){
  21. console.log(i); // 打印5个5
  22. },i*1000);
  23. }
  24. </script>
  25. // 4.使用闭包模拟块级作用
  26. // 因为使用了闭包,循环了五次,就产生了五个闭包,每个闭包都有独立的内部变量j,j的值是0,1,2,3,4
  27. <script>
  28. for (var i = 0; i < 5; i++) {
  29. (function (j) {
  30. setTimeout(function () {
  31. console.log(j);
  32. }, j * 1000);
  33. })(i);
  34. }
  35. </script>
  36. // es6的let声明的变量是存在块级作用域
  37. <script>
  38. for (let i = 0; i < 5; i++) {
  39. setTimeout(function () {
  40. console.log(j);
  41. }, j * 1000);
  42. }

3.实现JS的模块(js库)

  1. (function () {
  2. function get() {
  3. var xhr = new XMLHttpRequest();
  4. // xhr.opon('');
  5. // ......
  6. console.log('这是get方法');
  7. }
  8. function post() {
  9. var xhr = new XMLHttpRequest();
  10. // xhr.opon('');
  11. // ......
  12. console.log('这是post方法');
  13. }
  14. var axios = {
  15. get: get,
  16. post: post
  17. }
  18. window.axios = axios;
  19. })();

使用闭包的注意点
由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题
若有收获,就点个赞吧