闭包的基本概念

上一篇:作⽤域链
下一篇: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

⼩结

  • 闭包的基本概念
  • 闭包的实现⽅式
  • 闭包案例
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,869评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,716评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,223评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,047评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,089评论 6 395
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,839评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,516评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,410评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,920评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,052评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,179评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,868评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,522评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,070评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,186评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,487评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,162评论 2 356

推荐阅读更多精彩内容