闭包

闭包是作用域使用的特殊情况,
我们把函数执行形成私有上下文,来保护和保存私有变量机制称为闭包。
1、是一个函数,2、可以访问其他作用域中的变量;
有两种表现

  • 返回一个函数

    1. function create () {
    2. let a = 200;
    3. return function () {
    4. console.log(a); // 200
    5. }
    6. }
    7. let a = 100
    8. let fn = create();
    9. fn();
  • 作为参数被传递 ```javascript function create(fn) { let a = 100; fn(); }

let a = 200; function fn() { console.log(a); // 200,不是100 } create(fn)

  1. 可以看到,**(所有)自由变量的查找,是在函数定义的地方,向上级作用域查找,不是在执行的地方**
  2. <a name="OMg70"></a>
  3. ## 应用
  4. 1. 模仿块级作用域
  5. 2. 保护外部函数的变量 能够访问函数定义时所在的词法作用域(阻止其被回收)
  6. 3. 封装私有化变量
  7. 4. 创建模块
  8. <a name="cGCDh"></a>
  9. ### 隐藏数据
  10. ```javascript
  11. let createCache = function () {
  12. let data = {};
  13. return {
  14. get: function (key) {
  15. return data[key];
  16. },
  17. set: function (key, value) {
  18. data[key] = value;
  19. return data;
  20. }
  21. }
  22. }
  23. let cache = createCache();
  24. cache.set('token', 'token');
  25. cache.get('token');

节流和防抖的使用

  • 节流

以一个固定的间隔去触发,用于稀疏函数的执行频率

  1. // 节流
  2. let throttle = function (fn, delay) {
  3. let prev = 0;
  4. return function () {
  5. let self = this;
  6. let argus = arguments;
  7. let now = Date.now();
  8. if (now - prev > delay) {
  9. fn.apply(self, argus);
  10. prev = now;
  11. }
  12. }
  13. }
  • 防抖

频繁触发,只执行最后一次

  1. // 防抖
  2. let debounce = function (fn, delay) {
  3. let timeout = null;
  4. return function () {
  5. let self = this;
  6. let argus = arguments;
  7. if (timeout) clearTimeout(timeout);
  8. timeout = setTimeout(function () {
  9. fn.apply(self, argus);
  10. }, delay);
  11. }
  12. }

实现bind函数

  1. // 模拟bind的实现
  2. Function.prototype.bind1 = function () {
  3. // 将参数拆解为数组
  4. const args = Array.prototype.slice.call(arguments);
  5. // 获取this,并从数组剔除
  6. const _this = args.shift();
  7. // 原来的fn,fn.bind(...)的fn1
  8. const self = this;
  9. // 返回一个函数
  10. return function () {
  11. return self.apply(_this, args);
  12. }
  13. };
  14. function fn () {
  15. console.log(this);
  16. console.log(arguments);
  17. return 'this is a fn';
  18. }
  19. let fn1 = fn.bind1({
  20. name: 'fn',
  21. }, 10, 20);
  22. fn1();

缺点

变量会常驻内存,可能造成内存泄露
因为内存得不到及时的释放,可以人为的去置为null

js垃圾回收机制

  • �标记使用法

当这个函数结束,变量不再使用就得到了释放;

  • 引用计数法

在一定时间内不再使用;