闭包

我一直以为 闭包和原型链的学习是个抽丝剥茧的过程,这个过程痛苦且漫长 是真的不容易一下子理解的。

今天读了《你不知道的javaScript》 ,我觉得闭包讲的挺好的,还是总结一下吧。 变成自己的技能树一部分;

作者的话 :

对于那些有一点 JavaScript 使用经验但从未真正理解闭包概念的人来说,理解闭包可以看作是某种意义上的重生,但是需要付出非常多的努力和牺牲才能理解这个概念。

闭包就好像从 JavaScript 中分离出来的一个充满神秘色彩的未开化世界,只有最勇敢的人 才能够到达那里。但实际上它只是一个标准,显然就是关于如何在函数作为值按需传递的 词法环境中书写代码的。

闭包是基于词法作用域书写代码时所产生的自然结果,你甚至不需要为了利用它们而有意 识地创建闭包。闭包的创建和使用在你的代码中随处可见。你缺少的是根据你自己的意愿 来识别、拥抱和影响闭包的思维环境。

最后你恍然大悟:原来在我的代码中已经到处都是闭包了,现在我终于能理解它们了。理 解闭包就好像 Neo3 第一次见到矩阵 一样。

我们经常听人说闭包的强大 ,能实现这个看似一些不可能完成的任务; 优雅且高贵 。 

这里 ,定义一下 广义上的闭包: 如果曾经形成了自己小天地(专属作用域)的 都算是闭包;

                          技术意义上的闭包: 在广义的基础上,能够把专属作用域的变量拿出来为我所用的,体现出强大的一面。 

作者是这么定义的:当函数可以记住并访问所在的词法作用域时,就产生了闭包,即使函数是在当前词法作用 域之外执行。

还举了俩个小栗子,来说明

 demo1 : 

function foo() { var a = 2;
function bar() { console.log( a ); // 2
}
bar(); }
foo();

demo2: 

function foo() { var a = 2;
function bar() { console.log( a );
}
return bar; }
var baz = foo();
baz(); // 2 —— 朋友,这就是闭包的效果。

demo1 是闭包吗? 曾经是吧。一调用那一瞬间是个闭包。之后就没有了。 

demo2  这就是一个标准的闭包, 闭包了,并且体现出了效果。且 一般说的的闭包 更多的应该是值的这一种。

demo3 

var a = 2;
(function IIFE() { console.log( a );
})();

demo4


(function IIFE(a) { 
console.log( a );
})(3);

demo5 

var a = (function IIFE() {
   var b=5;
   var c=6;
   var d={b,c}; 
  return d
})();

a.b // 5
a.c // 6

IIFE函数一般来说算是 大家说的闭包 ,但是作者不同意的观点,我表示同意作者的观点也不同意这种观点,

demo3 技术来讲只算是广义上的闭包;

demo4 这种拥有了自己变量和自己的专属作用域,但是在内存也就是一瞬间。所以也算不得;

demo5这种就是闭包了 为我所用并且使用了单例模式 还返回了一个对象包装API 来供我们使用这个特性。  

简单的原理就是  

我们知道引擎有垃 圾回收器用来释放不再使用的内存空间。由于看上去第一层函数的内容不会再被使用,所以很 自然地会考虑对其进行回收。

而闭包的“神奇”之处正是可以阻止这件事情的发生。事实上内部作用域依然存在,因此 没有被回收。所以可以被利用,乃至把这个特性放大去利用产生了各种神奇的效果。

简而言之: 1,符合最小授权 不污染全局变量, 2,保存 专属的独特空间为我所用。自己为自己建造了一艘豪华游艇。

闭包的应用 :模块

这个 功能就是做 插件用的最多。强大的一面开始展现; 

function CoolModule() {
var something = "cool";
var another = [1, 2, 3];
function doSomething() {
 console.log( something );
}
function doAnother() {
console.log( another.join( " ! " ) );
}
return {
doSomething: doSomething, doAnother: doAnother
}; }
var foo = CoolModule(); foo.doSomething(); // cool
     foo.doAnother(); // 1 ! 2 ! 3

一个模块有自己专属的功能和方法,最常见的实现模块模式的方法通常被称为模块暴露,专属的模块的实现方式,

这边我需要几个不同的模块 我就可以调用几次生产

加以改进: 更多的情况下 

var foo = (function CoolModule() { 
var something = "cool";
var another = [1, 2, 3];
function doSomething() { 
console.log( something );
}
function doAnother() {
console.log( another.join( " ! " ) );
}
return {
doSomething: doSomething, doAnother: doAnother
}; })();
     foo.doSomething(); // cool
     foo.doAnother(); // 1 ! 2 ! 3

单例模式的生成,往往在 项目组我们更多的插件也是 单例,IIFE 页面加载的时候自动生成一个。  

然后我们就可以开心的使用这个实例了;

更加加以改进:

var foo = (function CoolModule(id) {
        function change() {
          // 修改公共 API
             publicAPI.identify = identify2;
         }
function identify1() {
 console.log( id );
}
function identify2() {
console.log( id.toUpperCase() );
}
var publicAPI = { 
             change: change,
             identify: identify1
         };
return publicAPI; 
})( "foo module" );
     foo.identify(); // foo module
     foo.change();

我们 在最后返回的时候  给包装到一个对象 并且把这个对象 声明一个标签加以保存; 类似的 匿名函数和非匿名函数之间的好处,

这样我们就可以去拿到这个返回的 对象并且 对其内部做一些改变了,拥有更多的主动权。 

 。 

let 的 实现其实 也是一个闭包。 和块级作用域配合起来, 强的一匹。

 

模块管理 工具也是闭包的实现 。现在我们用的模块工具 都是 import 和export 所以这方面不赘述。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值