WEB学习进阶之路四
【摘要】 本次学习JS中的一个特性闭包什么是闭包:函数和其周围状态的引用捆绑在一起构成闭包,通俗点说,闭包就是让你可以访问外部函数的作用域。在javascript中,当函数被创建,就会在函数生成时形成闭包。如下面的例子:<script>//例子1var foo;function bar(){ console.log(foo);}//例子2function foobar(){ ...
本次学习JS中的一个特性"闭包"
什么是闭包:
函数和其周围状态的引用捆绑在一起构成闭包,通俗点说,闭包就是让你可以访问外部函数的作用域。
在javascript中,当函数被创建,就会在函数生成时形成闭包。如下面的例子:
<script> //例子1 var foo; function bar() { console.log(foo); } //例子2 function foobar() { var innerVar; var fn = function(){ console.log(innerVar); } return fn; } </script>
以上两种都算闭包,不过第二种才是本文的重点
应用场景有哪些:
计数器
function counter() { var count = 0; return function(){ count += 1; console.log(count); } } var count1 = counter(); var count2 = counter(); var count3 = counter();
用于封装时,提供对内部变量的访问
var person = function(){ var name="中国"; return { getName:function(){ return name; }, setName:function(value){ name = value; } } }; var foo = new person(); //foo.setName('hello'); console.log(foo.getName());
这种场景一般用在创作独立插件时,避免和其他插件的变量冲突,或者污染全局变量
实现单例模式,其他缓存场景
var singleton = function () { var cache = {}; return { getObj: function(obj) { if (obj in cache) { return cache[obj]; } var newObj = new Date(); cache[obj] = newObj; return newObj; }, getCache: function() { return cache; } } }; var obj = new singleton(); obj.getObj('date')); obj.getCache();
当我们要重复去new一个对象,或者执行一些很耗时的逻辑时,使用此方法,能提供飞跃般的性能
匿名自执行函数
(function(num){ var x = 10; console.log(x + num); })(5);
他的优势就是不需要维护其中的变量,执行一次后自动释放,不污染全局变量
实现面向对象编程
和其他语言不一样,js是通过闭包模拟的面向对象过程,各个实例之间互不干扰,其实上面的几个例子都已经设计到了这块知识点。
比如稍微改造下“计数器”场景,就很明显知道这个场景的使用方法了
function counter() { var count = 0; return function(){ count += 1; console.log(count); } } var count1 = new counter(); var count2 = new counter(); var count3 = new counter();
可以看到,count1, count2, count3三个计数器相互不干扰。
代替递归函数
比如实现斐波那契
function fb(num) { if (1 == num || 2 == num) { return 1; } else { return fb(num-1) + fb(num-2) } }
如果使用上面的方法,在fb的对象被销毁的时候,再去调用就会报错
var foo = fb;
fb = null;
console.log(foo(3)); //这里就报错了
使用callee改造下
function fb(num) { if (1 == num || 2 == num) { return 1; } else { return arguments.callee(num-1) + arguments.callee(num-2) } }
这样在销毁对象之后,在调用就不会出错,但是当使用use strict模式时,arguments.callee是不支持的,这个时候使用闭包实现就是最安全的了
var fb = function(){ let cache = [0, 1]; let fib = function(n) { if (cache[n] == undefined) { cache[n] = fib(n-1) + fib(n-2); } return cache[n]; } return fib; }(); console.log(fb(10));
当然,闭包有那么多好处,是否可以在代码里面多用呢,不是的,闭包容易造成性能问题,也容易造成内存过多的消耗,甚至在某些旧版浏览器产生内存泄露。
比如我们经常这样写:
function foobar() { this.name = 'huawei mate 30'; this.price = '5000'; this.getName = function(){ return this.name; }; this.getPrice = function(){ return this.price; } } //上面这段代码就是使用了闭包,但是我们并没有想使用闭包或者没有闭包的作用,那么我们就可以改造下,这样实现: function foobar() { this.name = 'huawei mate 30'; this.price = '5000'; } foobar.prototype.getName = function(){ return this.name; } foobar.prototype.getPrice = function(){ return this.price; }
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)