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

2013-08-03 02:48:32 +08:00
 nervouna
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;}]

随时做好被人发现低级错误的准备 =..=!
5179 次点击
所在节点    JavaScript
22 条回复
yesmeck
2013-08-03 03:03:46 +08:00
爲什麼是返回 [9, 9, 9, 9, 9, 9, 9, 9, 9, 9] ?
AWSAM
2013-08-03 03:04:59 +08:00
没学过js
不过看代码 你定义了一个函数然后赋值给数组中的元素 返回的当然是函数了啊
想返回999 应该 调用 而不是 定义 函数吧
bixuehujin
2013-08-03 03:06:16 +08:00
for 里面创建的函数在何处调用?


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

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

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

@yesmeck
@AWSAM
@bixuehujin
@qiayue
utom
2013-08-03 03:29:32 +08:00
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
2013-08-03 10:59:55 +08:00
你把一个函数给一个数组,肯定全都是函数。
coolicer
2013-08-03 11:00:21 +08:00
JS讨论可以找我,我也是JS爱好者。
utom
2013-08-03 22:53:42 +08:00
newArray[i] = function(){ return i; }(); 后面括号立即执行~
linkgod
2013-08-03 23:20:00 +08:00
第一,就算如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
2013-08-04 10:52:10 +08:00
应该是楼主错了,不是程序错了
cave
2013-08-04 12:12:15 +08:00
为什么不是 [function (){return 0;}, function (){return 1;}, function (){return 2;}, function (){return 3;}, function (){return 4;}, ...]
linkgod
2013-08-04 13:25:09 +08:00
@cave 因为这里是始终访问的createFunctions作用域里面的i
cave
2013-08-04 13:43:22 +08:00
@linkgod 但是createFunctions自己的作用域里面并没有定义i
linkgod
2013-08-04 14:17:18 +08:00
@cave 有呀!你注意看那个for循环,i就是在那定义的。
cave
2013-08-04 15:23:17 +08:00
说错了,是匿名函数里面没定义i
viger
2013-08-05 16:41:11 +08:00
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
2013-08-05 16:55:42 +08:00
@viger 是的,我就是在看书的时候看到闭包,对着书上一个「错误做法」的例子做实验,发现这个问题的。
otakustay
2013-08-05 18:26:27 +08:00
为什么所有玩js的都喜欢主动去踩一下这个坑- -

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/77831

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX