V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
nervouna
V2EX  ›  JavaScript

初学 JS,对着书上的例子做抄写员,发现一个奇怪的问题

  •  
  •   nervouna · 2013-08-03 02:48:32 +08:00 · 5345 次点击
    这是一个创建于 4131 天前的主题,其中的信息可能已经有所发展或是发生改变。
    function createFunctions(){
    var newArray = [];

    for (var i=0; i<10; i++){
    newArray[i] = function(){
    return i;
    }
    }

    return newArray;
    }

    这这个函数不是应当返回 [9, 9, 9, 9, 9, 9, 9, 9, 9, 9]吗?为啥现在返回的是:

    [function (){return i;}, function (){return i;}, function (){return i;}, function (){return i;}, function (){return i;}, function (){return i;}, function (){return i;}, function (){return i;}, function (){return i;}, function (){return i;}]

    随时做好被人发现低级错误的准备 =..=!
    第 1 条附言  ·  2013-08-04 13:18:49 +08:00
    楼主已经发现自己错了=v=
    多谢各位
    22 条回复    1970-01-01 08:00:00 +08:00
    yesmeck
        1
    yesmeck  
       2013-08-03 03:03:46 +08:00   ❤️ 1
    爲什麼是返回 [9, 9, 9, 9, 9, 9, 9, 9, 9, 9] ?
    AWSAM
        2
    AWSAM  
       2013-08-03 03:04:59 +08:00 via iPad   ❤️ 2
    没学过js
    不过看代码 你定义了一个函数然后赋值给数组中的元素 返回的当然是函数了啊
    想返回999 应该 调用 而不是 定义 函数吧
    bixuehujin
        3
    bixuehujin  
       2013-08-03 03:06:16 +08:00   ❤️ 1
    for 里面创建的函数在何处调用?


    话说 [9, 9, 9, 9, 9, 9, 9, 9, 9, 9] 的结果怎么出来的呢?
    qiayue
        4
    qiayue  
       2013-08-03 03:07:15 +08:00   ❤️ 1
    你再仔细一句一句看看代码,返回没错,你自己理解错了
    bixuehujin
        5
    bixuehujin  
       2013-08-03 03:08:37 +08:00
    如何函数没有写错的话,结果正确无疑。
    nervouna
        6
    nervouna  
    OP
       2013-08-03 03:19:11 +08:00
    是的,我自己理解错了,深夜脑子秀逗了。感谢楼上几位……

    正确的姿势是再调用一下返回数组里的某个项。

    而且返回的数组里的函数,返回的值其实应当是 10

    @yesmeck
    @AWSAM
    @bixuehujin
    @qiayue
    utom
        7
    utom  
       2013-08-03 03:29:32 +08:00   ❤️ 1
    function createFunctions(){
    var newArray = [];
    for (var i=0; i<10; i++){
    newArray[i] = function(){
    return i;
    }();
    }
    return newArray;
    }

    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    coolicer
        8
    coolicer  
       2013-08-03 10:59:55 +08:00
    你把一个函数给一个数组,肯定全都是函数。
    coolicer
        9
    coolicer  
       2013-08-03 11:00:21 +08:00   ❤️ 1
    JS讨论可以找我,我也是JS爱好者。
    utom
        10
    utom  
       2013-08-03 22:53:42 +08:00   ❤️ 1
    newArray[i] = function(){ return i; }(); 后面括号立即执行~
    linkgod
        11
    linkgod  
       2013-08-03 23:20:00 +08:00   ❤️ 1
    第一,就算如LZ所愿,也不会反回 [9, 9, 9, 9, 9, 9, 9, 9, 9, 9],应该是返回 [10, 10, 10, 10, 10, 10, 10, 10, 10, 10]

    第二,回到js语言上来看,在执行到

    ```
    newArray[i] = function(){
    return i;
    }
    ```

    这个函数并没有立即执行,应该是

    ```
    newArray[i] = (function(){
    return i;
    })();
    ```
    这样才对,就得到[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    PotatoBrother
        12
    PotatoBrother  
       2013-08-04 10:52:10 +08:00 via iPhone   ❤️ 1
    应该是楼主错了,不是程序错了
    cave
        13
    cave  
       2013-08-04 12:12:15 +08:00   ❤️ 1
    为什么不是 [function (){return 0;}, function (){return 1;}, function (){return 2;}, function (){return 3;}, function (){return 4;}, ...]
    linkgod
        14
    linkgod  
       2013-08-04 13:25:09 +08:00
    @cave 因为这里是始终访问的createFunctions作用域里面的i
    cave
        15
    cave  
       2013-08-04 13:43:22 +08:00
    @linkgod 但是createFunctions自己的作用域里面并没有定义i
    linkgod
        16
    linkgod  
       2013-08-04 14:17:18 +08:00
    @cave 有呀!你注意看那个for循环,i就是在那定义的。
    cave
        17
    cave  
       2013-08-04 15:23:17 +08:00
    说错了,是匿名函数里面没定义i
    viger
        18
    viger  
       2013-08-05 16:41:11 +08:00   ❤️ 3
    1, 首先楼主在赋值给数组元素的是一个函数对象,而不是函数的结果。所以你运行后打印出的结果肯定是函数体。
    2,当你再次执行这些数组元素的函数对象时结果肯定是[10,10,10...10],为什么不是[9,9,9...9呢],其实这个要从javascript这种语言的特性说起。简单的说是其变量作用域的问题。一般强类型语言变量i的作用域只在循环内部可访问。JS不是。你可以在console中执行for(var j =0;j<10;j++);console.log(j);结果显示的是10,而不是undefined.
    3,楼上的朋友说在函数后面加上()即可马上执行函数,建议是(function(){})()这样写比较好;随便楼主可以google下JS闭包。
    4,注意变量申明时一定要var一下。如果没有,JS默认此变量是全局变量。

    @cave 匿名函数虽然没有定义i,但是JS的特性是该作用域内没有的自动从其父作用域中寻找变量。这个无需担心。当然有时候也会造成很多奇怪的错误,好的做法是即使var变量。
    nervouna
        19
    nervouna  
    OP
       2013-08-05 16:55:42 +08:00
    @viger 是的,我就是在看书的时候看到闭包,对着书上一个「错误做法」的例子做实验,发现这个问题的。
    otakustay
        20
    otakustay  
       2013-08-05 18:26:27 +08:00
    为什么所有玩js的都喜欢主动去踩一下这个坑- -
    FrankFang128
        21
    FrankFang128  
       2013-08-05 18:32:53 +08:00
    这不是坑。
    不理解的地方就应该多试试。
    mrhooray
        22
    mrhooray  
       2013-08-06 12:55:18 +08:00
    @viger 貌似大多数语言都有你说的这个js特性。。。感觉应该是js只有global scope和function的local scope,没有一般语言的lexical scope

    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Values,_variables,_and_literals#Variable_scope
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1862 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 16:19 · PVG 00:19 · LAX 08:19 · JFK 11:19
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.