V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
gooqiao
V2EX  ›  编程

[探讨]各位大佬,你们认为这段代码有形成闭包吗?

  •  
  •   gooqiao · 2018-09-05 22:45:46 +08:00 via Android · 3002 次点击
    这是一个创建于 2301 天前的主题,其中的信息可能已经有所发展或是发生改变。
    function showHelp(help) {
    document.getElementById('help').innerHTML = help;
    }

    function setupHelp() {
    var helpText = [
    {'id': 'email', 'help': 'Your e-mail address'},
    {'id': 'name', 'help': 'Your full name'},
    {'id': 'age', 'help': 'Your age (you must be over 16)'}
    ];

    for (var i = 0; i < helpText.length; i++) {
    (function() {
    var item = helpText[i];
    document.getElementById(item.id).onfocus = function() {
    showHelp(item.help);
    }
    })(); // 马上把当前循环项的 item 与事件回调相关联起来
    }
    }

    setupHelp();


    重点在自执行函数上,这个自执行函数有形成闭包吗?
    先说说我的观点,我不认为这有形成闭包,而只是创建了一个新的函数作用域而已。
    为什么我会这么认为,我先说说我对闭包的定义:闭包必须是越过原执行环境访问到了正常情况下不能访问的对象。很明显上述代码中并没有越过原执行环境,所以不形成闭包。

    贴发出来主要是想大家一起讨论下,大家互相交流学习。欢迎大家积极表达自己的意见。
    6 条回复    2018-09-06 16:23:35 +08:00
    Lax
        1
    Lax  
       2018-09-06 01:25:18 +08:00
    那个匿名函数访问到了创建它时的环境变量 helpText。
    只要具备这种访问局部变量的能力就是个闭包。不能因为是原地执行就排除在外了,把这个函数 return 到外部调用方去执行和原地执行没有任何差别。
    Shy07
        2
    Shy07  
       2018-09-06 08:50:49 +08:00 via iPhone
    个人理解:closure 就是封闭的代码块,closure 内部可以访问所在 binding 环境,而 closure 内部环境对外是不可访问的,同时 closure 可以作为参数传递。

    至于 closure 内部可以访问到正常情况访问不到的对象不过是 closure 的一个特性和使用方法而已。你见到一只会飞的鸭子,你不能在它不飞时,就说它不是鸭子了。
    Shy07
        3
    Shy07  
       2018-09-06 08:53:42 +08:00 via iPhone
    @Shy07 立即执行函数的匿名函数部分是闭包
    robinlovemaggie
        4
    robinlovemaggie  
       2018-09-06 12:57:32 +08:00 via Android
    开包我会,闭包是真 TMD 蛋疼
    gooqiao
        5
    gooqiao  
    OP
       2018-09-06 14:35:42 +08:00 via Android
    @Shy07
    如果是这样的话,那是不是就可以认为,只要在函数内部定义的函数用到了外部函数的对象都可以被看错是闭包。
    但是这个内部函数所在的执行环境本就拥有对外部函数定义的对象的访问权限,并没有什么特殊的地方。
    这也是我之所以认为上面代码不形成闭包的原因。
    不知大佬你怎么看?
    Shy07
        6
    Shy07  
       2018-09-06 16:23:35 +08:00
    @gooqiao

    例子中的代码和下面的代码应该是等效的,看到 bind 就可以视作使用了闭包,我是这么认为的

    ```javascript
    function showHelp(help) {
    document.getElementById('help').innerHTML = help;
    }

    function setupHelp() {
    var helpText = [{
    'id': 'email',
    'help': 'Your e-mail address'
    },
    {
    'id': 'name',
    'help': 'Your full name'
    },
    {
    'id': 'age',
    'help': 'Your age (you must be over 16)'
    }
    ];

    for (var i = 0; i < helpText.length; i++) {
    var item = helpText[i];
    document.getElementById(item.id).onfocus = showHelp.bind('item', item.help);
    }
    }
    ```



    另外,**我不是大佬**
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1012 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 20:15 · PVG 04:15 · LAX 12:15 · JFK 15:15
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.