闭包学习总结

本文深入探讨JavaScript中的闭包概念,包括闭包是如何形成的、闭包的观察与理解、闭包的作用及其实例应用等。此外,还介绍了如何利用闭包实现公共函数并访问私有变量,从而达到模块化编程的目的。

Closure 闭包学习总结

什么是闭包

JavaScript中的函数会形成闭包。 闭包是由函数以及创建该函数的词法环境组合而成。这个环境包含了这个闭包创建时所能访问的所有局部变量。 在一些编程语言中,函数中的局部变量仅在函数的执行期间可用,然而在javascript当中,若函数返回内层某个函数,无论该内层函数是否需要访问外层变量,返回函数都能正常执行,可见javascript自有其机制。

观察闭包

个人观察总结,闭包即闭包域(Closure Scope),是存放内层函数所需变量的引用的集合。

考虑以下代码。

var Soldier = function (ak) {
  var ammo = '.762';
  var Grenades = 0;
  this.name = "John";
  this.getName = function () {
      console.log(this.name + '\'s');
  }
  this.getWeapon = function () {
      console.log(ak);
      function fire() {
          let round = "30 ";
          this.noAmmon = function () {
              console.log('needs ' + round + ammo + ' ammo');
          }
      }
      var shot = new fire();
      shot.noAmmon();
      console.log(shot);
  }
}
var p = new Soldier('ak');
p.getName();
p.getWeapon();
console.dir(p);
复制代码

上图可知。

1.Closure(Soldier)中没有this.name。虽然getName访问了this.name却没有出现在Closure(Soldire)中,可见闭包的作用是为了存放变量的引用,对象内部变量引用没有必要存在闭包中。
2.无论Soldier的getName,getWeapon还是fire的noAmmon它们的都有Closure(Soldire) 但是getName却没有访问过任何外部变量(甚至为空函数)。由此可推断函数会自动引用闭包。
3.Grenades不存在于Closure(Soldier)当中。内部函数都没有访问的变量不会加到闭包中。
4.如果把所有外部变量的访问全部注释,将不会存在任何闭包。不存在空闭包。
5.noAmmon有两个闭包Closure(fire)和Closure(Soldier)且Closure(fire)比Closure(Soldier)排序低。可见外层函数闭包可共内层使用,反之不可,且函数由内向层闭包向外曾闭包依次查找变量直到Golbol,如果没有则会报错。

由以上几点总结:闭包是一个引用的集合,存放内层函数所需变量的引用,闭包也实现了作用域的控制,函数如何自内而外的查找变量。

闭包的作用举例

使用闭包来定义公共函数,并令其可以访问私有函数和变量。这个方式也称为 模块模式(module pattern)

var Soldier = (function () {
    var ammo = 30;
    var reload = function () {
        ammo = 30;
    }
    var fire = function (round) {
        ammo -= round;
    }
    var check = function () {
        console.log(ammo);
    }
    return {
        reload: reload,
        fire: fire,
        check: check
    }
})();
Soldier.check(); //output:30
Soldier.fire(15);
Soldier.check(); //output:15
Soldier.reload();
Soldier.check(); //output:30
复制代码

每个闭包都有它自己的词法环境,上例环境在一个立即执行的匿名函数内。该环境包含私有变量ammo且它无法从函数外部直接访问。必须通过该匿名函数返回的三个公共函数访问。 也正是因为环境被内层函数所共享,所以上例中的Soldier.reload,Soldier.fire,Soldier.check才可以访问且共享私有变量ammo。

var makeSoldier = function(){
    var Soldier = (function () {
    var ammo = 30;
    var reload = function () {
        ammo = 30;
    }
    var fire = function (round) {
        ammo -= round;
    }
    var check = function () {
        console.log(ammo);
    }
    return {
        reload: reload,
        fire: fire,
        check: check
    }
})();
return Soldier;
}
var s1 = makeSoldier();
var s2 = makeSoldier();
s1.fire(10);
s1.check();//output:20
s2.check();//output:30
复制代码

观察s1,s2的output可知,它们各自的ammo是独立性的。每个闭包只引用自己词法作用域内的变量,在一个闭包内对变量的修改,不会影响到另外一个闭包中的变量。

优点:以这种方式使用闭包,提供了许多与面向对象编程相关的好处 —— 特别是数据隐藏和封装。

缺点:消耗更多的内存,影响处理速度。例如,在创建新的对象或者类时,方法通常应该关联于对象的原型,而不是定义到对象的构造器中。原因是这将导致每次构造器被调用时,方法都会被重新赋值一次。

参考
闭包 - JavaScript | MDN

转载于:https://juejin.im/post/5aa530616fb9a028c8127c8f

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值