美文网首页
闭包的基本概念

闭包的基本概念

作者: 麓语 | 来源:发表于2018-08-02 14:17 被阅读0次

上一篇:作⽤域链
下一篇:getter 与 setter

主要内容:

  • 闭包的基本概念
  • 闭包的基本形式
  • 闭包与内存

⼀般⼈认为闭包是⼀个神秘⽽⼜晦涩的内容. 实际上并⾮如此. 接下来详细说
明闭包的概念和闭包的⼀般的形式, 同时讨论闭包的有点和缺点.

闭包的基本概念

所谓的闭包, 简单说就是允许低级⼦链访问⾼级⼦链的数据的结构.

在 "作⽤域链" ⼀节中介绍过, ⾼级⼦链可以直接访问低级⼦链的数据, 但是反过来⽆法访问:

var num1 = 123;
function foo() {
  var num2 = 456;
  console.log("1 级⼦链允许访问 0 级⼦链 " + num1);
}
foo();
try {
  console.log(num2);
} catch (e) {
  console.log("0 级⼦链⽆法访问 1 级⼦链的数据");
}

但是如果允许访问这个数据, 那就构成闭包结构.

闭包的通俗含义

闭包, 从字⾯意义上来解释, 就是包裹起来的, 封闭起来的结构. 在 JavaScript 中, 函数就是⼀个封闭的结构. 在函数中定义的数据, 在外⾯是访问不到的.

(function () {
  var num = 123,
      obj = {},
      arr = [],
      isTrue = false,
      str = "abc",
      foo = function() {};
})();

在函数外⾯是绝对⽆法访问⾥⾯定义的数据的. 因此它就构成⼀个封闭的结构. 但是没有任何作⽤, 因此在 JavaScript 中需要将其对外开放⼀些接⼝, 以便使⽤这些数据. 这就是要求函数返回⼀个数据, 好么函数要么对象.

闭包的基本结构

要在函数外访问函数内的数据, 最简单的就是返回⼀个函数:

function foo() {
  var num = 123;
  return function() {
    return num;
  }
}

当函数返回⼀个函数的时候, 返回的函数允许返回⼀个数据. 那么在函数外就可以访问函数内的数据了. 但是仅仅是访问这个数据, 有时需要对其进⾏修改.因此既要求获得数据, 也要求可以修改数据. 因此就需要两个函数, 那可以返回⼀个对象:

function foo() {
  var num = 123;
  return {
    get_Num: function() {
      return num;
    },
    set_Num: function(value) {
      num = value;
    }
  }
}
var o = foo();
console.log(o.get_Num()); // => 123
o.set_Num(456);
console.log(o.get_Num()); // => 456
⼩结⼀下闭包的这个结构:
  • ⾸先有⼀个函数, 在函数中定义数据
  • 同时返回⼀个函数, 允许访问函数内部的数据
  • 调⽤函数, 返回允许访问内部数据的函数
  • 利⽤返回的函数, 允许在外界访问函数内定义的数据

闭包的基本案例

有了闭包, 可以做到事情就变得⾮常多了. 下⾯通过⼏个案例来说明闭包的使⽤

使⽤闭包模拟私有变量
// v3 使⽤⽅法, v5 可以直接使⽤ getter
var person = function(name, age, gender) {
  return {
    get name() {
      return name;
    },
    get age() {
      return age;
    },
    get gender() {
      return gender;
    }
  }
};
var obj = person("jk", 19, "male");
console.log(obj.name);
console.log(obj.age);
console.log(obj.gender);
使⽤闭包模拟块级作⽤域
var sum = 0;
(function () {
  for (var i = 0; i <= 100; i++) {
    sum += i;
  }
})();
console.log(sum);
使⽤闭包创建唯⼀标识符
var uniqueInteger = (function () {
  var count = 0;
  return function() {
    return count++;
  };
})();

闭包与内存

使⽤闭包可以⾮常⽅便的组织代码, 将不需要对外公开的代码都封装起来, 保护起来. 使得代码更加紧凑, 维护更加⽅便. 但是使⽤闭包, 保存了私有数据,容易造成内存的泄露.

为了更加⽅便的解释这个问题, ⾸先讨论⼀下 JavaScript 中内存的管理.

内存管理

JavaScript 具有垃圾收集的功能. 也就是说当执⾏环境会负责管理代码的执⾏过程使⽤的内存, 包括内存的分配与释放. 在传统的程序设计中, 例如 C, C++,需要⼿动的管理内存, 申请, 释放都需要⼿动的处理. 因此容易出现问题. 在JavaScript 中不需要这么⿇烦, 所有的事情都由 JavaScript 引擎去完成.

常⻅的内存管理⽅式有两种: 标记式, 引⽤计数式.

使⽤标记式内存管理, 运⾏时在内存中会标记所有的不再使⽤的数据, 进⽽加以回收. 如今⼤部分浏览器所采⽤的是标记式内存管理. 只是进⾏内存回收的时间不同⽽已.

使⽤引⽤计数式内存管理, 运⾏时会给每⼀个对象加上编号, 凡是有变量指向该对象, 引⽤计数就 +1 , 凡是减少⼀个引⽤, 计数就 -1. 那么当引⽤计数为 0的时候, 回收内存. 但是⼀旦出现循环引⽤, 就容易造成内存泄露.

JavaScript 中不需要⾃⼰考虑内存维护的问题, 所有的内存维护都可以由JavaScript 引擎去处理. 但是为了更好的提升性能, 建议在不使⽤数据的时候,将其设置为 null

上一篇:作⽤域链
下一篇:getter 与 setter

⼩结

  • 闭包的基本概念
  • 闭包的实现⽅式
  • 闭包案例

相关文章

  • Swift基础语法-闭包,闭包函数回调,尾随闭包,闭包捕获值,循

    本节知识点 闭包的基本概念 闭包基本使用 闭包表达式作为回调函数 闭包的多种写法(尾随闭包) 闭包表达式优化 闭包...

  • Python简明教程第14节:闭包和装饰器

    闭包 首先还是得从基本概念说起,什么是闭包? 维基百科:在计算机科学中,闭包(Closure)是词法闭包(Lexi...

  • swift学习之闭包

    基本概念 闭包类似于oc中的block,用于保存一段代码,在需要的时候执行闭包是引用类型 尾随闭包 闭包作为函数的...

  • Python | 什么是闭包,生成器Generator该如何掌握

    一、闭包Closure (扩展) 闭包的基本概念及应用技巧 简单说,闭包就是根据不同的配置信息得到不同的结果 再来...

  • golang-闭包

    最近学习golang的匿名函数 发现闭包还是有点意思 闭包基本概念:闭包是可以包含自由(未绑定到特定对象)变量的代...

  • 闭包的基本概念

    上一篇:作⽤域链下一篇:getter 与 setter 主要内容: 闭包的基本概念 闭包的基本形式 闭包与内存 ⼀...

  • javascript中的闭包

    闭包 基本概念 当 内部函数 被保存到 外部 时,将会一定生成闭包。闭包会导致原有作用域链不释放,造成内存泄露。...

  • swift语法--12-1闭包基本概念

    swift语法--12-1闭包基本概念 block和闭包区别 OC:block类似于匿名函数, 用于封装代码块, ...

  • javascript闭包的形成图解

    下面就来说说闭包的一些基本概念和具体的形成过程。 什么是闭包? 闭包就是既能重用一个变量,又可以保护变量不被污染的...

  • Go匿名函数

    GO语言的匿名函数就是闭包 基本概念 闭包是可以包含自由(未绑定到特定对象)变量的代码块,这些变量不在这个代码块内...

网友评论

      本文标题:闭包的基本概念

      本文链接:https://www.haomeiwen.com/subject/vqojvftx.html