javascript中奇怪的变量作用域
Strange variable scope in javascript
所以我用javascript写了这段代码:
// Additional initialization code such as adding Event Listeners goes here
FB.api('593959083958735/albums', function(response) {
if(!response || response.error) {
// render error
alert("Noo!!");
} else {
// render photos
for(i=0; i<response.data.length; i++){
var albumName = response.data[i].name;
var albumCover = response.data[i].cover_photo;
var albumId = response.data[i].id;
console.log(albumName);
FB.api( albumCover, function(response) {
if(!response || response.error) {
// render error
alert("Noo!!");
} else {
// render photos
$("ul").append('<li>'+
'<a href="testFile.HTML" data-transition="slidedown">'+
'<img src= "' + response.picture + '" />'+
'<h2>' + albumName + '</h2>'+
'<p> Test Paragraph</p>'+
'</a>'+
'</li>')
.listview('refresh');
}
});
}
}
});
我使用facebook javascript API,将facebook页面的相册导入到我的jquery移动页面,并将它们放在listView中。如你所见,我是动态创建listView的。listView的缩略图是相册的封面照片和标题,相册的名称。
然而,这里有些可怕的错误。上面代码的结果可以在这里看到
缩略图都是正确的,但专辑名称是错误的。在每个单元格中,我得到最后一个专辑名。当我console.log(albumName)在我的代码,如你所见,我得到所有的名称正确。但在给FB的第二个电话里。api: "albumName"
变量只保存最后一个专辑名。
你知道这是怎么回事吗?
看起来你有著名的i for循环问题,你只有一个对i的引用。
for (var i = 0; i < response.data.length; i++) { //added the var here
(function (i) { //created a function
var albumName = response.data[i].name;
var albumCover = response.data[i].cover_photo;
var albumId = response.data[i].id;
console.log(albumName);
FB.api(albumCover, function (response) {
if (!response || response.error) {
// render error
alert("Noo!!");
} else {
// render photos
$("ul").append('<li>' +
'<a href="testFile.HTML" data-transition="slidedown">' +
'<img src= "' + response.picture + '" />' +
'<h2>' + albumName + '</h2>' +
'<p> Test Paragraph</p>' +
'</a>' +
'</li>')
.listview('refresh');
}
});
})(i); //call the function with i
}
问题不在于i
,而在于albumName
。
大多数JavaScript引擎都非常宽容,允许您多次使用var
关键字声明相同的变量。这就是你在这里做的事。需要注意的是,for
关键字并没有引入新的作用域;因此,当您(重新)声明循环中的每个变量(albumName
, albumCover
和albumId
)时,您将覆盖先前存储在同一变量中的值。
这会给您带来麻烦,因为您传递给FB.api
的回调关闭了这些局部变量,并且(显然)异步执行。当回调实际运行时,for
循环已经完成,这些变量都被设置为它们的最后一个值。
albumCover
,正如您已经观察到的(您说缩略图都是正确的)。这是因为您将此值同步传递给FB.api
;也就是说,你在循环中传递,所以它不会被关闭。
要更好地理解JavaScript中的闭包,请参见JavaScript闭包是如何工作的?
要明确的是:epascarello的回答应该能帮你解决问题。将逻辑包装在匿名函数中确实引入了一个新的作用域(一个可以在各种场景中使用的有用技巧),因此albumName
等的值对于每个回调都是不同的。我只是想指出,这不是i
本身造成的问题(因为你的回调不关闭i
在所有)。
- 带有KendoUI组件的Javascript变量作用域
- Javascript变量作用域:从回调函数中提取变量
- 使用JavaScript回调函数了解变量作用域和闭包
- jquery.post和变量作用域
- 变量作用域:在函数之间传递的名称
- 在 AJAX 和 Javascript 中使用变量和变量作用域
- 节点.js/express.js中的变量作用域
- jquery ajax 回调变量作用域(为什么有些在作用域中,而另一些则不在作用域中)
- JavaScript 中的变量作用域
- ajax GET 和 POST 中的变量作用域
- Javascript:变量作用域和全局变量的弊端
- Javascript 自执行函数和变量作用域
- 拼接上的Javascript全局变量作用域/覆盖
- 在Node中与jsdom和jquery共享变量作用域
- NodeJS:代码优化和变量作用域
- Javascript数组变量作用域
- AngularJS ng控制器指令不接受javascript中的变量(作用域函数),也不给出任何错误
- 回调函数中的变量作用域呢
- JavaScript/jQuery变量作用域导致错误
- AJAX变量作用域