闭包以及它的应用(扩展一下回收机制)

原创 peter庞 随笔 js心得 96阅读 2018-12-17 16:26:50 举报

什么是闭包?
闭包就是封闭与包裹的结构. 在 js 中很多东西具有包裹的结构, 即凡是括号形式的代码都有包裹的特性.

但是封闭特性只有函数具有, 即在函数内定义的变量, 外界无法访问. 所以函数可以构成闭包.

只有函数调用的时候, 系统会给函数分配内存, 那么这个属于函数的内存就是闭包.
看一下百度百科的解释:闭包就是能够读取其他函数内部变量的函数。例如在javascript中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数“。在本质上,闭包是将函数内部和函数外部连接起来的桥梁。

那么闭包到底是什么?
是说一块存储单元(对吧?)
是说一块特定的存储单元(对吧?)
是说访问这个特定的存储单元的一种方式(对吧?)


闭包怎么用?用来干什么?
这之前,我们说一下js中的垃圾回收机制:

1> 为什么需要垃圾回收

  • 物理内存是有限的, 如果一直创建就会 撑满内存, 使得程序运行崩溃
  • 我们的代码在不断使用内存的时候, 内存中的其他程序可能会出现问题
  • ...

2> 垃圾回收是怎么实现的, 以及回收的时候会有什么问题
在 js 引擎中, 都采用了一个被称之为引用计数器的算法
凡是在代码中创建一个对象, 那么在代码的底层( c++ ), 会给每一个对象利用一个引用计数的属性, 默认是 0
凡是在给对象赋值的时候, 就会给这个引用计数 +1
即:
o = new Object();
先创建对象, 同时引用计数初始化为 0
然后赋值, 即有一个变量指向了该对象, 将该对象的引用计数 记为 1

如果原本指向该对象的某一个变量, 重新指向了, 或赋值为 null, 则该对象失去一个引用
它的计数器就会 减一.
oo = o; // 计数器为 2
o = {}; // 原来的那个对象的计数器为 1
oo = null; // 原来的那个对象的计数器就为 0

js 引擎会记录下所有标记为 0 的对象. 同时每一个 js 引擎会有一个临界值.
只要内存消耗达到或超过了这个临界值, js 引擎就会将计数为 0 的对象销毁.
释放其占用的内存.


那么到底闭包怎么用呢?
所谓的闭包就是函数在运行的时候 生成的内存. 但是函数在运行结束后, 内存就会释放

因此我们要应用闭包, 首先得让他不释放.

如何让他不释放, 就是获得其内部数据的引用.

保存访问其使用能力的办法:

1> 返回一个可以访问其内部空间的函数

2> 返回一个对象, 对象具有访问内部数据的方法

-> 实现局部作用域
js 没有局部作用域, 所以定义的变量, 只要没有函数的约束, 就全局可访问
考虑实际开发的过程: 会引入很多的库, 所以多个库之间如果出现变量重名, 就会影响代码的运行.

-> 带有记忆的函数
所谓带有记忆的函数 是说函数在执行某些操作的时候 会缓存一部分数据, 待函数再次调用的时候

优先考虑缓存中存储的数据, 如果没有缓存数据, 则进行计算得到数据, 待数据得到后同时缓存该数据再返回数据.

函数在调用的时候可以得到计算的数据, 但是数据会在函数执行结束后 释放
我们可以让函数保留闭包, 那么将函数执行得到的结果存储到闭包中缓存
每次在使用的时候 先考虑闭包中是否含有数据, 然后如果没有数据则再计算.

fib 数列计算很慢的原因是 每次回重复计算很多的东西
所以我们需要缓存 第 n 个数 是 多少
所以我们的思想是 fib 函数在执行的时候, 先从缓存中取数据( 第 n 个数 )
如果这个数据不存在, 得到 undefined
如果存在就是数字, 那么 我们可以判断如果不存在 则递归计算
并将计算的结果 存到数组的 第 n 项
然后再返回, 那么这样是不是可以保证, 再次访问 第 n 个数字的时候, 就有缓存了

评论 ( 0 )
最新评论
暂无评论

赶紧努力消灭 0 回复