V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
aliehuhu
V2EX  ›  Python

有熟悉 js 的大神么?一个 var 命令疑问

  •  
  •   aliehuhu · 2017-08-27 10:50:36 +08:00 · 5897 次点击
    这是一个创建于 2676 天前的主题,其中的信息可能已经有所发展或是发生改变。
    <div class="box" id="a1"></div>
    <div class="box" id="a2"></div>
    <script type="text/javascript">
    var a=[],b=[];
    for(var i=0;i<10;i++){
    a[i] = function(){
    document.getElementById('a1').innerHTML = i;
    };
    b[i] = i;
    }
    a[6]();
    document.getElementById('a2').innerHTML = b[6];
    </script>

    为什么 a[6]() 输出结果是 10,而 b[6]输出结果是 6 ?
    32 条回复    2017-08-28 18:00:30 +08:00
    wwqgtxx
        1
    wwqgtxx  
       2017-08-27 10:55:04 +08:00
    因为闭包
    ClassicOldSong
        2
    ClassicOldSong  
       2017-08-27 10:55:49 +08:00 via Android
    典型的闭包问题
    we2ex
        3
    we2ex  
       2017-08-27 11:26:55 +08:00
    从 ES6 就不建议用 var 了,用 let 吧
    SuperMild
        4
    SuperMild  
       2017-08-27 11:31:49 +08:00
    用 let。
    在 js 节点右侧栏有个优秀的闭包教程 /go/js
    addywu
        5
    addywu  
       2017-08-27 11:31:56 +08:00 via Android
    var 作用域
    klesh
        6
    klesh  
       2017-08-27 11:32:18 +08:00 via Android   ❤️ 1
    a[i] = (function (ii){
    return function (){
    document.get... = ii;
    };
    })(i);
    Parabolazz
        7
    Parabolazz  
       2017-08-27 11:36:04 +08:00
    搜索一下 js 闭包
    crystom
        8
    crystom  
       2017-08-27 11:38:41 +08:00
    相当于 var i 是在外面定义的
    aliehuhu
        9
    aliehuhu  
    OP
       2017-08-27 11:53:06 +08:00
    @klesh 看了你这个明白了
    asdf123101
        10
    asdf123101  
       2017-08-27 11:54:21 +08:00 via Android
    楼上都说完了不知道该说什么。典型闭包的问题,MDN 上 let 词条里面有例子和解释。
    xrr2016
        11
    xrr2016  
       2017-08-27 12:10:10 +08:00
    因为运行 `a[6]()` 的时候变量 i 是 10
    qq12345454
        12
    qq12345454  
       2017-08-27 12:24:51 +08:00
    用 let 或者 const
    deepkolos
        13
    deepkolos  
       2017-08-27 12:59:34 +08:00
    for 循环结束之后 i 的值为 10
    autoxbc
        14
    autoxbc  
       2017-08-27 14:02:29 +08:00 via iPhone   ❤️ 1
    这是求值时机问题,是无形参函数从作用域链检索变量问题

    直接说闭包问题,显然是给出了解决方法,却回避了问题自身
    siteshen
        15
    siteshen  
       2017-08-27 14:24:23 +08:00   ❤️ 1
    我就想歪楼问下为啥发在 python 节点
    magicdawn
        16
    magicdawn  
       2017-08-27 14:37:46 +08:00
    aliehuhu
        17
    aliehuhu  
    OP
       2017-08-27 18:18:22 +08:00
    @siteshen 顶部导航点节点,没找到 js 节点,再看了看 Python 板块,感觉人要多些,就发这里了。
    aliehuhu
        18
    aliehuhu  
    OP
       2017-08-27 18:26:49 +08:00
    @autoxbc 就是不明白为什么 b[i]可以得到“当时 i 的值”,而 a[i]只能得到“调用时候 i 的值”。
    kotokz
        19
    kotokz  
       2017-08-27 20:00:07 +08:00
    这些都是 javascript 的坑,尽量用 let
    POPOEVER
        20
    POPOEVER  
       2017-08-27 20:14:51 +08:00
    看你的意图你该在 function 里把 i 传进去呗,直接拿全局 i 当然就是 for 结束后的 10 喽
    autoxbc
        21
    autoxbc  
       2017-08-27 23:22:05 +08:00   ❤️ 1
    @aliehuhu #18

    a[i] 被赋值为函数表达式,也就是函数对象。

    函数对象只能记录自己在定义时的作用域链,不能记录在定义时作用域链上的变量的瞬时值。

    函数引用的变量的值,要在函数被调用时再去读取。
    FrankFang128
        22
    FrankFang128  
       2017-08-27 23:57:04 +08:00
    跟闭包有毛关系?
    原因是执行时机。你把 a[6]() 提前执行不就是 6/7/8/9 了吗?
    服了上面一群说闭包的。
    FrankFang128
        23
    FrankFang128  
       2017-08-27 23:57:46 +08:00
    @autoxbc 所以我说 V2 上面大部分自称前端的都很水。
    lhstock
        24
    lhstock  
       2017-08-28 00:00:47 +08:00
    额,楼上的所有人。我想说。作用域你妹啊。
    > document.getElementById('a1').innerHTML = i; //给此元素内容写入 i

    循环完了当然是 10 ;
    还有
    @aliehuhu
    a[6]()输出结果为 10 这个说法不对。输出是 undefined ;写入的是 10
    lhstock
        25
    lhstock  
       2017-08-28 00:01:30 +08:00
    @FrankFang128 握爪
    FrankFang128
        26
    FrankFang128  
       2017-08-28 00:04:04 +08:00   ❤️ 1
    另外,说闭包的人其实说的是「立即执行函数」,这些人把「立即执行函数」称为「闭包」而不自知。
    xman99
        27
    xman99  
       2017-08-28 09:44:21 +08:00
    b(6) 已经是调用函数了, 没问题啊
    iWtbAbh
        28
    iWtbAbh  
       2017-08-28 09:54:45 +08:00
    @aliehuhu 别被误导。
    @lhstock 与其去猜,加上 debugger 在浏览器里跑一遍,就知道了。
    lhstock
        29
    lhstock  
       2017-08-28 12:00:05 +08:00
    @iWtbAbh 你在猜啊。那闭嘴吧
    iWtbAbh
        30
    iWtbAbh  
       2017-08-28 15:08:29 +08:00
    @lhstock 嗨呦,我选择说话就是错了, 毕竟 v2 大佬多。

    虽然被你恶心到了,但我为自己说的话负责。

    "输出是 undefined ;写入的是 10"

    避免误导别人,这是过程,就花了不到一分钟

    ![]( )

    在执行 a[6] () 前 i 已经被赋值了,哪来 undefined ?你能给我看看证据么,万分感谢。

    不然我说猜的有错?
    lhstock
        31
    lhstock  
       2017-08-28 17:17:18 +08:00
    @iWtbAbh
    提问原话为:“为什么 a[6]() 输出结果是 10,而 b[6]输出结果是 6 ?”
    我理解为:console.log(a[6]());console.log(b[6]);

    被赋值的是 a[6];
    而 a[6]=Fun ;

    没有返回值;自然是 undefined ;
    不然换个说法 a[6]是个方法;方法哪有值;
    有错么;
    你要不服你把代码 56 行替换为'''console.log(a[6]() '''好吧;
    基本概念理解有误导致描述有误;
    无脑喷什么
    iWtbAbh
        32
    iWtbAbh  
       2017-08-28 18:00:30 +08:00
    @lhstock 不好意思,是我理解错了。

    a[6]() 没有 return , 默认返回 undefined。

    而我把楼主问的问题加了自己主观的理解, 理解成输出结果的是 i 。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3887 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 05:13 · PVG 13:13 · LAX 21:13 · JFK 00:13
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.