WEB学习进阶之路四

举报
sujrexia 发表于 2020/06/23 19:42:21 2020/06/23
【摘要】 本次学习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

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。