资讯专栏INFORMATION COLUMN

hello,闭包

tulayang / 3213人阅读

摘要:由于闭包函数是由调用的,所以一般它的指向。因为闭包记住了它定义时候的作用域呀,这个时候的是块级的,能够好好地保存起来被闭包函数使用。

定义

当函数可以记住并访问它定义时候的作用域,就产生了闭包。也就是说,一个函数在另外一个函数里面定义,但是它执行的时候,可能是在其他的作用域,但是它还是能够凭着出生时的回忆,找到定义时的作用域,去访问里面的变量。

    function foo() {
        var a = 2;
        function bar() {
            console.log(a)
        }
        return bar;
    }
    
    var bar = foo();
    bar();//记住了定义时的作用域,所以还是可以访问到a,这里会输出2

为什么能够访问到定义时候的作用域呢?答案只有一个,定义闭包的函数是个重情义的家伙,考虑到那个宝宝可能随时要用到它里面的变量,都不肯被回收。没错,这样会导致foo的作用域一直没有被回收,有一点浪费内存空间。

关于this对象

一般函数的this指向的是调用它的对象。由于闭包函数是由window调用的,所以一般它的this指向window。如果你需要让它指向某个对象,可以用call或者把外部的this保存起来,在里面直接使用。

    var name = "window";
    var object = {
        name: "My Object",
        //var that = this;
        getNameFunc: function() {
            return function() {
                console.log(this.name);
                //console.log(that.name);
            }
        }
    }
    
    object.getNameFunc()();//输出"window"
    object.getNameFunc().call(object);//输出"My Object"
循环和闭包

很常见的一段代码,运行结果就是输出5个5。因为这里的i没有块级作用域,也就是说闭包里面的函数访问到外部的变量i只有一个,加上setTimeout是异步的,执行到里面的回调的时候,外面的这个i的值就是循环结束后的值5。

    for(var i = 0; i < 5; i++) {
        setTimeout(function() {
            console.log(i);
        }, 1000)
    }

在没有let的时候,我们都是通过模仿块级作用域来解决。这个时候,闭包函数定义的作用域变成了(function(){}),然后在这个作用域里面把i的值赋值给j,每个闭包函数访问到的j就是它定义时候作用域已经保存好了的,自然就能够正确的输出。

     for(var i = 0; i < 5; i++) {
         (function() {
            var j = i;
            setTimeout(function() {//闭包
                console.log(j);
            }, 1000)
         })()
    }

当然,我们一般都舍不得再用一个j来保存,直接用传参数的形式,让块级作用域可以访问到i的值。

     for(var i = 0; i < 5; i++) {
         (function(j) {
            setTimeout(function() {//闭包
                console.log(j);
            }, 1000)
         })(i)
    }

简单改一下,每次用个块级作用域的let来保存一下是不是就可以了啊

    for(var i = 0; i < 5; i++) {
        let j = i;
        setTimeout(function() {
            console.log(j);
        }, 1000)
    }

哈哈哈,真的就输出0 1 2 3 4 5了。因为闭包记住了它定义时候的作用域呀,这个时候的j是块级的,能够好好地保存起来被闭包函数使用。
其实就是相当于每次循环都会去声明一个j,然后这个j的作用域就属于这次循环,所以可以直接把j的赋值写在for循环里。

    for(let j = 0; i < 5; i++) {
        setTimeout(function() {
            console.log(j);
        }, 1000)
    }
模块化

可以使用闭包来实现模块化的。

    var module = (function(window) {
        function test1() {
        }
        functon test2() {
        }
        
        return {
            test1: test1,
            test2: test2
        }
    })(window)

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/95393.html

相关文章

  • 说说Python中的闭包 - Closure

    摘要:闭包可以用来在一个函数与一组私有变量之间创建关联关系。夹带私货外部变量返回的是函数,带私货的函数支持将函数当成对象使用的编程语言,一般都支持闭包。所以说当你的装饰器需要自定义参数时,一般都会形成闭包。 Python中的闭包不是一个一说就能明白的概念,但是随着你往学习的深入,无论如何你都需要去了解这么一个东西。 闭包的概念 我们尝试从概念上去理解一下闭包。 在一些语言中,在函数中可以(嵌...

    leon 评论0 收藏0
  • 闭包,又见闭包。。。。?

    摘要:完美的闭包,对,闭包就这么简单。这仅仅是闭包的一部分,闭包利用函数作用域达到了访问外层变量的目的。此时一个完整的闭包实现了,的垃圾回收机制由于闭包的存在无法销毁变量。 1.闭包是指有权访问另一个函数作用域中的变量的函数。 上面这段话来自 javascript 高级程序设计 第三版 P178 。作者说闭包是一个函数,它有访问另一个函数作用域中的变量的能力。 2.函数访问它被创建时所处的...

    keelii 评论0 收藏0
  • Python Closure

    摘要:在计算机科学中,闭包又称词法闭包或函数闭包,是引用了自由变量的函数。闭包被广泛应用于函数式语言中。运用闭包可以避免对全局变量的使用。将栈顶的元素取出,创建元组,并将该元组进栈。 在计算机科学中,闭包 又称 词法闭包 或 函数闭包,是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。闭包被广泛应用于函数式语言中。 从上面这段话中可以看出闭...

    n7then 评论0 收藏0
  • JavaScript闭包

    摘要:朋友,这就是闭包的效果。那么函数就是一个闭包,它可以在作用域外被访问。封闭函数必须返回至少一个内部函数,这样内部函数才能在私有作用域中形成闭包,并且可以访问或者修改私有的状态。的模块机制中为模块增加了一级语法支持。 闭包 闭包是什么? 当函数可以记住并访问所在的词法作用域时,就产生了闭包,即使函数是在当前词法作用域之外执行,简单上讲,就是在一个函数中内部的函数。 function fo...

    bluesky 评论0 收藏0
  • PHP 闭包那些事儿

    摘要:注理论上讲闭包和匿名函数是不同的概念,不过将其视作相同的概念。匿名函数可以从父作用域继承变量,而这个父作用域是定义该闭包的函数不一定是调用它的函数。 匿名函数 匿名函数,也叫闭包函数,说白了就是没有名字的函数,和一般函数结构一样,只是少了函数名以及最后需要加上分号;。 注:理论上讲闭包和匿名函数是不同的概念,不过PHP将其视作相同的概念。 $func = function() { ...

    winterdawn 评论0 收藏0
  • 通过示例学习JavaScript闭包

    摘要:译者按在上一篇博客,我们通过实现一个计数器,了解了如何使用闭包,这篇博客将提供一些代码示例,帮助大家理解闭包。然而,如果通过代码示例去理解闭包,则简单很多。不过,将闭包简单地看做局部变量,理解起来会更加简单。 - 译者按: 在上一篇博客,我们通过实现一个计数器,了解了如何使用闭包(Closure),这篇博客将提供一些代码示例,帮助大家理解闭包。 原文: JavaScript Clos...

    xingpingz 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<